Re: [Lazarus] Code Structure / SourceEdit and SyneEdit [Re: Mouse Link in SynEdit (only link-able items)]

2008-12-18 Thread Martin Friebe
In some places below, I am unsure what you meant by component:
- the view (as in MVC)
- the overall editor (as in SynEdit)

Hans-Peter Diettrich wrote:
 Martin Friebe schrieb:
   
 Model shall contain
 - the raw text
 - bookmarks, and other marks
 - foldable secitions
 - ...

 Other information can be local to a specific Component (in case multiply 
 component display the same model in more than one window). An example 
 would be which sections are folded. This info may or may not be part of 
 the model
 

 Right. We should start with the persistent information, stored together 
 with the text on disk, then add all information that is common to all 
 (multiple) Views.
   
Serializing the Model for storage purposes (such as saving to a file or 
many files) for me comes after the decision how the model looks.

There may be more than one way to serialize the model. As there are many 
ways to use SynEdit.
- In Lazarus it is used a SourceEditor, so serializing should write the 
Text information into one file, and other information into another file.
- In User Applications, people may wish to serialize the model into just 
one file (which can not be edited by other editors)

 We could differ between a public and a private model. (Probably not needed)
 
 Most probably not needed in this form, default is the public Model.
Actually we may need. Example folding.
Having the same model displayed in many Windows, the user may want to 
fold different nodes in each Window.
Or even use different highlighters, leading to different nodes being 
available.

The design of this must leave the choice to the user, which information 
is hold in the public, and which in the private model. The private Model 
can store the same info as the public. The private model only stores 
info the user whises to be different from the public model, all other 
info will be forwarded.

However concerning the design of the other Classes (Controller/View), 
the differentation between private or public model is not relevant. They 
access one Model. This Model knows what to do.

 Folding has to be reflected in a component, both as a structure (block 
 tree in the gutter) and as currently visible lines (for the text 
 painter), so that a helper object/class is appropriate for retrieving 
 all the information in an synchronized way. Then one instance can reside 
 in the Model, holding the shared definition of the blocks, and another 
 instance can be part of the Views, doing individual folding - that's 
 only a matter of how a new View is initialized.
   
Ack
 View.Folding := Model.Folding; //object reference
 if FoldingPerView then begin
PrivateFolding := TFoldingState.Create(View.Folding);
View.Folding := PrivateFolding;
 end;

 [This is what you would consider as pushing another item on the stack, 
 see below]
   
My implementation probably looks slightly different. There will be no 
dedicated properties (on the View) for dedicated features.

  View.Model := TheModel;
Then the View can internally distribute this. The Model can be a Private 
Model, which acts as a wrapper to the public Model.

This way it is easier to add features, without the need to change the 
way the view is set up.

 In this terms if you wish to implement new feature (which are not 
 covered by the set of existing properties), an component that inherits 
 from the original is the most likely way. This inherited component can 
 either implement the features itself, or create additional ( or 
 substitute existing) helper classes to archive the new functionality
 
 Isn't LazSynEdit such a customized version of a SynEdit?
   
yes and no. SynLazarus is a fork off, of an early Synedit. Not done by 
inheritance.
 But in the following I would like to look at the details of a Component 
 that provides the following functionality (and can be used by any 
 editor, Memo or anything else):

 A component that has:
 - a Model (was: RawSource) property
   - For ease of access an extended TStrings interface can be assumed 
 (this simplifies the case, as it already implements the text to be 
 organized into lines)
 

 ACK. UTF-8 encoding, I suppose? Access should be routed through the 
 folding object.
   
For SynEdit in Lazarus, currently UTF8. Ideally most of the code should 
be agnostic to the encoding, and the remainder exchangeable.
The design of the Classes involved most not be based on an encoding. 
(except maybe the design of the model)

   - A Tab is a normal character that does has no information about it's 
 later display properties.
   - Highlighting information is not part of the model. (Displaying the 
 same model in 2 windows can be done with different Highlighters selected)
   - Markup (such as the selected block, if any) is not part of the model
   - This Text has information where it can be folded, but is *not* yet 
 folded or wrapped
 

 Wordwrap should be implemented in the component, because it depends on
 the width of the window. Folding should 

Re: [Lazarus] Code Structure / SourceEdit and SyneEdit [Re: Mouse Link in SynEdit (only link-able items)]

2008-12-18 Thread Hans-Peter Diettrich
Martin Friebe schrieb:
 In some places below, I am unsure what you meant by component:
 - the view (as in MVC)
 - the overall editor (as in SynEdit)

Now that you mention it, I'm also unsure. I meant the implementation of 
the component, without thinking of the embedding/outsorcing of the 
controller, or whether the control should include an default controller 
for a default (new text file) data source.


 Serializing the Model for storage purposes (such as saving to a file or 
 many files) for me comes after the decision how the model looks.

But we can decide in advance, which properties are to be stored at all, 
or will have to be saved and restored when the data source (file) is 
exchanged.


 We could differ between a public and a private model. (Probably not needed)
 
 Most probably not needed in this form, default is the public Model.
 Actually we may need. Example folding.
 Having the same model displayed in many Windows, the user may want to 
 fold different nodes in each Window.
 Or even use different highlighters, leading to different nodes being 
 available.

All that IMO is configurable, using according stacks. The component code 
uses a given helper object, without knowing whether it's private or shared.

 The design of this must leave the choice to the user, which information 
 is hold in the public, and which in the private model. The private Model 
 can store the same info as the public. The private model only stores 
 info the user whises to be different from the public model, all other 
 info will be forwarded.

Or the private Model is independent from outside data, and all shared 
properties have to be transferred into the View, by the (application 
wide) Controller. The public Model cannot know what a View has to do, 
when settings change, so that all changes must be signaled to the Views. 
In an stack, we need an back-channel for propagating such configuration 
changes to the other end.

This may be related to what I called characteristic data. The View 
contains an set of properties, for private use, and the Model contains 
another set of shared properties. When the shared properties change, a 
single change notification is sent to each View, with the changed 
property set, and every View has to check for changes and react as 
appropriate. That's easier to implement, and doesn't leave an View in an 
inconsistent state, when one of more related settings change.

I remember FontChanged and other methods in SynEdit, which may have to 
be embedded in a wider scope, e.g. guarded by BeginChange/EndChange 
calls. All intermediate changes are stored, but are recognized only on 
the final EndChange. When all acutal changes are collected in an set of 
ChangeFlags, the receiver can know which settings actually have changed, 
and which (other) ones may deserve an according readjustment.

I already planned to open another thread, on my design for such 
synchronizations, in detail for synchronizing scrolls and caret moves.


 However concerning the design of the other Classes (Controller/View), 
 the differentation between private or public model is not relevant. They 
 access one Model. This Model knows what to do.

IMO the Model has to know nothing, except that it holds data, and 
possibly how to load/store these data in a customized class (overridden 
methods).


 View.Folding := Model.Folding; //object reference
 if FoldingPerView then begin
PrivateFolding := TFoldingState.Create(View.Folding);
View.Folding := PrivateFolding;
 end;

 [This is what you would consider as pushing another item on the stack, 
 see below]
   
 My implementation probably looks slightly different. There will be no 
 dedicated properties (on the View) for dedicated features.
   View.Model := TheModel;
 Then the View can internally distribute this. The Model can be a Private 
 Model, which acts as a wrapper to the public Model.

I should have used Self instead of View, to indicate that my code 
resides inside the View, in the View.Model property setter. Then we 
agree again, I assume?


[encoding]
 For SynEdit in Lazarus, currently UTF8. Ideally most of the code should 
 be agnostic to the encoding, and the remainder exchangeable.
 The design of the Classes involved most not be based on an encoding. 
 (except maybe the design of the model)

