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 parses a new document for it's line count, multi-line comments, longest line (maybe for foldable blocks as well). - with folding, it translates between document line and visible row numbers (not yet implemented). - it parses a given line for syntactic elements, setting the text attributes in the display line buffer. Painting a line requires multiple actions: - the viewport row is mapped into a document line (or vice versa). - the according text is retrieved and stored in the line buffer, with tab expansion, special character substitution and UTF translation if required, bookmarks etc. - the syntax highlighter fills in character attributes. - hyperlink attributes are updated, according to the mouse position. - the visible part of the line buffer is determined, depending on the viewport margins and wrapped lines. Then the text and gutter painters are invoked for the supplied line buffer, if their painting area is not clipped. The text painter determines sequences of same text attributes, initializes the canvas (DC) and paints the according characters. The prepared line buffers can be kept in an cache, so that a quick refresh can be made when the mouse moves over the hyperlinks in the current view. BTW, the top gutter can hold file tabs, or an ruler with column numbers, tab and margin markers. It must not exist at all, but when such an object is assigned to the grid, it's invoked in the appropriate situations. Multiple edit windows deserve an application wide (non-visual) file pool. A visual notebook can contain any subset of source files, so that both cannot be combined into one component. So much for now DoDi _______________________________________________ Lazarus mailing list [email protected] http://www.lazarus.freepascal.org/mailman/listinfo/lazarus
