[Lazarus] implicit undo (attn Flávio) [Re: Code Structure / SourceEdit and SyneEdit]
Hans-Peter Diettrich
DrDiettrich1 at aol.com
Wed Mar 4 18:13:06 CET 2009
Martin Friebe schrieb:
>> 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.
>>
> Just read this, ....
>
> I had the same idea, and am in progress with something like this.
> I needed it to abstract layers of functionality. for example trimming
> trailing spaces. If it should work as a transparent plugin it needs
> access to undo/redo.
IMO an abstract base class better should be a viewer, without text
manipulation commands. This would allow to sort out problems related to
undo/redo for debugging.
> My current approach is:
>
> - I separated SynEdit.Lines from the internal textbuffer (so textbuffer
> has no longer a need to be TStrings based (it still is, because i didn't
> take the time to change it))
The TStrings approach isn't really bad. The virtual Get method can
access any kind of buffer, and we don't have to introduce new names for
the basic methods and properties, reducing possible confusion of the
users of the component.
> - I add a few basic methods such as
> InsertText(x,y, substring); DeleteText,(x,y, len) ; BreakLine,
> JoinLine (maybe InsertNewLine, DeleteEntireLine) [*]
In my CharGrid I use a single basic function for insertion and deletion,
with the Len indicating insertion (> 0) or deletion (< 0). This delta
can be used to adjust the text size, also with undo/redo operations.
It might be necessary to distinguish clearly between display and text
positions, where display positions take into account folded blocks, tab
expansion etc., which only affect the display. While display coordinates
may be separated into row and column, other positions (bookmarks...)
better should be given as single text/file offsets. [Where IMO 32 bits
are sufficient for *text* file size/positions - a dedicated data type
will allow for eventual customization]
> - they can deal with undo and redo
> - In SynEdit all operations can be reduced to the above (and don't
> care about undo/redo)
The undo/redo capabilities can be encapsulated in the text buffer object
implementation, only the related methods have to be added to the
TStrings interface.
> Since TrailingSpaces is already a wrapper around the TextBuffer, it can
> simply intercept those methods, and deal with them.
Such a wrapper IMO disallows to change the trim option at runtime. I'd
implement it only in the display code.
> ----
> The only flaw I still have with this is, that currently all the
> SynEditText* (wrappers around the actual textbuffer, doing, spaces,
> tabs, folding....) are combining Display and Edit functionality.
>
> It would be nice to be able to write a TSynDisplay class first, and
> inherit the editor from it....
FACK
> [*]
> of course insertText could detect newlines, but it adds complexity. It
> will be simpler if SynEdit keeps control of this level, and InsertText,
> only operates on the current line
As mentioned above, a single text offset value is sufficient for all
text (buffer) operations. The text buffer must not necessarily be
organized by lines, the object *only* has to map between line numbers
and text positions for display references. Two such mapping functions
are required, one for absolute lines in the entire text (in the text
buffer object), and another one for virtual (folded) display row numbers
(in the block folding object).
DoDi
More information about the Lazarus
mailing list