Recent

Author Topic: TMemo's empty last line  (Read 11871 times)

lagprogramming

  • Full Member
  • ***
  • Posts: 159
TMemo's empty last line
« on: June 19, 2015, 11:07:48 am »
   Why was TMemo designed to append an additional empty line at the end?

Leledumbo

  • Hero Member
  • *****
  • Posts: 8307
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: TMemo's empty last line
« Reply #1 on: June 19, 2015, 03:03:18 pm »
   Why was TMemo designed to append an additional empty line at the end?
I guess it's because its backend, which is a TStrings descendant, behaves that way.

lagprogramming

  • Full Member
  • ***
  • Posts: 159
Re: TMemo's empty last line
« Reply #2 on: July 08, 2015, 03:14:24 pm »
What's Delphi's behaviour? Does it add an empty line at the end?

typo

  • Hero Member
  • *****
  • Posts: 3051
Re: TMemo's empty last line
« Reply #3 on: July 08, 2015, 03:16:57 pm »
Yes.

Graeme

  • Hero Member
  • *****
  • Posts: 1431
    • Graeme on the web
Re: TMemo's empty last line
« Reply #4 on: July 11, 2015, 07:10:29 pm »
   Why was TMemo designed to append an additional empty line at the end?
Please supply a sample program so I can see what you mean. Then I'll be able to understand what you are saying, and I'll be able to correctly under the question about fpGUI.
--
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://fpgui.sourceforge.net/

Windsurfer

  • Sr. Member
  • ****
  • Posts: 368
    • Windsurfer
Re: TMemo's empty last line
« Reply #5 on: July 11, 2015, 08:03:34 pm »
When a single TMemo is dropped on a form, it starts with a line that says 'Memo1'. This is followed by a blank line. Every time a line is added,
Code: [Select]
Memo1.Lines.Add('New line')the blank line is pushed down.

I always assumed this was so that there was a blank line for the user to write on.

jc99

  • Hero Member
  • *****
  • Posts: 544
    • My private Site