The data exchange between the classes IMO should use fixed data types. 
When TStrings are used, an agreement must exist whether the strings are 
Ansi or UTF-8 encoded. In the CharGrid I used WideString in the 
interface (assuming UCS-2), and left it to the Model to translate the 
string encoding, between file format, internal storage, and 
viewer/contoller interface.


 Wordwrap should be implemented in the component, because it depends on
 the width of the window. Folding should be reflected in a helper object, 
 that allows to retrieve the visible lines. In the simplest case (source 
 not foldable at all) that object does a 1:1 mapping of the unfolded lines.
   
 Which 

Re: [Lazarus] Code Structure / SourceEdit and SyneEdit [Re: Mouse Link in SynEdit (only link-able items)]

2008-12-17 Thread Martin Friebe




Hans-Peter Diettrich wrote:

  Martin Friebe schrieb:
  
  
Maybe for clarifications. I started this using the word "view". But I 
can see there are 2 ways to read this word.
- "physical view": Like a painter. The final output of the combined 
text/style information. Most common drawing it to a canvas. But it could 
be a reader too.
- "logical view": (I guess what you called the grid?). A module that 
takes the raw-text, and converts it into a structure suitable for the 
"physical view", applying style/highlight info on the way.

  
  
In the model-view-controller context, the view is the logical aspect.
  

Best to always specify the context (logical / physical ). The painter
is no separate itme in MVC, so it resides within the "View" too.

You also pointed out correctly (at the end of the mail) that
TextBuffer/lineBuffer/SourceText/etc are inappropriate names.
(Unfortunately I came to read this after I wrote most of my response)

I will revise my text to use Model instead. In cases were I overlooked
the old term, please assume it as a reference to Model.

Model shall contain
- the raw text
- bookmarks, and other marks
- foldable secitions
- ...

Other information can be local to a specific Component (in case
multiply component display the same model in more than one window). An
example would be which sections are folded. This info may or may not be
part of the model

Information like the (logical) caret position are specific to each
Component. This information is not part of the model.

We could differ between a public and a private model. (Probably not
needed)


  Let me add another clarification:

My primary viewpoint is that of an component writer, designing 
components for general use, i.e. not bound to a specific application or 
context, unless specific to the functionality of the component itself.

Consequently my CharGrid is a general component, whose use in Lazarus 
may deserve extensions to the general functionality. The basic component 
has certain capabilities, and a specific implementation. Take it both as 
a general model, and a specific implementation as a proof of the concept.
  

This should apply to both (your grid and LazSynEdit). To the user it
will present itself as one whole component. It should not expose it's
inner structure. In the case where it is implemented using a structure
of internal classes, it will act as Facade and have a single interface.

In this terms if you wish to implement new feature (which are not
covered by the set of existing properties), an component that inherits
from the original is the most likely way. This inherited component can
either implement the features itself, or create additional ( or
substitute existing) helper classes to archive the new functionality

The original class could also expose some of it helper classes (in the
same way that a data aware class depends on a data-provider), and allow
the end user to provide a class with the desired functionality. This I
believe can be discussed in implementation details.


  Now we can discuss in general, *whether* it's possible to achive the 
Lazarus-specific functionality, based on the given component design. 
This was my context in the preceding discussion. I wanted to prove that 
my approach is suitable for that specific use, and find out where the 
implementation may deserve a redesign. The result only can be go/nogo.
  

Let's try to stick to the abstracts in this part. We may open a new
subthread to this mail and discuss implementation details in parallel.
I would also try to stick to the "display/presentation" part of the
discussion here. For the edit part a new sub thread may be created?

So the below will concern itself with the View of the MVC


  

I do use the word "view" to describe the logical-view of a source-file 
transformed into a grid.
I do  not  use the word "view" to describe the painter. ( I propose 
"physical view")
I do  not  use the word "view" to describe the high level dual 
visibility of the same source-file in 2 windows (or a splitted window) ( 
I propose "user view" ?? imho a weak description, not good)

  
  When it comes to implementation details, like painting, then I'd prefer 
"component" for the overall (TLazEdit or TCharGrid) component. That 
component can consist of, or use, dedicated sub-components, wich we 
should address as text and gutter painters, syntax highlighters etc.
  

We roughly look at a component (I call it TextDrawer to avoid
confusion with the word View), that will cover the following
functionality:
- access to a model
- logical presentation of this model (folding, tabs, grid)
- painter (gutter, text area, possible others)

I believe we can leave details such as scrollbars for a higher level?
This could be done using a decorator.

[.]
[ discussion about double-display-width and multi-code-point chars ] 
Let's move it to a different thread for details. For discussing the
abstracts it should be enough to assume we have access 

Re: [Lazarus] Code Structure / SourceEdit and SyneEdit [Re: Mouse Link in SynEdit (only link-able items)]

2008-12-17 Thread Hans-Peter Diettrich
Martin Friebe schrieb:

 Model shall contain
 - the raw text
 - bookmarks, and other marks
 - foldable secitions
 - ...
 
 Other information can be local to a specific Component (in case multiply 
 component display the same model in more than one window). An example 
 would be which sections are folded. This info may or may not be part of 
 the model

Right. We should start with the persistent information, stored together 
with the text on disk, then add all information that is common to all 
(multiple) Views.

Folding has to be reflected in a component, both as a structure (block 
tree in the gutter) and as currently visible lines (for the text 
painter), so that a helper object/class is appropriate for retrieving 
all the information in an synchronized way. Then one instance can reside 
in the Model, holding the shared definition of the blocks, and another 
instance can be part of the Views, doing individual folding - that's 
only a matter of how a new View is initialized.

View.Folding := Model.Folding; //object reference
if FoldingPerView then begin
   PrivateFolding := TFoldingState.Create(View.Folding);
   View.Folding := PrivateFolding;
end;

[This is what you would consider as pushing another item on the stack, 
see below]

 Information like the (logical) caret position are specific to each 
 Component. This information is not part of the model.

ACK

 We could differ between a public and a private model. (Probably not needed)

Most probably not needed in this form, default is the public Model.


 This should apply to both (your grid and LazSynEdit). To the user it 
 will present itself as one whole component. It should not expose it's 
 inner structure. In the case where it is implemented using a structure 
 of internal classes, it will act as Facade and have a single interface.

Right, that's why I addressed the component view.

 In this terms if you wish to implement new feature (which are not 
 covered by the set of existing properties), an component that inherits 
 from the original is the most likely way. This inherited component can 
 either implement the features itself, or create additional ( or 
 substitute existing) helper classes to archive the new functionality

Isn't LazSynEdit such a customized version of a SynEdit?


 So the below will concern itself with the View of the MVC
[...]
 We roughly  look at a component (I call it TextDrawer to avoid confusion 
 with the word View), that will cover the following functionality:
 - access to a model
 - logical presentation of this model (folding, tabs, grid)
 - painter (gutter, text area, possible others)
 
 I believe we can leave details such as scrollbars for a higher level? 
 This could be done using a decorator.

Right. We now should agree about what to discuss, for what purpose.

The need for refactoring should be clear by now, when multiple edit
windows shall become possible. I should know more about editing lcl
code, so that it is at least syntax-checked in the IDE, and in the next
step how to test the modifications, perhaps with a test application, or
by rebuilding the IDE.


 [ discussion about double-display-width and multi-code-point chars ]
 [ column mode block ]
 Again we can open a thread with implementation details


 I would like to see see folded view to be part of the TextDrawer 
 (char-grid ?) component.

See above. That's only a matter of the initialization and finalization 
of the component.


 But in the following I would like to look at the details of a Component 
 that provides the following functionality (and can be used by any 
 editor, Memo or anything else):
 
 A component that has:
 - a Model (was: RawSource) property
   - For ease of access an extended TStrings interface can be assumed 
 (this simplifies the case, as it already implements the text to be 
 organized into lines)

