Hans-Peter Diettrich wrote:
Best to always specify the context (logical / physical ). The painter is no separate itme in MVC, so it resides within the "View" too.Martin Friebe schrieb: 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) 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.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. 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. 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.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. 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 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 to a library providing the needed information. We then only need to concern ourself at which point we need to access this information. [ 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. 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) - 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 - 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 could either be internal part of the component or be given to it. Which one is the case should not matter for the design of the component. The component then retrieves the correct part(s) of the raw source, transforms it and paints it to the canvas Does this description makes sense? And we open other mail-threads for other topics? Undo definitely is an editor feature since it modifies the Model.Even if Undo functionality is added to the document source, this is nothing what the visual component should have to know or care about. In the MVC model it's the task of the controller, to submit user actions to the right place (object and method), where Undo, Folding, Insert etc. is implemented. The controller must know about all those details, but the viewer component only has to know how to obtain the text to display. It even must *not* know, whether the text can be edited by the user at all - it only must be aware of a Change message, indicating that the text has been changed, somehow. Folding I believe can be part of the Display-Component. (This is application of the folding info stored in the model) It has certain similarities with the Grid. The Grids purpos is to: Select text from the RawSource, and transform it in certain ways, like: Display whitespace, after a newline; or adjust position in the grid, after tabs Similar work is done by Folding or Wrapping. The change the selection (selection of what is visible), and transform it (wrapping may transform a logical line into several physical lines) The same applies for Tab expansion, The handling of DoubleDisplayWidth Char or merging of multicode points (provided they are known by access to a library) The component should also concern the application of highlighting or Markup information, provided it can retrieve it from the appropriate classes. (This will allow multiply Components to display the same Model , using different highlighters) The Keypress should be on the controller, the Display-Component does not need to be concerned with this.The controller reference can become another property of the final component, but for the first steps I left it to an OnKeyPress handler, to translate keystrokes into actions. E.g. my test application translates the cursor keys into scroll actions, and calls the according methods of the CharGrid. Stack refers to an implementation similar to a protocol stack (http://en.wikipedia.org/wiki/Protocol_stack) In this case the painter would talk to the lowest end of the stack, and the top end of the stack would access the Model. The Stack can have any amount of elements depending on which transformations are needed. The different to a list of transformers is: - in a list 2 neighbours would not necessarily know each others (they could, but that would almost make it a stack) - a list controller would be needed. The TSynEditMarkup* classes are an example of a list. In a list (as I see it) you ask the controller do to the task, the controller hands the request to the first list-member, then the controller takes the result to the next list member and so on. In a stack each element directly asks the next higher level for the information required. this allows each element to ask any (and any amount of) questions to the next higher level All we need is access to the Model. Origination, Location or Ownership can be left to implementation, and should be easy to change. As for the logical view. this does (in my description) not contain the controller. It describes what the class or classes that are concerned with the transformation of the RawSourceText into the a format suitable to the Painter (The grid in this case). Please see the attached Image, it's just a rough Idea, without much detailed design. (It only covers the TextDrawer (View in MVC), it does not cover Model or Controller) The "decorated TextDrawer would then have access to the Model. And the controller has access to all of this I was referring to the internals of the TextDrawer. I left model and Controller out of the game here. As you can see in the image, I divide the TextDrawer into 2 sets of classes. In terms of MVC this needs more clarification. I did put folding into the LogicalView (and therefore into the TextDrawer, which is the View of the MVC) Now of course, The TextDrawer does not store any of the data (model). Folding consists of 2 parts: - The information what is folded, which is part of the model (and modified by the controller) - The application of this data, to provide the correct output. It is the concern of the TextDrawer to apply this information. This gets as outside the Display-Model. A solution could be to have a ModularSynEdit (which has SourceModel Property) and an integrated SynEdit (which has it's own Model for compatibility with existing code) Seems we were discussing different things. I only discussed the internals of the TextDrawer. The file provider is seen in a special way from within each TextDrawer that accesses it. That should not limit it's interaction with any amount of Controllers. It also may be that your linked list, is what I refer to as stack? Can you please give me an example where an edit command is sent to the view? This is strictly between the Controller and the Model.The controller receives commands from a view or other source. From "other" source means that the command applies to the view in the active window. Then the controller sends scroll commands etc. (affecting only the view) immediately back to the view, translated into logical actions (scroll a page ahead, copy selection etc.). Edit commands (insert/delete) are sent to View.DataSource, or are performed immediatly The only exception, is that any edit command that is relative to the current display (such as a vertical block operation) does need feedback from the View. This is because the View determines which chars are vertically aligned. (This information is not available from the model) I think we were not so far apart in our solutions. Only we used different terminology.on that document, and after completion the active views of the updated document are notified of the changes. When the controller is invoked with keyboard input, then it must look for the according action in the key-map, and if no action is associated, inserts the character into the file, at the current (caret) position of the view. Do you understand now, why a multi-window editor deserves some strict logical (re)structuring of the current SynEdit component? Correct. No problem with that. Best regards Martin |
<<inline: textdrawer.gif>>
_______________________________________________ Lazarus mailing list [email protected] http://www.lazarus.freepascal.org/mailman/listinfo/lazarus