Re: TMemo's empty last line
« Reply #6 on: July 11, 2015, 11:06:58 pm »
If anybody likes,
Here's a small test-program
Code: [Select]
unit frm_MemoEmptyLineMain;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    btnClearMemo: TButton;
    btnMemoAdd: TButton;
    btnSetText: TButton;
    btnAddText: TButton;
    btnInsertText: TButton;
    lblShowText: TLabel;
    Memo1: TMemo;
    procedure btnClearMemoClick(Sender: TObject);
    procedure btnMemoAddClick(Sender: TObject);
    procedure btnSetTextClick(Sender: TObject);
    procedure btnAddTextClick(Sender: TObject);
    procedure btnInsertTextClick(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.btnClearMemoClick(Sender: TObject);
begin
  Memo1.Clear;
  lblShowText.Caption:=''''+memo1.Text+'''';
end;

procedure TForm1.btnMemoAddClick(Sender: TObject);
begin
  memo1.lines.add('Add Testline '+ inttostr(memo1.Lines.Count));
  lblShowText.Caption:=''''+memo1.Text+'''';
end;

procedure TForm1.btnSetTextClick(Sender: TObject);
begin
  memo1.lines.Text:='This is a test'+LineEnding+
  'if there is alway an empty line'+LineEnding+
  'at the end.';
  lblShowText.Caption:=''''+memo1.Text+'''';
end;

procedure TForm1.btnAddTextClick(Sender: TObject);
begin
  memo1.lines.AddText('AddText Testline '+ inttostr(memo1.Lines.Count));
  lblShowText.Caption:=''''+memo1.Text+'''';
end;

procedure TForm1.btnInsertTextClick(Sender: TObject);
begin
  memo1.lines.Insert(0,'Insert Testline '+ inttostr(memo1.Lines.Count));
  lblShowText.Caption:=''''+memo1.Text+'''';
end;

end.
The form:
Code: [Select]
object Form1: TForm1
  Left = 207
  Height = 217
  Top = 361
  Width = 594
  Caption = 'Form1'
  ClientHeight = 217
  ClientWidth = 594
  LCLVersion = '1.4.0.4'
  object Memo1: TMemo
    Left = 0
    Height = 176
    Top = 0
    Width = 320
    Lines.Strings = (
      'Memo1'
    )
    TabOrder = 0
  end
  object btnClearMemo: TButton
    Left = 8
    Height = 25
    Top = 184
    Width = 75
    Caption = 'Clear'
    OnClick = btnClearMemoClick
    TabOrder = 1
  end
  object btnMemoAdd: TButton
    Left = 92
    Height = 25
    Top = 184
    Width = 75
    Caption = 'Add'
    OnClick = btnMemoAddClick
    TabOrder = 2
  end
  object btnSetText: TButton
    Left = 176
    Height = 25
    Top = 184
    Width = 75
    Caption = 'set Text'
    OnClick = btnSetTextClick
    TabOrder = 3
  end
  object btnAddText: TButton
    Left = 256
    Height = 25
    Top = 184
    Width = 75
    Caption = 'AddText'
    OnClick = btnAddTextClick
    TabOrder = 4
  end
  object btnInsertText: TButton
    Left = 336
    Height = 25
    Top = 184
    Width = 75
    Caption = 'Insert'
    OnClick = btnInsertTextClick
    TabOrder = 5
  end
  object lblShowText: TLabel
    Left = 325
    Height = 15
    Top = 8
    Width = 64
    Caption = 'lblShowText'
    ParentColor = False
  end
end
The only way not to have an empty line, is to set the .text property directly.
OS: Win XP x64, Win 7, Win 7 x64, Win 10, Win 10 x64, Suse Linux 13.2
Laz: 1.4 - 1.8.4, 2.0
https://github.com/joecare99/public
'~|    /''
,_|oe \_,are
If you want to do something for the environment: Twitter: #reduceCO2 or
https://www.betterplace.me/klimawandel-stoppen-co-ueber-preis-reduzieren

eny

  • Hero Member
  • *****
  • Posts: 1617
Re: TMemo's empty last line
« Reply #7 on: July 12, 2015, 01:41:44 am »
When a single TMemo is dropped on a form, it starts with a line that says 'Memo1'. This is followed by a blank line. Every time a line is added,
Code: [Select]
Memo1.Lines.Add('New line')the blank line is pushed down.
It's a matter of definition.
If you were to check Memo.Lines.Count it would return 1, which is correct. There is no 2nd ('blank') line.
However by default each line is displayed ending with a line ending character/characters (platform dependant constant 'LineEnding').
So the cursor in the TMemo component can be positioned just after the text of the first line (including the LineEnding), which is on line 2.
That second line is not part of the memo text.

The only way not to have an empty line, is to set the .text property directly.
True; this is the confusing part.
If you do this:
Code: [Select]
Memo1.Lines.Text := 'One line'... then the cursor can not be placed beyond the end of the first line as there is no LineEnding (yet).
If you then in turn do "Memo1.Lines.Add('New line')" this is restored and line 1 ánd line 2 will have a LineEnding at the end and you can position the cursor on line 3 (which in turn is not part of the actual Memo text...).
« Last Edit: July 12, 2015, 01:43:24 am by eny »
All posts based on: Win10 (Win64); Lazarus 2.0.10 'stable' (x64) unless specified otherwise...

lagprogramming

  • Full Member
  • ***
  • Posts: 159
Re: TMemo's empty last line
« Reply #8 on: July 12, 2015, 11:01:01 am »
I've attached an example. As previously pointed by other users, I think the important thing is that
Code: [Select]
Memo.Clear;Memo.Lines.Add('Text line');will make the TMemo have two lines, the additional empty line influences the vertical scrollbar.
The user would have to scroll each TMemo on the form because he would think that additional informations appear upon scrolling the list.
Things start to become annoying when dealing with multiple TMemos vertically arranged.
For this reason I'd like to know why people chose this design. I don't see the benefits of having that empty line.

eny

  • Hero Member
  • *****
  • Posts: 1617
Re: TMemo's empty last line
« Reply #9 on: July 12, 2015, 11:25:52 am »
The user would have to scroll each TMemo on the form because he would think that additional informations appear upon scrolling the list.
Which is absolutely no problem for anybody that is used to editors or word processors in general.

If you only want to display information (no editing) simply disable the scroll bar.
Or choose a different component (listbox, virtual string list etc.).
All posts based on: Win10 (Win64); Lazarus 2.0.10 'stable' (x64) unless specified otherwise...

jc99

  • Hero Member
  • *****
  • Posts: 544
    • My private Site
Re: TMemo's empty last line
« Reply #10 on: July 12, 2015, 11:35:32 am »
I've attached an example. As previously pointed by other users, I think the important thing is that
Code: [Select]
Memo.Clear;Memo.Lines.Add('Text line');will make the TMemo have two lines, the additional empty line influences the vertical scrollbar.
The user would have to scroll each TMemo on the form because he would think that additional informations appear upon scrolling the list.
Things start to become annoying when dealing with multiple TMemos vertically arranged.
For this reason I'd like to know why people chose this design. I don't see the benefits of having that empty line.
... but that's up to you, because you can always do :
Code: [Select]
  Memo.Lines.Text := TrimRight(Memo.Lines.Text); // Get rid of the last line.
And your annoying design issue only apply when you have exactly so much lines in your memo that it fits.
But you are using a memo, meaning your user can change data, also when the form resizes your loose your design-advantage.
And if you only want to display a static text, why not use a label ?
if you want to get rid of the scrollbars use
Code: [Select]
  Memo.Scrollbars := ssNone; // Get rid of the scrollbars.

[EDIT]
@eny: +1 you've been a little faster. 
« Last Edit: July 12, 2015, 11:38:01 am by jc99 »
OS: Win XP x64, Win 7, Win 7 x64, Win 10, Win 10 x64, Suse Linux 13.2
Laz: 1.4 - 1.8.4, 2.0
https://github.com/joecare99/public
'~|    /''
,_|oe \_,are
If you want to do something for the environment: Twitter: #reduceCO2 or
https://www.betterplace.me/klimawandel-stoppen-co-ueber-preis-reduzieren

eny

  • Hero Member
  • *****
  • Posts: 1617
Re: TMemo's empty last line
« Reply #11 on: July 12, 2015, 12:40:31 pm »
@eny: +1 you've been a little faster.
I had less text to type  ;)
All posts based on: Win10 (Win64); Lazarus 2.0.10 'stable' (x64) unless specified otherwise...