ACK. UTF-8 encoding, I suppose? Access should be routed through the 
folding object.

   - A Tab is a normal character that does has no information about it's 
 later display properties.
   - Highlighting information is not part of the model. (Displaying the 
 same model in 2 windows can be done with different Highlighters selected)
   - Markup (such as the selected block, if any) is not part of the model
   - This Text has information where it can be folded, but is *not* yet 
 folded or wrapped

Wordwrap should be implemented in the component, because it depends on
the width of the window. Folding should be reflected in a helper object, 
that allows to retrieve the visible lines. In the simplest case (source 
not foldable at all) that object does a 1:1 mapping of the unfolded lines.


 - properties to define the ViewPort
   - The controller can change attributes such as topline or display area 
 according to the users action.
   - The component is not concerned where those changes originate from
   - (The decorated TextDrawer (with scrollbars) can send info to the 
 controller, about required Viewport changes)
 - A canvas.
   This 

Re: [Lazarus] Code Structure / SourceEdit and SyneEdit [Re: Mouse Link in SynEdit (only link-able items)]

2008-12-16 Thread Mattias Gärtner
Zitat von Hans-Peter Diettrich drdiettri...@aol.com:

 Martin Friebe schrieb:

  Then how to you handle double width chars? This si one of the problems I
  still have to address.
  Even in a proportional font, some chars (Chinese, and other) have twice
  the width of a normal char. They will 2 positions in the grid.
  Actually it is the same issue as tabs.

 Are these characters inside the Unicode BMP?

AFAIK: yes.
All chinese characters are in some fonts double wide characters.


[...]
 That's why keep both the characters and their text attributes in the
 line buffer, passed to the painter. I started with separate regions,
 describing the begin and length of tokens, selection etc., but it turned
 out that the handling of overlapping regions is accomplished easier by a
 direct mapping of the text attributes to every single character. The
 text attributes then can be used to e.g. determine, whether the mouse is
 over a (character in a) hyperlink.

What means 'text attributes to every single character'?
How much memory is needed for a 10mb text?


[...]
 One such case is the docking manager, where I still don't see a chance
 to implement an different manager separately from Controls.pp. The
 anchor docking sample in fact lacks the drag-dock functionality, because
 the implementation would require access to and modification of the
 existing code base, hidden in the implementation section of Controls.pp.
 An extraction of the hidden classes leads to circular unit references
 all over, protected methods are inaccessible from other classes etc.

The anchor docking lacks dd because my plan is: first finish the restore layout
and get manual things stable. Then implement dd. But at the moment I have other
priorities than docking.
If the dd properties/methods are not sufficient in the LCL then they can be
extended.


[...]


Mattias

___
Lazarus mailing list
Lazarus@lazarus.freepascal.org
http://www.lazarus.freepascal.org/mailman/listinfo/lazarus


Re: [Lazarus] Code Structure / SourceEdit and SyneEdit [Re: Mouse Link in SynEdit (only link-able items)]

2008-12-16 Thread Mattias Gärtner
Zitat von Hans-Peter Diettrich drdiettri...@aol.com:

 Mattias Gärtner schrieb:

  Even in a proportional font, some chars (Chinese, and other) have twice
  the width of a normal char. They will 2 positions in the grid.
  Actually it is the same issue as tabs.
  Are these characters inside the Unicode BMP?
 
  AFAIK: yes.
  All chinese characters are in some fonts double wide characters.

 What double, 4 bytes or double display width?

double display width. The font is called 'monospace' but has two different
widths. chinese characters are twice the width as the other characters in the
font.


 Double width on the display could be fixed by simply doubling their
 indicated width, if it applies to all characters in that codepage.
 Monospaced doesn't mean quadratic ;-)


 [...]
  What means 'text attributes to every single character'?
  How much memory is needed for a 10mb text?

 The text attributes only are stored in the line buffer of the line to be
 painted, nowhere else.

ok


  [...]
  The anchor docking lacks dd because my plan is: first finish the restore
  layout and get manual things stable. Then implement dd. But at the moment 
 I have other priorities than docking.

 Oh, that's you, too? :-)

Yes, the world is small.


Mattias

___
Lazarus mailing list
Lazarus@lazarus.freepascal.org
http://www.lazarus.freepascal.org/mailman/listinfo/lazarus


Re: [Lazarus] Code Structure / SourceEdit and SyneEdit [Re: Mouse Link in SynEdit (only link-able items)]

2008-12-16 Thread Martin Friebe
There are several meanings by the word view I have tried to put some 
clarification into this. Having finished this mail, I thought I copy 2 
fragments up here to the top. If they are not clear in itself, please 
read on first. And let us find a common approach to name those things


Maybe for clarifications. I started this using the word view. But I 
can see there are 2 ways to read this word.
- physical view: Like a painter. The final output of the combined 
text/style information. Most common drawing it to a canvas. But it could 
be a reader too.
- logical view: (I guess what you called the grid?). A module that 
takes the raw-text, and converts it into a structure suitable for the 
physical view, applying style/highlight info on the way.


I do use the word view to describe the logical-view of a source-file 
transformed into a grid.
I do  not  use the word view to describe the painter. ( I propose 
physical view)
I do  not  use the word view to describe the high level dual 
visibility of the same source-file in 2 windows (or a splitted window) ( 
I propose user view ?? imho a weak description, not good)


Some of the answers where given before I understood that view in your 
text sometimes refers to multi window display.  I tried to amend them 
in a 2nd run through my answer. I hope I didn't miss any. If my answers 
do not seem to match your text, I probably read view in a different way 
from what you meant


Hans-Peter Diettrich wrote:
 Martin Friebe schrieb:
   
 Then how to you handle double width chars? This si one of the problems I 
 still have to address.
 Even in a proportional font, some chars (Chinese, and other) have twice 
 the width of a normal char. They will 2 positions in the grid.
 Actually it is the same issue as tabs.
 
 Are these characters inside the Unicode BMP?
   
Yes, and there are quite a few Lazarus users waiting for a solution.
In utf16 they occupy 1 code point ( they are encoded in  a single 16 bit 
word), but need display twice the display width. Actually it seems they 
are called full width, while all others  (like western chars) are 
called half width.
 Full Unicode requires assistance by some sophisticated library, that can 
 deal with all the oddities of character sequences (ligatures...), and 
   
True, and so far we only talk about the display, it also needs to be 
edited. Anyway there is much other work before I get there, so I think I 
defer the details on this part.
 Column Blocks, as well as horizontal caret movement have to deal with 
 this anyway, since you may allow to be in the middle of a tab. But you 
 can not permit to have the caret in the middle of a chinese char.
 
 No problem, my tabs have a special display encoding, that forces the 
 caret to move to the next ordinary character cell.

 Is it really still a column block, when a double-width character hangs 
 out on it's right boundary?
   
Well it is the users option (with tabs) to either have ragged column 
blocks, or cut tabs into spaces or 
With Chinese (and I believe Arabic, and a few other language) there are 
no options (the char can not be cut).
 The question still is how do your painters to all that. IMHO the mapping 
 into a grid requires a lot of info (folded/ word wrapped/ tabs,...) as 
 well as highlighting info. The painter as I see it collects all this 
 info, but the info is provided by other objects.
 
 Right, I left the implementation of the highlighters and folding to 
 dedicated objects. The classes have to implement only the very slim 
 interface of the base class, everything else is open end.
   
Right that sounds similar to my plans. The folded info is stored in a 
FoldTree (well at the moment it is split, and some is still stored on 
the raw-text-lines, work in progress)
The mapping is done in FoldedView.

 From all I read the difference is, that I put a viewer-class into a 
stack. You seem to have this in your grid-class, or a specialized 
inherited grid-class.
Probably both approaches have their benefits. In order to compare them 
we would have to deeply analyse both of them.
 BTW, I stored characteristic info in fixed size records, which can 
 easily saved and exchanged together with the source file or the global 
 settings. No encapsulation, but easy to use, and little chances for 
 coding errors.
   
