Thread: Re: [Freemind-developer] FreeMind Design aspects (Page 2)
A premier mind-mapping software written in Java
Brought to you by:
christianfoltin,
danielpolansky
From: Dimitri P. <dpo...@gm...> - 2008-01-23 11:27:31
|
Ray, > It might be best to think about taking the refactoring in steps. I see it like you. The refactoring should be performed incrementally. The new design model however should be completed before we start with the refactoring itself. Afterwards we could define the steps. So in the proposed "Kernel-Extensions" design we could stepwise extract the properties from the kernel classes and move them to the property packages. Dimitry |
From: Ray B. <ray...@co...> - 2008-01-23 17:22:18
|
Dimitry, I agree with you that we need to understand where we are going before we start the refactoring. I'm not yet in agreement that we should go with a small kernel model for the new design. I'm not saying we shouldn't, it's just that the only designs that have been offered, so far, are stick to the old design, or go with a radical new small kernel design. Your design may turn out to be the best choice, but I don't know that, yet. A Mind Map Editor, which is what we have, is very different from an operating system or a browser. We should think about what the software is supposed to do, and evaluate each possible design based on those goals. Below is a partial example of the kind of analysis I'm talking about: -------- First, we identify the overall goals for our software: 1) Make it easy to create and edit mind maps: a) Each mind map is a single document b) Each node contains: * Text * User Defined Properties * A Time/Date Stamp for when it was created, and when it was last edited. * An optional Note * An edge coming from the parent node * (optional) Edges leading to any children nodes * pointers to children nodes * pointer to the parent node * formatting information c) The document starts with a single root node which cannot be deleted w/o destroying the document. d) The user should be able to create a child node with a single keystroke or mouse click. e) The user should be able to create a sibling node for any node, except the root, with a single key stroke or mouse click. 2) The user should have fine control over the grouping of nodes {Identify all possible grouping mechanisms, like clouds, and how they behave.} 3) The user should have fine control over the appearence of the mind map: a) The color, font, size, and formatting of text b) The color, style, and size of edges c) The color and style of clouds. General Principles 1) The most commonly performed operations should be one click or one key-stroke operations. 2) Our user interface should conform to generally accepted interface standards used in Windows and Linux applications. 3) The application behave in a consistent manner. For instance, if the user moves the application to one side of the window and closes it, the application should start back up in the same place it was closed, unless that is impossible. (For instance, if it was moved to a monitor that is no longer attached to the system.) Potential extensions 1) Add the ability to transform a given node into a root node. That would create a new document rooted by that node. All children nodes for the new root would be transfered into the new document. The new root node would be replaced in the current document by a proxy node, which would allow the node to be represented as a link to the document, or by replicating the graph of the document in the current mind map. -------- Basically, it's a design that is documenting the current capabilities of the system and additional features we consider important. I don't think we have to write down every detail, just enough that we're pretty sure we've covered the scope of tasks that the software is expected to accomplish. Once we have that, we can evaluate each new design proposal against our requirements, and determine which one helps us meet those requirements in the best way. One of the things that people have consistently praised about FreeMind is the speed with which you can work. I think we have to be careful when refactoring to make sure we don't sacrifice the responsiveness of the program for our users on older hardware, or, if we are going to make such a compromise, we make sure we tell them about it. If we try to make the kernel too small, we'll wind up using lazy loading for elements of the architecture that are used all the time. Ray Dimitri Polivaev wrote: > Ray, > > >> It might be best to think about taking the refactoring in steps. >> > > I see it like you. The refactoring should be performed incrementally. The new design model however should be completed before we start with the refactoring itself. Afterwards we could define the steps. > > So in the proposed "Kernel-Extensions" design we could stepwise extract the properties from the kernel classes and move them to the property packages. > > Dimitry > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Microsoft > Defy all challenges. Microsoft(R) Visual Studio 2008. > http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ > _______________________________________________ > Freemind-developer mailing list > Fre...@li... > https://lists.sourceforge.net/lists/listinfo/freemind-developer > > |
From: Dimitri P. <dpo...@gm...> - 2008-01-23 11:22:49
|
> * Where is the problem that the MindMapController is long? It is a > facade (see GOF) and offers all possible actions on the model in a > reliable and undoable way. So, it is clear that every change > action like setBold and setText is done via the MindMapController > derived from MindMapActions. > This is design by purpose as it is now clear what to do to change > the map. Before, this was difficult and the change methods were > spread all over the application. > The facade would be removed by your design proposal. My design proposal replaces one oversized controller by many independent property controllers which are easier to understand and to maintain. They could be facades for their packages. > * Who says, that a small kernel is the right for an application like > FreeMind? Only as the linux kernel is built like this? Linux, Eclipse and many other IDEs and other programs are developed in this way. Specifically for FreeMind: because Model, Controller and View for each single property like icon or node text are coupled stronger than e.g. Modells or Actions for differen independent properties, the splitting of the whole into independent parts can be done bewteen the properties themselves. > * An empty interface for extensions means that the main program > can't help the extension to achive its goals. The extension is > completely alone and responsible to do every work needed for it. > This contradicts my main goal, that it should be easy to write > extensions and that the main application should do the standard > work like registering at the menus and to give signals, when > important things happen. The Kernel should send only common property independent signals, see y previous mail for more. > * I tried to make the MindMapController smaller by taking a map with > String->Action pairs. But every access involved a casting then and > I rolled the changes back. The Castings and Access to Actions could be capseled in the property controllers e.g. Action IconController#someIconAction; void IconController#setStateIcons(MindMapNode, MindMapIcon); > * I started to implement the storage of notes inside the plugin. > Later, I saw that a lot of places need to change or to read the > notes texts and it was absolutely clear, that the notes content > must be available for everybody in the public model. > You are about to remove the items from the model. Thus, they are > not so easy to access. The access to the Note were as easy as String NoteController.getNoteText(MindMapNode node) { Note note = node.getExtensions().get(Note.class); return note != null ? note.toString() : null; } > So, let me state again my design goals: > > * It should be absolutely clear, how to change items in the model. > * It should be easy to implement extensions. Extensions typically > combine existing functionality in new ways users need them. > * It should be clear, how things/responsibilitys are divided. (Like > now, as the MindMapController is responsible to change/store the > model and the model is responsible to hold it). > > Summarizing, I see it very critical to have such a generic design setup > as you proposed. All your goals can be achieved by the proposed design. Dimitry > > Best regards, Chris |
From: Dimitry P. <dpo...@gm...> - 2008-01-15 21:06:10
Attachments:
Extensions.png
|
> where are you drawing the line between an > "extension", and just a "visitable" object? What "visitable" objects are > you thinking other than "extensions"? I think on viewer components registered by extensions at NodeView's content pane. They should not be referenced by their class name. That's why many elements of the same class can belong to the same VisitableCollection. (If want we have multiple views for one map, we are likely to have multiple viewers per node and extension property). Example (you see that I have changed the interfaces a bit, the new class diagram is attached to the mail. Further I have added a method MindMapNode NodeView#getNode()) public class AttributeExtensionController implements NodeViewLifeCycleObserver{ public void nodeViewCreated(ModeController controller, NodeView nodeView) { MindMapNode node = nodeView.getNode(); AttributeTableModel nodeAttributes = (AttributeTableModel)node.getExtensions().get(AttributeTableModel.class); if(nodeAttributes == null){ return; } AttributeTable attributes = new AttributeTable(nodeAttributes); nodeView.getContentPane().add(attributes); node.getObservers().add(attributes); } > Are you planning to go into a refactoring phase before this new design is > implemented? Because I think small things like these can often create an > extremely buggy solution if implemented later on, and I dont want to see > this project get there. Whatever we decide, I prefer to have that decision > early on and then stick with it from the very onset. I'd prefer if we > either decide to disable multiple windows/application instances altogether > (that would be simpler to do), or we decide to fully support it (what I'd > personally prefer) from the very point we start coding by this design. I would like to make as small steps as possible. I do not believe in final design, I believe in iterations. And I am no sure whether we should introduce additional complexity right now. IMHO after the refactoring is done, further changes can be introduced easier than now. >> I can remove both ModeController#getActiveMap() and >> ModeController#getActiveMapView(), because they rather belong to the >> ApplicationController (and they are already present there). > O, ok ... I somehow still can't find it in ApplicationController. Could > you give me the exact method name? I mean methods getSelectedXXX() and setSelectedXXX(...). (I have intentionally used other name for stimulating a discussion about what name is better: getActiveXXX() or getSelectedXXX() . > Right :-) Actually I realized this part when I was done writing the first > half, so I went on to add the 2nd half saying that such calls in MindMaps > should probably just wrap the ones provided by ModeController. > > Although redundant, I see it's value as clarifying the API. I mean if I > want to create new maps, or load them, I'd probably go looking for them in > the MindMap class. Similarly, if I want to save a map, a map.save call > would make a lot of sense. But something like > map.getModeController().save(this) would mean I'd have to go through > ModeController API, and nothing in the MindMap method list would tell me > that something by the name of 'getModeController' would actually let me > save this map. And even then I would be unsure about calling it, since I > wouldn't know if this was in fact the right method or is it supposed to be > an internal method meant to be called by some other method "really" meant > for the saving purpose. At least this *is* the kind of problem I first > faced a few days back when I joined in this project. Just a few wrappers > providing a more conventional interface would have made things easier on > me. Agreed. Dimitry |
From: Dimitry P. <dpo...@gm...> - 2008-01-15 21:53:06
Attachments:
Extensions.png
|
Next try :-). Dimitry |
From: Reasamp <re...@gm...> - 2008-01-17 18:15:50
|
>> where are you drawing the line between an >> "extension", and just a "visitable" object? What "visitable" objects are >> you thinking other than "extensions"? > > I think on viewer components registered by extensions at NodeView's > content pane. They should not be referenced by their class name. That's > why many elements of the same class can belong to the same > VisitableCollection. (If want we have multiple views for one map, we are > likely to have multiple viewers per node and extension property). Didn't quite get the kind of answer I was looking for, but lets see. For the rest of the class diagrams I could compare things with existing code base where things weren't being too clear. Here I can't do that. So lets see what happens as the details get filled in over time. Things should get clearer for me. > >> Are you planning to go into a refactoring phase before this new design >> is implemented? [...] > > I would like to make as small steps as possible. I do not believe in > final design, I believe in iterations. And I am no sure whether we > should introduce additional complexity right now. IMHO after the > refactoring is done, further changes can be introduced easier than now. > Na no final designs are coming up in open-source projects thats for sure. But the thing I was worried about, that during refactoring phase some other features do get added along as well ... so changes like these might as well be implemented as early on as possible before more code gets to depend on such things. but if things are purely/mostly refactoring, yes things can actually become easier. > I mean methods getSelectedXXX() and setSelectedXXX(...). (I have > intentionally used other name for stimulating a discussion about what > name is better: getActiveXXX() or getSelectedXXX() . Honestly, to me, either one is good. After an hour of reading through the API, I'd be used to either one. Probably not the answer you were looking for, but sorry :( > >> Right :-) Actually I realized this part when I was done writing the >> first >> half, so I went on to add the 2nd half saying that such calls in >> MindMaps >> should probably just wrap the ones provided by ModeController. >> >> [...] > > Agreed. > Thanks. Reasamp |
From: Ray B. <ray...@co...> - 2008-01-17 20:45:07
|
One of the problems with: all the right things but no more as you point out, is that different people want different things. The desired feature set for any given application grows with time. What might ultimately make the most sense, is for the application to keep track of what features are used the most frequently, and pre-cache any code or data that might take a while to load. Since very few user will use the whole feature set, this should give our users a much more satisfactory experience than if we let the whole application bloat up and hog memory or if we try to pick which functions we think will be used most. (Obviously, there will be a core set of functions we'll keep in memory because they are used by all the other functions.) I think that one focus in the future should be on pure interface issues. We want to make it as easy as possible to use FreeMind. That means we should make it easy for the user to understand what is happening at any given time, and make it easy work quickly. We also have to make the entire interface consistent, so the user doesn't have to learn a different set of rules for different parts of the program. Some of that work has already started and I think it's already improved the look and usability of the program. Ray Reasamp wrote: >> thanks for your questions. This week I have absolutely no time to >> answer, but I shall so it ASAP. In particular I am going to write about >> >> * goals of the proposed refactoring, >> * differences and similarities between eclipse and FreeMind, >> * advantages and disadvanteges of Lazy Loading for extensions. >> * extention mechanisms for menus, tool bars and other GUI elements. >> >> > Even before this mail, I simply assumed that these things would be coming > up as soon as you have the time:) Guess I can wait > But anyway, adv/disadv for lazy loading is something widely available in > Eclipse plugin whitepapers and tutorials all over the net. Don't think > documenting that out would be necessary if it is similar enough with > Eclipse (I mean, we do have other sources to figure that out). I'd rather > like to see that time spent in the details specific to Freemind, perhaps > with some short description of things from Eclipse if that helps to > establish the context. > > And about goals, I'd like to put in two notes about features loosely > related to goals. To me it seems that FreeMind needs to become an easily > accessible tool with just all the right things but no more. Trouble, > obviously, is that the right combination depends on the people. So as > number and complexity of features/plugins increase, we might want to ship > them as separate packages to keep the application look and be acceptably > lightweight. This means some simple but basic assumptions come under > consideration: > * We need a plugins manager. If I install a plugin which I dont like, I > need to be able to remove it. I'd like to be able to enable/disable > plugins/groups of plugins without actually going into the plugins folder > and moving them out. This in turn means the generic plugins interface will > provide enough information for such management. > * Plugin packages should not have to share the same directory as root > freemind installation. This is specially true if we intend 3rd parties to > develop plugins in the long run. This would, once again, enable me to > simply delete those additional files if I don't like them. Similarly, if > FreeMind is uninstalled/updated, plugin data should not be lost. So our > plugin discovery feature will need to be a bit robust. > > Reasamp > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Microsoft > Defy all challenges. Microsoft(R) Visual Studio 2008. > http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ > _______________________________________________ > Freemind-developer mailing list > Fre...@li... > https://lists.sourceforge.net/lists/listinfo/freemind-developer > > |
From: Reasamp <re...@gm...> - 2008-01-18 03:01:42
|
On Fri, 18 Jan 2008 02:44:22 +0600, Ray Benjamin <ray...@co...> wrote: > I think that one focus in the future should be on pure interface issues. > We want to make it as easy as possible to use FreeMind. Agreed! That is the first thing that got me into being a FreeMind user, and I'd want to stop using it the moment it gets messed up. But then again, I'm sure I can make a few contributions here and there to make sure that doesn't happen;) Reasamp |
From: Dimitry P. <dpo...@gm...> - 2008-01-23 23:02:01
|
Ray, The refactoring itself should not change any user interface or behavior issue. It just should create some significantly clearer and easier design open for future development. > I'm not yet in agreement that we should go with a > small kernel model for the new design. If we try to make > the kernel too small, we'll wind up using lazy loading for elements of > the architecture that are used all the time. It looks like I have expressed myself in a way leading to misunderstanding. I do not propose to extract any parts of functionality in plug-ins. The main purpose of the proposed design is reducing the complexity of the main MindMap, MindMapNode, Controller and ModeController classes by moving models, controllers (actions) and views of their different properties in different mutually independent classes and packages. For instance we could write > b) Each node contains: > * pointers to children nodes > * pointer to the parent node > * pointer to the map > * node formatting information (form and color) > * optional cloud formatting information (color) > * Text > * Text formatting information > * An optional Note > * Optional Icons and so-called state icons > (e.g. Attribute or Note icon) > * An edge coming from the parent node > * Edge formatting information > * A Time/Date Stamp for when it was created, and when it was last edited. > * Other properties like latex So I propose to use leave only the structural information in the MindMapNode: > * pointers to children nodes > * pointer to the parent node > * pointer to the map and create packages freemind.format.model freemind.format.controller.mindmapmode > * node formatting information (form and color) freemind.cloud.model freemind.cloud.controller.mindmapmode > * optional cloud formatting information (color) freemind.text.model freemind.text.controller.mindmapmode > * Text > * Text formatting information freemind.note.model freemind.note.controller.mindmapmode freemind.note.view.mindmapmode freemind.note.view.browsermode > * Note and so on. Changing or extending of such small packages with similar structure is much easier than handling and improvements of huge interfaces and classes we have without such structure today. The proposed Extension Object mechanism describes how specific property controller and model objects can be seamlessly attached to the "main" controller and model objects so that the program performance is not noticeable decreased. Dimitry |
From: Ray B. <ray...@co...> - 2008-01-24 01:36:14
|
Thank you, Dimitry, this makes a lot more sense to me, and seems fine. I'll probably have more questions, later, but then, I always do. :) Ray Dimitry Polivaev wrote: > Ray, > > The refactoring itself should not change any user interface or behavior > issue. It just should create some significantly clearer and easier > design open for future development. > > >> I'm not yet in agreement that we should go with a >> small kernel model for the new design. If we try to make >> the kernel too small, we'll wind up using lazy loading for elements of >> the architecture that are used all the time. >> > > It looks like I have expressed myself in a way leading to > misunderstanding. I do not propose to extract any parts of functionality > in plug-ins. The main purpose of the proposed design is reducing the > complexity of the main MindMap, MindMapNode, Controller and > ModeController classes by moving models, controllers (actions) and views > of their different properties in different mutually independent classes > and packages. > > For instance we could write > > >> b) Each node contains: >> * pointers to children nodes >> * pointer to the parent node >> * pointer to the map >> * node formatting information (form and color) >> > > * optional cloud formatting information (color) > >> * Text >> > > * Text formatting information > > * An optional Note > > * Optional Icons and so-called state icons > > (e.g. Attribute or Note icon) > >> * An edge coming from the parent node >> * Edge formatting information >> * A Time/Date Stamp for when it was created, and when it was last edited. >> * Other properties like latex >> > > So I propose to use leave only the structural information in the > > MindMapNode: > > * pointers to children nodes > > * pointer to the parent node > > * pointer to the map > > and create packages > > freemind.format.model > freemind.format.controller.mindmapmode > > * node formatting information (form and color) > > freemind.cloud.model > freemind.cloud.controller.mindmapmode > > * optional cloud formatting information (color) > > freemind.text.model > freemind.text.controller.mindmapmode > > * Text > > * Text formatting information > > freemind.note.model > freemind.note.controller.mindmapmode > freemind.note.view.mindmapmode > freemind.note.view.browsermode > > * Note > > and so on. > > Changing or extending of such small packages with similar structure is > much easier than handling and improvements of huge interfaces and > classes we have without such structure today. > > The proposed Extension Object mechanism describes how specific property > controller and model objects can be seamlessly attached to the "main" > controller and model objects so that the program performance is not > noticeable decreased. > > Dimitry > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Microsoft > Defy all challenges. Microsoft(R) Visual Studio 2008. > http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ > _______________________________________________ > Freemind-developer mailing list > Fre...@li... > https://lists.sourceforge.net/lists/listinfo/freemind-developer > > |
From: Reasamp <re...@gm...> - 2008-01-24 03:44:15
|
Thank you! I was starting to get the "left out of it" feeling all this time, since I mixed up these "Extensions" being talked about with "plugins" as they are. Makes a LOT more sense now! By the way, if a design similar to this gets accepted, could we make this particular email a part of the official docs?? Would help a lot of people. Reasamp On Thu, 24 Jan 2008 05:02:06 +0600, Dimitry Polivaev <dpo...@gm...> wrote: > MindMapNode: > > * pointers to children nodes > > * pointer to the parent node > > * pointer to the map > > and create packages > > freemind.format.model > freemind.format.controller.mindmapmode > > * node formatting information (form and color) > > freemind.cloud.model > freemind.cloud.controller.mindmapmode > > * optional cloud formatting information (color) > > freemind.text.model > freemind.text.controller.mindmapmode > > * Text > > * Text formatting information > > freemind.note.model > freemind.note.controller.mindmapmode > freemind.note.view.mindmapmode > freemind.note.view.browsermode > > * Note > > and so on. > > Changing or extending of such small packages with similar structure is > much easier than handling and improvements of huge interfaces and > classes we have without such structure today. > > The proposed Extension Object mechanism describes how specific property > controller and model objects can be seamlessly attached to the "main" > controller and model objects so that the program performance is not > noticeable decreased. > > Dimitry |
From: Reasamp <re...@gm...> - 2008-01-25 06:45:59
|
Dimitri, (Sorry if I got it wrong, but I'm still not sure if you spell your name with a 'y' or 'i' at the end) Just wanted a little clarification: How are we planning to handle extension packages with a high degree of dependancy? For example, say we have an extension for 'Cloud' and another for 'DropShadowText', and yet another for a 'BlackStrikeThrough'. Now if a particular node has all these effects, we have to make sure that the effects are rendered in the right order (Cloud,ShadowText,Strike) or else they overdraw one another. How are these dependancies planned to be handled? This could apply to other non-formatting dependencies as well, like if one extension sets a particular attribute and another uses that attribute for formatting, then the setter should run before the formatter. Reasamp On Thu, 24 Jan 2008 05:02:06 +0600, Dimitry Polivaev <dpo...@gm...> wrote: > > b) Each node contains: > > * pointers to children nodes > > * pointer to the parent node > > * pointer to the map > > * node formatting information (form and color) > > * optional cloud formatting information (color) > > * Text > > * Text formatting information > > * An optional Note > > * Optional Icons and so-called state icons > > (e.g. Attribute or Note icon) > > * An edge coming from the parent node > > * Edge formatting information > > * A Time/Date Stamp for when it was created, and when it > was > last edited. > > * Other properties like latex > > So I propose to use leave only the structural information in the > > MindMapNode: > > * pointers to children nodes > > * pointer to the parent node > > * pointer to the map > > and create packages > > freemind.format.model > freemind.format.controller.mindmapmode > > * node formatting information (form and color) > > freemind.cloud.model > freemind.cloud.controller.mindmapmode > > * optional cloud formatting information (color) > > freemind.text.model > freemind.text.controller.mindmapmode > > * Text > > * Text formatting information > > freemind.note.model > freemind.note.controller.mindmapmode > freemind.note.view.mindmapmode > freemind.note.view.browsermode > > * Note > > and so on. > |
From: Dimitri P. <dpo...@gm...> - 2008-01-25 13:45:57
|
Reasamp, > Dimitri, I'm still not sure if you spell your name > with a 'y' or 'i' at the end I would prefer the 'y'. > How are we planning to handle extension packages with a high degree of > dependancy? For example, say we have an extension for 'Cloud' and another > for 'DropShadowText', and yet another for a 'BlackStrikeThrough'. Now if a > particular node has all these effects, we have to make sure that the > effects are rendered in the right order (Cloud,ShadowText,Strike) or else > they overdraw one another. How are these dependancies planned to be > handled? This could apply to other non-formatting dependencies as well, > like if one extension sets a particular attribute and another uses that > attribute for formatting, then the setter should run before the formatter. Thank you for your very good questions, which have not been discussed until now. If I understand you correct, it is all about how different node properties are rendered in a right way. I could propose a solution which I believe to be easy and pragmatic. The standard node rendering components (NodeView) should not have extensions like model or controller components. They always own one MainView component for painting of the node's form, text, icons, background and selection background. The MainViews depend on many node property packages (as they interpret text, font, color, icons), but they only read them and do not change them directly. The NodeViews are responsible for its own layout including positioning of the child nodes and painting of the clouds and the outcoming edges. (It means that they can read the information from appropriate node extension objects like node shifts, clouds or edges). They can be extended by adding further rendering components like AttributeTable or Latex Viewer (HotEqn) coming from extensions, which also are usual awt or swing components (JComponent) painting themselves. So attaching and painting of arbitrary new node property elements is possible. You see that design of the rendering component packages is a bit different from the design of the model or controller packages. IMHO it is so because * the renderer components are usually derived from JComponent or awt.Component, * they are quite memory intensive, * they essential task of the rendering component is the rendering of the effects in the right order, * complexity of the rendering component is smaller than complexity of the controller packages with all actions and listeners defined there, and they do not have to be split Dimitry |
From: Dimitry P. <dpo...@gm...> - 2008-01-26 07:09:28
|
> Actually my question was about how extensions would communicate with each > other should that be necessary, I used rendering merely as an example. In general assume extension A depends on operations and properties declared in extension I, e.g. an attribute extension wants that the node displays an attribute icon. For this purpose it could use a public method of the controller of the icon extension IconController#setStateIcon(MindMapNode node, ImageIcon icon). The icon controller itself could be obtained from the ModeController e.g. by ModeController.get(IconController.class) . If you had define another example, I could use it either. >> they essential task of the rendering component is the rendering of the >> effects in the right order, > How are we ensuring that the different extended components do not overlap > each other? Is this automatically taken care of by LayoutManagers? How could differently extended components overlap? I do not understand you. Yes, layout managers are responsible for overlap free node placement. > I just went through the NodeView class. I'm not sure if you'd agree, but > seemed like a good place to start refactoring :) I am not sure if refactoring should START with refactoring of the viewers. I would start with the models. But you are welcome to put your ideas on the table. I am looking forward to know them. Dimitry |
From: Reasamp <re...@gm...> - 2008-01-26 17:02:08
|
Thanks, I think you have mostly addressed all my queries. The part I am worried about is how tightly things are currently coupled into the Swing library. Although there IS a separation, if we ever think about using some other rendering technique/API, something tells me we will have to work hard. And that is bound to happen sooner or later. (Pls tell me if this is not the case) In fact, since JComponents are quite memory-intensive, this can become a problem very easily with large maps. If a user prefers to keep all his work in one single large map on different branches (as opposed to making new maps out of the larger branches), I have seen Freemind become somewhat hard to handle. It's rendering starts to fail in certain places, certain features no longer work (notably PDF export) etc. This happens at around 4000 visible nodes - a high number for sure, but can easily be reached if someone hits "Expand All" after about a year. So we might actually have to leave JComponent-based rendering sometime soon. I am not suggesting that we do this right now, but we should keep provisions in our designs now so that we can make such changes in a relatively painless way. Just keeping an eye that however we design, removing JComponent dependency should be easy. I do have some ideas now, and I hope to be able to make a rough sketch of necessary plans in a few days time. In the mean time, please suggest if I should change any part of my opinions here. Reasamp |
From: Dimitry P. <dpo...@gm...> - 2008-01-27 19:41:39
|
> * The ModeController.createMap method seems to be static, since it takes > ModeController object as a parameter (although not shown so in the > diagram). But interfaces cannot have static methods. You are right, I have not considered the method to be static and I should remove the parameter. > * ModeController also have saveMap/loadMap methods. Do you expect these > methods to have different implementations in different mode controllers? > Otherwise wouldn't it be better to make them static methods of some > separate, globally accessible class? Yes, for instance freemind now has a so-called file mode where file system is shown and can be navigated as a mind map, but there is no legal "save" operation. > * There are 4 different Observer classes shown on the same page. It does > not seem to mention which class has the "add*Observer" methods. In case > ModeController was intended, doesn't it seem unusual that someone trying > to listen for such events would be required to register the listener to > every single active ModeController implementation? Once again, it does > seem like firing/managing such listeners could be done from a separate, > globally accessible object. I have in mind that the extensions added to the mode controller (as it is an ExtensionCollection) could automatically become the listener if they implement the required interfaces. The reason for it is that the extensions of the mode controller are property controller responsible for creating/loading/saving/deleting of the property objects. Dimitry |
From: Dimitry P. <dpo...@gm...> - 2008-01-28 08:42:26
|
>>> * ModeController also have saveMap/loadMap methods. Do you expect these >>> methods to have different implementations in different mode controllers? >>> Otherwise wouldn't it be better to make them static methods of some >>> separate, globally accessible class? >> Yes, for instance freemind now has a so-called file mode where file >> system is shown and can be navigated as a mind map, but there is no >> legal "save" operation. > Since not all ModeControllers would implement it, wouldn't it be better to > move them elsewhere? I was thinking maybe we could make them static > members of a separate class named MapXML or something providing these two > functions as static utility functions - the idea being that these are the > only two functions that defines our XML format for ".mm" files. That way: > * The ModeControllers who do support save/load can simply define > wrappers to indicate these maps are saveable (maybe they will implement an > interface named SaveableMaps) > * The ModeControllers who do NOT support them can still use them as an > "Export as FreeMind Maps" option to save a copy of the current state of > mindmap as it exists into a normal-mode mindmap. I see that implementation of the methods could delegate them to some other objects. I do not understand why such methods should be static. >>> * There are 4 different Observer classes shown on the same page. It does >>> not seem to mention which class has the "add*Observer" methods. In case >>> ModeController was intended, doesn't it seem unusual that someone trying >>> to listen for such events would be required to register the listener to >>> every single active ModeController implementation? Once again, it does >>> seem like firing/managing such listeners could be done from a separate, >>> globally accessible object. >> I have in mind that the extensions added to the mode controller (as it >> is an ExtensionCollection) could automatically become the listener if >> they implement the required interfaces. The reason for it is that the >> extensions of the mode controller are property controller responsible >> for creating/loading/saving/deleting of the property objects. > I see. One thing though, doesn't that mean identical copies of observer > registry (list of observers) are being separately maintained in the > different ModeControllers. I know this is not a huge performance issue, > but the reason I'm pointing this out is this: I was planning a new design > where some core classes would hook in as observers as well. That will > probably force me back to manually register listeners to every > ModeController, or keep an "extension component" for these core classes as > well which will have its hook points automatically by this method. Neither > of them sounds good. I have provided an extra observer collection for models but not for controllers, and you could introduce an observer collection for controllers too. Dimitry |
From: Dimitry P. <dpo...@gm...> - 2008-01-28 18:59:07
|
> I was thinking single, globally accessible methods, and static > methods are the ones that come to my mind first. Methods of Singleton > objects are also another alternative... We have already had a discussion about singletons at this list. I have proposed to use them, but I changed my opinion because of the following argument: > I've certainly seen places where singletons have been abused, which > can lead to big problems, since some people treat them as permission > to establish all kinds of essentially global variables. I've found > them to be pretty useful, as long as I only used them where they fit > the problem I was trying to solve. > > Thanks, Ray In the discussed case I do not see why those methods should be available across all levels and objects. Dimitry. |
From: Reasamp <re...@gm...> - 2008-01-29 14:25:09
|
Na that sounds ok, since I wasn't too inclined about Singletons either - it is true that abuse is possible. > In the discussed case I do not see why those methods should be available > across all levels and objects. Ok, first let me make sure we are talking about the same context here: // --- start of code snippets --- public interface ModeController implements [...] { [...other methods...] public MindMap createMap(); public void closeMap(); /* save/load methods NOT declared here since not all/most ModeControllers are expected to support it. So it should not, for example, be possible to invoke saveMap or loadMap methods on arbitrary ModeController objects without proper casting. */ } public interface SaveableMapsModeController extends ModeController { public void saveMap(MindMap,Writer); public void loadMap(MindMap,Reader); } public class DefaultModeController implements SaveableMapsModeController { [... other methods ...] public void saveMap(MindMap map,Writer out) { MapXML.saveMap(map,out); } public void loadMap(MindMap map,Reader in ) { MapXML.loadMap(map,in ); } } public class MapXML { public static void saveMap(MindMap,Writer) { ... actual implementation ... } public static void loadMap(MindMap,Reader) { ... actual implementation ... } } // ---- End of code --- Firstly, if they are not made static, the only difference I see is the addition of a few "new MapXML()" statements. It exposes the exactly same set of methods either way, so there is no encapsulation problems raised explicitly by "static". And by making these functions publicly available, we allow the kind of "Export MM file" to directly use them. Secondly, saveMap/loadMap is a process that really does not depend on the actual ModeController being used. They do not modify the states of any object, does not access any global variable in MapXML, or anything else. Objects usually have a state. Reasamp |
From: Reasamp <re...@gm...> - 2008-01-26 03:53:48
|
> Thank you for your very good questions, which have not been discussed > until now. If I understand you correct, it is all about how different > node properties are rendered in a right way. Actually my question was about how extensions would communicate with each other should that be necessary, I used rendering merely as an example. But the fact that rendering components have a slightly different architecture probably means me using this example was misplaced :) Anyway, since the rendering issue came up, and as I understand it the way you are proposing it is exactly how it is implemented right now, let me put in two points to note: > they essential task of the rendering component is the rendering of the > effects in the right order, How are we ensuring that the different extended components do not overlap each other? Is this automatically taken care of by LayoutManagers? and secondly, I just went through the NodeView class. I'm not sure if you'd agree, but seemed like a good place to start refactoring :) Reasamp |
From: Reasamp <re...@gm...> - 2008-01-27 18:38:17
|
Dimitry I was trying to set up the plans for a completely new system for map rendering to make it independent from the other core classes. In the process I came across a few more questions (I guess asking question has been all I've been doing so far). They all concern the original class diagrams you posted in PDF two weeks back: * The ModeController.createMap method seems to be static, since it takes ModeController object as a parameter (although not shown so in the diagram). But interfaces cannot have static methods. * ModeController also have saveMap/loadMap methods. Do you expect these methods to have different implementations in different mode controllers? Otherwise wouldn't it be better to make them static methods of some separate, globally accessible class? * There are 4 different Observer classes shown on the same page. It does not seem to mention which class has the "add*Observer" methods. In case ModeController was intended, doesn't it seem unusual that someone trying to listen for such events would be required to register the listener to every single active ModeController implementation? Once again, it does seem like firing/managing such listeners could be done from a separate, globally accessible object. Reasamp |
From: Ray B. <ray...@co...> - 2008-01-28 11:16:29
|
Reasamp, Most of my job, so far, seems to have been asking questions. Your questions have been helping me understand the design better, so you're not the only one benefiting from them. In addition, questions, like these, that help clarify issues and improve the design, help us all. Ray Reasamp wrote: > Dimitry > I was trying to set up the plans for a completely new system for map > rendering to make it independent from the other core classes. In the > process I came across a few more questions (I guess asking question has > been all I've been doing so far). They all concern the original class > diagrams you posted in PDF two weeks back: > * The ModeController.createMap method seems to be static, since it takes > ModeController object as a parameter (although not shown so in the > diagram). But interfaces cannot have static methods. > * ModeController also have saveMap/loadMap methods. Do you expect these > methods to have different implementations in different mode controllers? > Otherwise wouldn't it be better to make them static methods of some > separate, globally accessible class? > * There are 4 different Observer classes shown on the same page. It does > not seem to mention which class has the "add*Observer" methods. In case > ModeController was intended, doesn't it seem unusual that someone trying > to listen for such events would be required to register the listener to > every single active ModeController implementation? Once again, it does > seem like firing/managing such listeners could be done from a separate, > globally accessible object. > > Reasamp > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Microsoft > Defy all challenges. Microsoft(R) Visual Studio 2008. > http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ > _______________________________________________ > Freemind-developer mailing list > Fre...@li... > https://lists.sourceforge.net/lists/listinfo/freemind-developer > > |
From: Reasamp <re...@gm...> - 2008-01-28 03:14:08
|
On Mon, 28 Jan 2008 01:41:46 +0600, Dimitry Polivaev <dpo...@gm...> wrote: >> * ModeController also have saveMap/loadMap methods. Do you expect these >> methods to have different implementations in different mode controllers? >> Otherwise wouldn't it be better to make them static methods of some >> separate, globally accessible class? > > Yes, for instance freemind now has a so-called file mode where file > system is shown and can be navigated as a mind map, but there is no > legal "save" operation. Since not all ModeControllers would implement it, wouldn't it be better to move them elsewhere? I was thinking maybe we could make them static members of a separate class named MapXML or something providing these two functions as static utility functions - the idea being that these are the only two functions that defines our XML format for ".mm" files. That way: * The ModeControllers who do support save/load can simply define wrappers to indicate these maps are saveable (maybe they will implement an interface named SaveableMaps) * The ModeControllers who do NOT support them can still use them as an "Export as FreeMind Maps" option to save a copy of the current state of mindmap as it exists into a normal-mode mindmap. >> * There are 4 different Observer classes shown on the same page. It does >> not seem to mention which class has the "add*Observer" methods. In case >> ModeController was intended, doesn't it seem unusual that someone trying >> to listen for such events would be required to register the listener to >> every single active ModeController implementation? Once again, it does >> seem like firing/managing such listeners could be done from a separate, >> globally accessible object. > > I have in mind that the extensions added to the mode controller (as it > is an ExtensionCollection) could automatically become the listener if > they implement the required interfaces. The reason for it is that the > extensions of the mode controller are property controller responsible > for creating/loading/saving/deleting of the property objects. I see. One thing though, doesn't that mean identical copies of observer registry (list of observers) are being separately maintained in the different ModeControllers. I know this is not a huge performance issue, but the reason I'm pointing this out is this: I was planning a new design where some core classes would hook in as observers as well. That will probably force me back to manually register listeners to every ModeController, or keep an "extension component" for these core classes as well which will have its hook points automatically by this method. Neither of them sounds good. Reasamp |
From: Reasamp <re...@gm...> - 2008-01-28 17:36:49
|
> I see that implementation of the methods could delegate them to some > other objects. I do not understand why such methods should be static. Sorry, I didn't really put that much thought into that one word (static) :) But seriously, I was thinking single, globally accessible methods, and static methods are the ones that come to my mind first. Methods of Singleton objects are also another alternative, but I didn't see the need for them. I did not see much need to modify/extend its behavior without having to change any of those new methods. > I have provided an extra observer collection for models but not for > controllers, and you could introduce an observer collection for > controllers too. Ok, thanks. Reasamp |