lagprogramming

  • Full Member
  • ***
  • Posts: 159
Re: TMemo's empty last line
« Reply #12 on: July 12, 2015, 01:22:05 pm »
   Thank you for your recommendations but I'm still interested in why this design has been chosen. I still fail to understand the benefits of that empty line.

   Are you absolutely sure that Delphi's TMemo has two lines after executing the code:
Code: [Select]
Memo.Clear;Memo.Lines.Add('Text line');
   Reading http://bugs.freepascal.org/view.php?id=24973 it looks like I've remembered right. In the past TListBox acted the same as TMemo acts now. Why is that nowadays for a TListBox is not acceptable to have an empty line but it's acceptable for a TMemo?
   Also, could that empty line at the end have an impact on copying to clipboard processes!?

   By the way, "Memo1.Lines.Text := TrimRight(Memo1.Lines.Text);" not only slows down things but also removes all [#0..' '] characters. This means all empty lines at the end, space only lines, and who knows what else... I'm not sure this workaround is usable.

   I'm still looking forward. If you have a new idea on the subject, share it here. I'm not much interested in workarounds as I'm interested in why is TMemo behaving this way.

jc99

  • Hero Member
  • *****
  • Posts: 544
    • My private Site
Re: TMemo's empty last line
« Reply #13 on: July 12, 2015, 04:09:09 pm »
[...]   Are you absolutely sure that Delphi's TMemo has two lines after executing the code:
Code: [Select]
Memo.Clear;Memo.Lines.Add('Text line');
positive !!
Two lines (one line with CRLF at the end)
With trim CRLF is gone -> one line
(Testet on DXE)
OS: Win XP x64, Win 7, Win 7 x64, Win 10, Win 10 x64, Suse Linux 13.2
Laz: 1.4 - 1.8.4, 2.0
https://github.com/joecare99/public
'~|    /''
,_|oe \_,are
If you want to do something for the environment: Twitter: #reduceCO2 or
https://www.betterplace.me/klimawandel-stoppen-co-ueber-preis-reduzieren

Graeme

  • Hero Member
  • *****
  • Posts: 1431
    • Graeme on the web
Re: TMemo's empty last line
« Reply #14 on: July 13, 2015, 10:30:55 am »
When a single TMemo is dropped on a form, it starts with a line that says 'Memo1'. This is followed by a blank line. Every time a line is added,
Code: [Select]
Memo1.Lines.Add('New line')the blank line is pushed down.

I always assumed this was so that there was a blank line for the user to write on.
No, fpGUI's TfpgMemo doesn't do that. The Lines property is completely empty, not even the silly 'Memo1' text. Here is code that the fpGUI UI Designer creates when you drop a memo on a form.

Code: [Select]
  Memo1 := TfpgMemo.Create(self);
  with Memo1 do
  begin
    Name := 'Memo1';
    SetPosition(20, 10, 225, 194);
    FontDesc := '#Edit1';
    Hint := '';
    TabOrder := 2;
  end;

If you do the following on a newly created Memo (as shown above) and execute the following code...

Code: [Select]
procedure TMainForm.ButtonClicked(Sender: TObject);
begin
  ShowMessage(IntToStr(Memo1.Lines.Count));
  Memo1.Lines.Add('new line');
  ShowMessage(IntToStr(Memo1.Lines.Count));
end;

The results would be 0 and then 1.
--
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://fpgui.sourceforge.net/

 

TinyPortal © 2005-2018