You are speaking of the highlighting info? Maybe easiest to give a 
usecase or example? Also when you say characteristic, do you mean: the 
details of the characteristics (e.g. numbers are blue or comments are 
bold), or do you mean whih characteristic apply to a char/group of chars 
(e.g. format the next 3 chars with the format for numbers).
 The View port for example does not do the painting, it is a helper class 
 to map the right code into the grid. It is used by the painters, but 
 also used outside.
 It allows (without accessing the painter) to check if a char or the 
 caret is in the visible area. ( There still is the question if it will 
 be 

Re: [Lazarus] Code Structure / SourceEdit and SyneEdit [Re: Mouse Link in SynEdit (only link-able items)]

2008-12-16 Thread Hans-Peter Diettrich
Martin Friebe schrieb:

 Maybe for clarifications. I started this using the word view. But I 
 can see there are 2 ways to read this word.
 - physical view: Like a painter. The final output of the combined 
 text/style information. Most common drawing it to a canvas. But it could 
 be a reader too.
 - logical view: (I guess what you called the grid?). A module that 
 takes the raw-text, and converts it into a structure suitable for the 
 physical view, applying style/highlight info on the way.

In the model-view-controller context, the view is the logical aspect.

Let me add another clarification:

My primary viewpoint is that of an component writer, designing 
components for general use, i.e. not bound to a specific application or 
context, unless specific to the functionality of the component itself.

Consequently my CharGrid is a general component, whose use in Lazarus 
may deserve extensions to the general functionality. The basic component 
has certain capabilities, and a specific implementation. Take it both as 
a general model, and a specific implementation as a proof of the concept.

Now we can discuss in general, *whether* it's possible to achive the 
Lazarus-specific functionality, based on the given component design. 
This was my context in the preceding discussion. I wanted to prove that 
my approach is suitable for that specific use, and find out where the 
implementation may deserve a redesign. The result only can be go/nogo.

Then we can discuss in detail, *how* the desired functionality can be 
achieved (implemented). In this part I can explain how I implemented 
certain functionalities, and how I would use and extend the 
functionality in general. Others can explain their model, how to 
implement and extend the functionality in their design and 
implementation, so that we can find out about the specific advantages 
and disadvantages of the different approaches. We seem to have just 
entered this part of the discussion.


 
 I do use the word view to describe the logical-view of a source-file 
 transformed into a grid.
 I do  not  use the word view to describe the painter. ( I propose 
 physical view)
 I do  not  use the word view to describe the high level dual 
 visibility of the same source-file in 2 windows (or a splitted window) ( 
 I propose user view ?? imho a weak description, not good)

When it comes to implementation details, like painting, then I'd prefer 
component for the overall (TLazEdit or TCharGrid) component. That 
component can consist of, or use, dedicated sub-components, wich we 
should address as text and gutter painters, syntax highlighters etc.


 Some of the answers where given before I understood that view in your 
 text sometimes refers to multi window display.  I tried to amend them 
 in a 2nd run through my answer. I hope I didn't miss any. If my answers 
 do not seem to match your text, I probably read view in a different way 
 from what you meant

IMO we should restrict the term view to any unspecific visual 
representation of a model (document), in the abstract MVC context. 
Distinct from the context of a specific component or viewer.


[...]
 Is it really still a column block, when a double-width character hangs 
 out on it's right boundary?
   
 Well it is the users option (with tabs) to either have ragged column 
 blocks, or cut tabs into spaces or 

The user selects an column block with the mouse, as a rectangle from 
top/left to bottom/right. Then we have to specify how to deal with 
unaligned double-width characters, at the left and right margins of that 
rectangle, in block highlighting and copy/paste operations.

 With Chinese (and I believe Arabic, and a few other language) there are 
 no options (the char can not be cut).

There exist more such language and Unicode specific restrictions. Take 
the more familiar case of an Ä (A-umlaut), which in Unicode can be 
represented as either a single code point Ä or as two code points for 
umlaut and A. Both encodings are displayed as the same glyph, by a 
true Unicode painter. Now we have a problem, because the internal 
representation of that glyph can consist of one or two code points, so 
what should happen when the user deletes that character from the text? 
In an Unicode editor the first delete may delete the umlaut, so that 
the glyph is not removed on screen, but instead is converted into the 
remaining A.

That's why I dislike the use of Unicode with all related hazzles. Either 
we need a Unicode library, that implements everything, including the 
painting, and implement something like an text processor - or we deal 
with code points and display above umlaut-A combination as two adjacent 
glyphs.

In my approach I assumed (willingly) that there exists a 1:1 
correspondence between stored code units (WideChar) and visible glyphs, 
and all glyphs are displayed left-to-right. For all unhandled cases I 
expect a detailed specification, from somebody really familiar with the 
handling of those 

Re: [Lazarus] Code Structure / SourceEdit and SyneEdit [Re: Mouse Link in SynEdit (only link-able items)]

2008-12-15 Thread Martin Friebe
Hans-Peter Diettrich wrote:
 Martin Friebe schrieb:
   
 The only reason I did skip the grid in the name is that a generic 
 painter base class will not define a griod (or maybe it will but based 
 on pixels). So it does not block anyone from implementing a proportional 
 painter
 
 Okay, but a proportional representation will have a very different 
 coordinate mapping, so that most of the basic functions (mouse, cursor 
 movements) are very different. My approach addressed exactly those low 
 level tasks, with the CharGrid already being a specialized grid class, 
 with cells containing characters, and added font and text properties.

 My primary goal was a stable base component, that can be turned into any 
 text viewer or editor, by adding specialized document interfaces in 
 derived classes. For a proportional representation the design will have 
 to be turned upside down, and the base class will have to be specialized 
 and follow the design of the related content handler(s).
   
Then how to you handle double width chars? This si one of the problems I 
still have to address.
Even in a proportional font, some chars (Chinese, and other) have twice 
the width of a normal char. They will 2 positions in the grid.
Actually it is the same issue as tabs.

Each char needs to have an info, how many cells it will allocate. Now if 
that is the case then to display proportional fonts, all I need to to 
make the grid size 1 pixel.
-- I do *not* encourage that. I do not say this is a good thing for a 
source editor. But given how close SynEdit comes to proportional display 
anyway, I keep at least an open mind about a structure that would allow 
to implement it. --

Column Blocks, as well as horizontal caret movement have to deal with 
this anyway, since you may allow to be in the middle of a tab. But you 
can not permit to have the caret in the middle of a chinese char.

 That canvas/handle holder does not replace the (Grid)Painter. It is used 
 by the GridPainter(s), and used by the GutterPainter(s). It may even be 
 thyat it does not need to exist, and canvas and handle can be passed to 
 all the Painters in Form of their LCL classes.
 
 Then my CharGrid is kind of a canvas holder, which performs the mapping 
 between document (content) and viewport (painting) space. The painters 
 do not have to know about the organization of the canvas, they only have 
 to paint given information within their actual clipping area (part of a 
 display line). The content holder (source file) can be switched at any 
 time, whereupon the CharGrid adjusts the viewport (window) to the new 
 content extent.
   
The question still is how do your painters to all that. IMHO the mapping 
into a grid requires a lot of info (folded/ word wrapped/ tabs,...) as 
well as highlighting info. The painter as I see it collects all this 
info, but the info is provided by other objects.

The View port for example does not do the painting, it is a helper class 
to map the right code into the grid. It is used by the painters, but 
also used outside.
It allows (without accessing the painter) to check if a char or the 
caret is in the visible area. ( There still is the question if it will 
be the painter or the viewport who defines the size of each grid cell 
(basically the font size))

 As It currently stands all the info about everything is hold by the Main 
 SynEdit Class, and all other classes need to ask the central SynEdit 
 Class. That is undesirable.
 

 ACK. A MVC (model-view-controller) approach migth be better. The model 
 holds the source files, the view manages painting and user interface 
 (mouse and keyboard), and the controller updates the document upon input 
 or other commands, and synchronizes the related view(s) afterwards.
   
The view IMHO is more than one class, that gradually apply the mapping 
from a Source-Holder (TStringList) to a char-grid. The Painter then 
transfers each char to from the grid to the canvas.

That is what I am currently trying to do

the painter looks at a grid-provider,  a grid provider may read either 
the source or another grid-provider as input. I currently call those 
grid-provider View.

One thing must change, currently the PaintLines code, combines the 
highlight info with the grid-view result. But that means mapping the 
highlight info.
The highlight info must be applied to the unmodified source, and then 
share the way through the grid-providers
(That's actually something I realized from this discussion = good)

So If  I display a text that has no tabs, no double width chars, no 
folds, no , then all I need is:

-source-buffer
-highlight info (does not re-organize the layout)
-viewport-grid
-painter

The view port grid, selects the correct lines, and within each line the 
correct substring. So if the text is horizontaly scrolled it cuts the 
beginning of each line, and in any case, it cuts any line that is to long.
There a 2 objects:
- The TViewPort = which defines the corner points / 

Re: [Lazarus] Code Structure / SourceEdit and SyneEdit [Re: Mouse Link in SynEdit (only link-able items)]

2008-12-15 Thread Hans-Peter Diettrich
Martin Friebe schrieb:

 Then how to you handle double width chars? This si one of the problems I 
 still have to address.
 Even in a proportional font, some chars (Chinese, and other) have twice 
 the width of a normal char. They will 2 positions in the grid.
 Actually it is the same issue as tabs.

Are these characters inside the Unicode BMP?

Actually I did a translation into WideChar, so that only characters from 
the Unicode BMP can be processed. In this model I'd insert a dummy 
character into the output string, that is not displayed but compensates 
for the width of the preceding double-width character.

And what about RTL text? IMO there exist limits for the task of an 
source code editor, where it's easier to use or port some existing text 
processing component, instead of reinventing the wheel.

Full Unicode requires assistance by some sophisticated library, that can 
deal with all the oddities of character sequences (ligatures...), and 
that should be provided and maintained by the platform. Windows has such 
a Uniscribe library, see
http://www.catch22.net/tuts/neatpad/11
This editor tutorial convinced me to either stay with truly monospaced 
characters, or let an according library do all drawing. Nothing 
half-baked in between. The same for the *input* of Chinese or other 
exceptional character sets (IME editors...).


 Column Blocks, as well as horizontal caret movement have to deal with 
 this anyway, since you may allow to be in the middle of a tab. But you 
 can not permit to have the caret in the middle of a chinese char.

No problem, my tabs have a special display encoding, that forces the 
caret to move to the next ordinary character cell.

Is it really still a column block, when a double-width character hangs 
out on it's right boundary?


 The question still is how do your painters to all that. IMHO the mapping 
 into a grid requires a lot of info (folded/ word wrapped/ tabs,...) as 
 well as highlighting info. The painter as I see it collects all this 
 info, but the info is provided by other objects.

Right, I left the implementation of the highlighters and folding to 
dedicated objects. The classes have to implement only the very slim 
interface of the base class, everything else is open end.

BTW, I stored characteristic info in fixed size records, which can 
easily saved and exchanged together with the source file or the global 
settings. No encapsulation, but easy to use, and little chances for 
coding errors.


 The View port for example does not do the painting, it is a helper class 
 to map the right code into the grid. It is used by the painters, but 
 also used outside.
 It allows (without accessing the painter) to check if a char or the 
 caret is in the visible area. ( There still is the question if it will 
 be the painter or the viewport who defines the size of each grid cell 
 (basically the font size))

In my model nobody has to know about the painting, all required 
information resides in the line buffer and viewport outline. Apart from 
the basic client and gutter size (in pixels) and the font size, the 
viewport outline contains the overall grid dimension, corresponding to 
the line/row count of the document after block folding, the visible area 
is described by a scrollable offset within the grid, or (0,0) for 
painting in client address space, and the current extent of the viewport 
(client area of the control), in both fully and partially visible 
characters. The separation into fully (page size) and partially visible 
(viewport size) characters allows to e.g. scroll by (fully visible) 
pages in both directions, while painting and display of the caret stops 
only at the viewport margins - the latter (caret display) is not 
properly implemented in the current LazEdit!

 ACK. A MVC (model-view-controller) approach migth be better. The model 
 holds the source files, the view manages painting and user interface 
 (mouse and keyboard), and the controller updates the document upon input 
 or other commands, and synchronizes the related view(s) afterwards.
   
 The view IMHO is more than one class, that gradually apply the mapping 
 from a Source-Holder (TStringList) to a char-grid. The Painter then 
 transfers each char to from the grid to the canvas.

All that has to be encapsulated in every single view(er). When the code 
explorer is a view, it's internals have almost nothing in common with 
the text viewer. A gutter also is kind of an viewer, coupled with the 
text viewer only by a common TopLine, but independent otherwise.

Of course the various viewers are related to a distinct document and 
helper objects, from which they obtain all the information to be 
displayed, but the kind of required information depends on their 
individual tasks.

The document base class has (virtual) functions for the conversion 
between stored (file based) and visible (possibly folded) coordinates, 
so that the details of folding are encapsulated. When the gutter 
painter/viewer 

Re: [Lazarus] Code Structure / SourceEdit and SyneEdit [Re: Mouse Link in SynEdit (only link-able items)]

2008-12-14 Thread Martin Friebe
Hans-Peter Diettrich wrote:
 Martin Friebe schrieb:
   
 A couple of remarks:
 -Individual drawer objects fro Gutter and TextArea (I will avoid Grid in 
 the name, Grid is a specialization)
 
 The Grid is a hint on the organisation of the canvas, in rectangular 
 cells. I've spent a lot of time in the various coordinate systems and 
 their mapping, for drawing purposes (relative to the window), document 
 view (rows/columns, scrolling, line wrapping), and document storage 
 (folding, tab expansion, UTF encoding). The need for properly anchored 
 bookmarks was a big challenge. Similar, but finally easy to implement, 
 was the preservation of the cursor column, when scrolling across lines 
 of shorter lenght.
   
The only reason I did skip the grid in the name is that a generic 
painter base class will not define a griod (or maybe it will but based 
on pixels). So it does not block anyone from implementing a proportional 
painter

 This has been started for the Gutter. It does need a lot of clean up still.
 It would also benefit from the Os-Handle and canvas being moved into a 
 wrapper class. This would:
 - avoid the need  to callback synedit for Invalidates
 - allow a Handle/Canvas of another Component being passed to SynEdit, 
 and SynEdit painting the other component (e.g. SourceEditor)
 
 Here we may have quite different viewpoints, on the delegation of the 
 responsibilities.
   
That canvas/handle holder does not replace the (Grid)Painter. It is used 
by the GridPainter(s), and used by the GutterPainter(s). It may even be 
thyat it does not need to exist, and canvas and handle can be passed to 
all the Painters in Form of their LCL classes.

As It currently stands all the info about everything is hold by the Main 
SynEdit Class, and all other classes need to ask the central SynEdit 
Class. That is undesirable.
I extracted 2 classes already (but the ove isn't complete)
- TSynEditCaret:
   Storing all info about the caret. It will obviously need help from 
other modules, to deal with tabs, double-width chars, wrapped lines 
(that will probably be a specialized subclass, completely replacing the 
original), and other things
-TSynEditSelection:
  To deal with the selected block. This one is not very related to this 
discussion. But it has the same needs as the Caret

I will have to add a TSynEditViewPortClass:
 This will at least store the Coordinates of the screen in the text (as 
in TopLine/LeftChar - LinesInWindow/CharWidthOfScreen), maybe a bit 
more.  To do so, it will need access to the Painter to get information 
about the grid (LineHeight, SingleCharWidth)

 Similar considerations for the Textarea. However the textdrawer will 
 have to access a lot of other objects, and need ways to merge the 
 result. there are
 - the highlighter
 - the MarkUpManager
 
 In my solution the highlighting (including hyperlinks) is implemented in 
 derived classes, by overriding the line-painting method. I ended up in a 
 single array, holding the scanner start state for every line - required 
   
If I understand your description correct: This special array is 
currently part of SynEditCodeBuffer? In any case this is information for 
the highlighter. The (Grid)Drawer should never access this info 
directly. The grid drawer will ask the highlighter (In the current 
Synedit there may be a need to clean up the way the Highlighter is 
handled...)
 for proper handling of multi-line comments. Hyperlinks are implemented 
 as special highlighting information. When the mouse pointer moves, the 
 according characters and attributes are obtained for the current line, 
 from the document, then the line eventually is repainted when the 
 active state of a hyperlink has changed.
   
For Hyper links, had you have a look at the MarkUp class? 
(SynEditMarkupCtrlMouseLink in 
components\synedit\syneditmarkupctrlmouselink.pp; there is stil some 
remains in central Synedit that need moving)

Again this class does not replace the GridDrawer. It is to be used as a 
helper class by any GridDrawer.

I have no information about the internals of you r grid drawer, and how 
it delegates work and responsibilities, so I can not really comment on it.
I don't know how your grid drawer deals with all the different 
tasks/responsibilities, it has to meet (especially within the 
LineDrawing Class). You talk a lot of sub classes that implement the 
individual bits. This may be needed (and probably is at least for 
WordWrapping).
But I believe that the Griddrawer (and it's LineDrawer) should solve a 
lot by delegate to helper classes?

Of course this is easily said. And I haven't yet got the full design for 
how I will/would do the GridDrawer.

 - The TextLines itself (e.g. Highlighter token will return a tab as a 
 tab, but the TestLines need to translate this into displayable chars. Either
   -- spaces
   -- show special chars  (and if tab is only one char, then maybe 
 there is only one  followe by spaces?
 
 Right, tab expansion is 

Re: [Lazarus] Code Structure / SourceEdit and SyneEdit [Re: Mouse Link in SynEdit (only link-able items)]

2008-12-14 Thread Hans-Peter Diettrich
Martin Friebe schrieb:

 The only reason I did skip the grid in the name is that a generic 
 painter base class will not define a griod (or maybe it will but based 
 on pixels). So it does not block anyone from implementing a proportional 
 painter

Okay, but a proportional representation will have a very different 
coordinate mapping, so that most of the basic functions (mouse, cursor 
movements) are very different. My approach addressed exactly those low 
level tasks, with the CharGrid already being a specialized grid class, 
with cells containing characters, and added font and text properties.

My primary goal was a stable base component, that can be turned into any 
text viewer or editor, by adding specialized document interfaces in 
derived classes. For a proportional representation the design will have 
to be turned upside down, and the base class will have to be specialized 
and follow the design of the related content handler(s).


 That canvas/handle holder does not replace the (Grid)Painter. It is used 
 by the GridPainter(s), and used by the GutterPainter(s). It may even be 
 thyat it does not need to exist, and canvas and handle can be passed to 
 all the Painters in Form of their LCL classes.

Then my CharGrid is kind of a canvas holder, which performs the mapping 
between document (content) and viewport (painting) space. The painters 
do not have to know about the organization of the canvas, they only have 
to paint given information within their actual clipping area (part of a 
display line). The content holder (source file) can be switched at any 
time, whereupon the CharGrid adjusts the viewport (window) to the new 
content extent.


 As It currently stands all the info about everything is hold by the Main 
 SynEdit Class, and all other classes need to ask the central SynEdit 
 Class. That is undesirable.

ACK. A MVC (model-view-controller) approach migth be better. The model 
holds the source files, the view manages painting and user interface 
(mouse and keyboard), and the controller updates the document upon input 
or other commands, and synchronizes the related view(s) afterwards.

 I extracted 2 classes already (but the ove isn't complete)
 - TSynEditCaret:
Storing all info about the caret. It will obviously need help from 
 other modules, to deal with tabs, double-width chars, wrapped lines 
 (that will probably be a specialized subclass, completely replacing the 
 original), and other things
 -TSynEditSelection:
   To deal with the selected block. This one is not very related to this 
 discussion. But it has the same needs as the Caret

The caret is private to every view, the outer world only has to retrieve 
or modify the logical (content based) caret position. The same for the 
selection, with content based row/col coordinates; the view will manage 
the display of either a sequential or column based block hightlighting, 
and merge the text attributes of all block sources (syntax, 
hyperlinks, selection).

BTW, just the requirement for column-based blocks discourages the use of 
an proportional font. Elastic tabs may allow for blocks with consistent 
left/right margins, but then the text will look strange in any other 
editor or viewer, what's not desireable with shareable source code.


 I will have to add a TSynEditViewPortClass:
  This will at least store the Coordinates of the screen in the text (as 
 in TopLine/LeftChar - LinesInWindow/CharWidthOfScreen), maybe a bit 
 more.  To do so, it will need access to the Painter to get information 
 about the grid (LineHeight, SingleCharWidth)

This were my CharGrid, that translates everything between document 
(model) and view space. The interface between document and view can be a 
simple record, containing the document row count. My CharGrid then can 
determine everything else from the text itself. I delegated that mapping 
to the syntax highlighter, that already has the task of parsing the 
text. It also will be involved in the determination of foldable blocks, 
so that folding (list of blocks and their state) can be implemented 
inside that class.

TopLine and LeftChar are not of any interest outside the view. A 
ScrollIntoView method will be sufficient for the outer world, with 
document based coordinates, perhaps with an anchor (alTop, alBottom, 
alCenter).



 - the highlighter
 - the MarkUpManager
 
 In my solution the highlighting (including hyperlinks) is implemented in 
 derived classes, by overriding the line-painting method. I ended up in a 
 single array, holding the scanner start state for every line - required 
   
 If I understand your description correct: This special array is 
 currently part of SynEditCodeBuffer? In any case this is information for 
 the highlighter. The (Grid)Drawer should never access this info 
 directly. The grid drawer will ask the highlighter (In the current 
 Synedit there may be a need to clean up the way the Highlighter is 
 handled...)

My hiliter has several purposes:
- it 

Re: [Lazarus] Code Structure / SourceEdit and SyneEdit [Re: Mouse Link in SynEdit (only link-able items)]

2008-12-13 Thread Martin Friebe
Hans-Peter Diettrich wrote:
 Martin Friebe schrieb:
   
 Well I am in the process of breaking it up into smaller bits.
 - The gutter drawing moved to its own class.
 - Folding is partly abstracted
 - Trim Trailing spaces has been abstracted into a class of its own. (a 
 view of SynEditLines)
 - Caret and block have been started
 
 I've a TCharGrid component, developed in the time when the SynEdit was 
 too instable and unreliable. It handles all cursor moves, scrolling, 
 selecting text (also in columns), tab widths, (syntax) coloring, and 
 also has provisions for both vertical and horizontal gutters. It was 
 intended as a more reliable base for e.g. SynEdit, in general for 
 representing text in a monospaced font, as is convenient for source 
 code. It was developed and tested with Delphi 7, i.e. for Windows, but 
 should be widely platform independent. If somebody is interested in the 
 source code...

 DoDi
   
Looking at your signature, you are the Author of 
http://wiki.lazarus.freepascal.org/Redesign_of_the_SynEdit_component ?

A couple of remarks:
-Individual drawer objects fro Gutter and TextArea (I will avoid Grid in 
the name, Grid is a specialization)

This has been started for the Gutter. It does need a lot of clean up still.
It would also benefit from the Os-Handle and canvas being moved into a 
wrapper class. This would:
- avoid the need  to callback synedit for Invalidates
- allow a Handle/Canvas of another Component being passed to SynEdit, 
and SynEdit painting the other component (e.g. SourceEditor)

Similar considerations for the Textarea. However the textdrawer will 
have to access a lot of other objects, and need ways to merge the 
result. there are
- the highlighter
- the MarkUpManager
- The TextLines itself (e.g. Highlighter token will return a tab as a 
tab, but the TestLines need to translate this into displayable chars. Either
  -- spaces
  -- show special chars  (and if tab is only one char, then maybe 
there is only one  followe by spaces?
 This can only be done by the Lines, as they know the layout/tabwidth 
(see concept of Views/ TabView below)


The storage and view of the TextLines:
I think TSynEditCodeBuffer is a good start for this. Yet tabs are a 
specialisation, that should go into a ViewClass.
ViewClasses TSynEditStrings themself, that will modify how the stored 
text is seen. (TrimTrailingSpaces is an example. FoldedView too, so 
FoldedFiew does not yet fully follow the concept)

The following Views (and others) can apply to the text

- WordWrapView
- FoldView
- TabView or ElasticTabView (http://bugs.freepascal.org/view.php?id=9650)
   modifies Logical(byte) to Phisical (char on screen) calculations.
   probably still returns tabs, but offers conversation methods.
   - replacing tabs with spaces in the Strings[] property, may 
complicate Highlighting and MarkUp and show special chars
 It would also impact the ability of keeping the caret from being 
placed in the middle of a tab (which currently can be done)
- TrimSpaceView
- TSynEditStringBuffer (holding the actual text)

Martin



___
Lazarus mailing list
Lazarus@lazarus.freepascal.org
http://www.lazarus.freepascal.org/mailman/listinfo/lazarus


Re: [Lazarus] Code Structure / SourceEdit and SyneEdit [Re: Mouse Link in SynEdit (only link-able items)]

2008-12-13 Thread Hans-Peter Diettrich
Martin Friebe schrieb:

 Looking at your signature, you are the Author of 
 http://wiki.lazarus.freepascal.org/Redesign_of_the_SynEdit_component ?

Right, this was the draft for the subsequent implementation.

 A couple of remarks:
 -Individual drawer objects fro Gutter and TextArea (I will avoid Grid in 
 the name, Grid is a specialization)

The Grid is a hint on the organisation of the canvas, in rectangular 
cells. I've spent a lot of time in the various coordinate systems and 
their mapping, for drawing purposes (relative to the window), document 
view (rows/columns, scrolling, line wrapping), and document storage 
(folding, tab expansion, UTF encoding). The need for properly anchored 
bookmarks was a big challenge. Similar, but finally easy to implement, 
was the preservation of the cursor column, when scrolling across lines 
of shorter lenght.

 This has been started for the Gutter. It does need a lot of clean up still.
 It would also benefit from the Os-Handle and canvas being moved into a 
 wrapper class. This would:
 - avoid the need  to callback synedit for Invalidates
 - allow a Handle/Canvas of another Component being passed to SynEdit, 
 and SynEdit painting the other component (e.g. SourceEditor)

Here we may have quite different viewpoints, on the delegation of the 
responsibilities.

 Similar considerations for the Textarea. However the textdrawer will 
 have to access a lot of other objects, and need ways to merge the 
 result. there are
 - the highlighter
 - the MarkUpManager

In my solution the highlighting (including hyperlinks) is implemented in 
derived classes, by overriding the line-painting method. I ended up in a 
single array, holding the scanner start state for every line - required 
for proper handling of multi-line comments. Hyperlinks are implemented 
as special highlighting information. When the mouse pointer moves, the 
according characters and attributes are obtained for the current line, 
from the document, then the line eventually is repainted when the 
active state of a hyperlink has changed.

 - The TextLines itself (e.g. Highlighter token will return a tab as a 
 tab, but the TestLines need to translate this into displayable chars. Either
   -- spaces
   -- show special chars  (and if tab is only one char, then maybe 
 there is only one  followe by spaces?

Right, tab expansion is highly configurable in my solution :-)

  This can only be done by the Lines, as they know the layout/tabwidth 
 (see concept of Views/ TabView below)

Right, the handling of wrapped lines also was a challenge :-)

 The storage and view of the TextLines:
 I think TSynEditCodeBuffer is a good start for this. Yet tabs are a 
 specialisation, that should go into a ViewClass.
 ViewClasses TSynEditStrings themself, that will modify how the stored 
 text is seen. (TrimTrailingSpaces is an example. FoldedView too, so 
 FoldedFiew does not yet fully follow the concept)

I've left folding to the document management, for any convenient 
implementation. The visual component manages visible lines only, the 
mapping between stored and visible lines must be implemented outside of 
it. Including notifications of the changed line count, when text blocks 
are collapsed or expanded. If desired, multiple views can have different 
blocks collapsed, different tab width, wrapping on different screen 
boundaries etc. The consideration of multiple views reveals clear 
frontiers for the various responsibilities (what feature to implement 
where).


 The following Views (and others) can apply to the text
 
 - WordWrapView
 - FoldView
 - TabView or ElasticTabView (http://bugs.freepascal.org/view.php?id=9650)
modifies Logical(byte) to Phisical (char on screen) calculations.
probably still returns tabs, but offers conversation methods.
- replacing tabs with spaces in the Strings[] property, may 
 complicate Highlighting and MarkUp and show special chars
  It would also impact the ability of keeping the caret from being 
 placed in the middle of a tab (which currently can be done)
 - TrimSpaceView
 - TSynEditStringBuffer (holding the actual text)

IMO all this is already perfectly implemented in my CharGrid.

With regards to the ElasticTabView, I have my own opinion on a mix of an 
source code editor with a text processor or page layouter - it stinks :-(

I neither like subroutine arguments indented to the ( of the call, nor 
block comments to the right of source code, sensitive to insertion or 
deletion of lines of code. I don't want to open a can of worms for 
people who put more emphasis on the appearance of their(?) source code, 
than on its functionality. It's more annoying when the caret disappears 
in the last line or column of the window, as I observed in the current 
SynEdit implementation.

DoDi

___
Lazarus mailing list
Lazarus@lazarus.freepascal.org
http://www.lazarus.freepascal.org/mailman/listinfo/lazarus


[Lazarus] Code Structure / SourceEdit and SyneEdit [Re: Mouse Link in SynEdit (only link-able items)]

2008-12-12 Thread Martin Friebe
Mattias Gärtner wrote:
 Zitat von Alexander Klenin kle...@gmail.com:
   
 I should note that I was horrified by the amount of glue code needed
 to route an event through main form, source notebook, source editor and
 SynEdit.
 
 The IDE is structured in a hierarchy.

 mainide: the top level of the IDE and the central nerve system. Because of its
 size it's splitted into several units. This is the 'integrated' in IDE. It
 connects the various modules like debugger, package system, codetools,
 designer, etc.
 source notebook: the whole source editor
 source editor: one single editor (at the moment in the same unit with source
 notebook, but should eventually split up)
 synedit: visual control
   
Reading this, I just had an idea. (Nothing that would be done anytime 
soon, as it would be a major project)

In The current structure
SynEdit is the Visual control, and therefore also the control that takes 
all events such as mouse/key down/up/move. Often it is SynEdits work to 
react to this, but often it also needs to call back to SourceEditor.

It is at least worth reviewing if this order could/should be changed (I 
am not sure about it):
- SourceEditor could be a visual component with all the Key/Mouse event 
handlers.
- It would *not* inherit from SynEdit, but same as now it would have a 
SynEdit instance that it can make calls to. This SynEdit would not paint 
on it's own canvas, but rather paint on the SourceEditors canvas
- Instead of SynEdit making all the callbacks to SourceEditor, now all 
events go to SourceEditor first, and SourceEditor can decide what to 
forward.

On the other hand, it is probably not worth the amount of work. Well the 
future will show, if there is a use case for it...

Best Regards
Martin



___
Lazarus mailing list
Lazarus@lazarus.freepascal.org
http://www.lazarus.freepascal.org/mailman/listinfo/lazarus


Re: [Lazarus] Code Structure / SourceEdit and SyneEdit [Re: Mouse Link in SynEdit (only link-able items)]

2008-12-12 Thread Alexander Klenin
On Fri, Dec 12, 2008 at 21:37, Martin Friebe laza...@mfriebe.de wrote:

 In The current structure
 SynEdit is the Visual control, and therefore also the control that takes
 all events such as mouse/key down/up/move. Often it is SynEdits work to
 react to this, but often it also needs to call back to SourceEditor.

 It is at least worth reviewing if this order could/should be changed (I
 am not sure about it):
 - SourceEditor could be a visual component with all the Key/Mouse event
 handlers.
 - It would *not* inherit from SynEdit, but same as now it would have a
 SynEdit instance that it can make calls to. This SynEdit would not paint
 on it's own canvas, but rather paint on the SourceEditors canvas
 - Instead of SynEdit making all the callbacks to SourceEditor, now all
 events go to SourceEditor first, and SourceEditor can decide what to
 forward.

Sigh, if we are dreaming anyway, here is my dream:

1) Logic should be separated from the presentation, so first there should be
'TAbstractSynEdit' class, concerning itself purely with text manipulations,
such as text insertion/deletion, cursor position changes, text
attribute calculation,
save/loading, codetools etc.
TAbstractSynEdit should not depend on any visual code, in partucular it should
descend from TObject/TPersistent, not TControl.

2) Logic should be covered by automated tests, e.g. using fpcunit framework.

3) Presentation and user interaction should be the concern of TSynEdit class,
  aggregating TAbstractSynEdit and delegating all actual logic to the latter.

4) SourceEditor should be removed (or converted into a trivial wrapper),
TSourceNotebook should reference TSynEdit directly.

 On the other hand, it is probably not worth the amount of work. Well the
 future will show, if there is a use case for it...

True. Proper design requires lots of effort, and (especially
short-term) benefits
might not outweight the costs.

-- 
Alexander S. Klenin
Insight Experts Ltd.
___
Lazarus mailing list
Lazarus@lazarus.freepascal.org
http://www.lazarus.freepascal.org/mailman/listinfo/lazarus


Re: [Lazarus] Code Structure / SourceEdit and SyneEdit [Re: Mouse Link in SynEdit (only link-able items)]

2008-12-12 Thread Martin Friebe
Alexander Klenin wrote:
 On Fri, Dec 12, 2008 at 21:37, Martin Friebe laza...@mfriebe.de wrote:
   
 In The current structure
 SynEdit is the Visual control, and therefore also the control that takes
 all events such as mouse/key down/up/move. Often it is SynEdits work to
 react to this, but often it also needs to call back to SourceEditor.

 It is at least worth reviewing if this order could/should be changed (I
 am not sure about it):
 - SourceEditor could be a visual component with all the Key/Mouse event
 handlers.
 - It would *not* inherit from SynEdit, but same as now it would have a
 SynEdit instance that it can make calls to. This SynEdit would not paint
 on it's own canvas, but rather paint on the SourceEditors canvas
 - Instead of SynEdit making all the callbacks to SourceEditor, now all
 events go to SourceEditor first, and SourceEditor can decide what to
 forward.
 
 Sigh, if we are dreaming anyway, here is my dream:

 1) Logic should be separated from the presentation, so first there should be
 'TAbstractSynEdit' class, concerning itself purely with text manipulations,
 such as text insertion/deletion, cursor position changes, text
 attribute calculation,
 save/loading, codetools etc.
 TAbstractSynEdit should not depend on any visual code, in partucular it should
 descend from TObject/TPersistent, not TControl.
   
Well I am in the process of breaking it up into smaller bits.
- The gutter drawing moved to its own class.
- Folding is partly abstracted
- Trim Trailing spaces has been abstracted into a class of its own. (a 
view of SynEditLines)
- Caret and block have been started

Of course, they do still have heavy dependencies. But those can not 
easily be removed yet, other parts have to be broken free first.

 2) Logic should be covered by automated tests, e.g. using fpcunit framework.
   
Also started (mainly folding), so they need heavy cleanup. I cam from 
other test frame-works and forcefully attempted to abuse fpcunit...

But as far as I am concerned, you can not write code without having 
automated tests.
 3) Presentation and user interaction should be the concern of TSynEdit class,
   aggregating TAbstractSynEdit and delegating all actual logic to the latter.

 4) SourceEditor should be removed (or converted into a trivial wrapper),
 TSourceNotebook should reference TSynEdit directly.

   
 On the other hand, it is probably not worth the amount of work. Well the
 future will show, if there is a use case for it...
 

 True. Proper design requires lots of effort, and (especially
 short-term) benefits
 might not outweight the costs.

   
___
Lazarus mailing list
Lazarus@lazarus.freepascal.org
http://www.lazarus.freepascal.org/mailman/listinfo/lazarus


Re: [Lazarus] Code Structure / SourceEdit and SyneEdit [Re: Mouse Link in SynEdit (only link-able items)]

2008-12-12 Thread Marc Weustink
Martin Friebe wrote:
 Mattias Gärtner wrote:
 Zitat von Alexander Klenin kle...@gmail.com:
   
 I should note that I was horrified by the amount of glue code needed
 to route an event through main form, source notebook, source editor and
 SynEdit.
 
 The IDE is structured in a hierarchy.

 mainide: the top level of the IDE and the central nerve system. Because of 
 its
 size it's splitted into several units. This is the 'integrated' in IDE. It
 connects the various modules like debugger, package system, codetools,
 designer, etc.
 source notebook: the whole source editor
 source editor: one single editor (at the moment in the same unit with source
 notebook, but should eventually split up)
 synedit: visual control
   
 Reading this, I just had an idea. (Nothing that would be done anytime 
 soon, as it would be a major project)
 
 In The current structure
 SynEdit is the Visual control, and therefore also the control that takes 
 all events such as mouse/key down/up/move. Often it is SynEdits work to 
 react to this, but often it also needs to call back to SourceEditor.
 
 It is at least worth reviewing if this order could/should be changed (I 
 am not sure about it):
 - SourceEditor could be a visual component with all the Key/Mouse event 
 handlers.
 - It would *not* inherit from SynEdit, but same as now it would have a 
 SynEdit instance that it can make calls to. This SynEdit would not paint 
 on it's own canvas, but rather paint on the SourceEditors canvas
 - Instead of SynEdit making all the callbacks to SourceEditor, now all 
 events go to SourceEditor first, and SourceEditor can decide what to 
 forward.
 
 On the other hand, it is probably not worth the amount of work. Well the 
 future will show, if there is a use case for it...

It would make the design more pure then as it is now. I have too been 
wondering why synedit needs all the knowledge of ide events.

Marc
___
Lazarus mailing list
Lazarus@lazarus.freepascal.org
http://www.lazarus.freepascal.org/mailman/listinfo/lazarus


Re: [Lazarus] Code Structure / SourceEdit and SyneEdit [Re: Mouse Link in SynEdit (only link-able items)]

2008-12-12 Thread Alexander Klenin
On Sat, Dec 13, 2008 at 06:26, Flávio Etrusco flavio.etru...@gmail.com wrote:
 My vision deviates a bit from this in the sense that TAbstractSynEdit
 would just be an abstraction (or dedicated implementation) of a
 cleaner text manipulation interface (as TStrings won't cut it), which
 would also implement transparent/automatic/implicit 'undo' handling.
 Then each command would be a class, probably inheriting from TAction.

It is not a deviation as much as detalization ;-)
However, it is also important not to overdo abstractions --
perhaps a separate class for every command is too much.

Anyway, I am glad that you (and Martin) agree with the general concept.

-- 
Alexander S. Klenin
Insight Experts Ltd.

___
Lazarus mailing list
Lazarus@lazarus.freepascal.org
http://www.lazarus.freepascal.org/mailman/listinfo/lazarus