[MonoDevelop] The new solution pad

Lluis Sanchez lluis@ximian.com
Mon, 14 Feb 2005 15:17:03 +0100


I'm working on the new solution pad, and I'd like to explain how I think
it should work.

The first design idea is to have a hierarchy of TreeNode classes, so we
would have ProjectNode, CombineNode, FileNode, AspFileNode and so on.

There are two reasons why I think this design is not so good.

      * This model is not extensible enough. It can be vertically
        extended easily, by adding new subclasses in the hierarchy (e.g.
        new project or file types), but it's difficult to extend
        horizontally. For example, an SVN addin would need to show a
        special icon overlay for ALL files locally modified, and there
        isn't an easy way to add this functionality to all existing
        FileNode classes.
      * With this design, for every node in the tree we have three
        objects: the internal gtk data structure, the data object that
        the node represents (e.g. the ProjectFile), and the TreeNode
        that links both. I think the last one is not necessary and we
        can save some memory avoiding it.

So, my idea is to have a set of Node Builders, instead of a hierarchy of
nodes. NodeBuilders can handle one specific type of data, or multiple
types of data, and can be chained to provide composite functionality.
NodeBuilder would have the following interface:

public abstract class NodeBuilder
	protected ITreeBuilderContext Context { get {...} }

	public abstract bool CanBuildNode (Type dataType);

	public Gdk.Pixbuf BuildIcon (Gdk.Pixbuf icon, object dataObject) {...}
	public string BuildLabel (string label, object dataObject) {...}
	public void BuildChildNodes (BuildContext ctx, object dataObject) {...}

	public DragOperation CanDrag (object dataObject) {...}
	public bool CanDrop (object dataObject, DragOperation operation) {...}
	public void OnDrop (object dataObject, DragOperation operation) {...}
	public virtual void OnSelect (object dataObject) {...}
	public virtual void OnAction (object dataObject) {...}

By implementing the CanBuildNode method, a NodeBuilder specifies the
kind of data to which it will be applied. The solution pad will create
and cache a chain of NodeBuilder objects for each data type (not for
each data object). All builders in a chain will be used to build the
node. For example, to build the tree node label, it will call BuildLabel
in sequence for all builders, so all of them will have a chance of
adding text to the label.

One important point about the design, is that it will not allow direct
changes on the tree hierarchy, such as adding arbitrary nodes or
modifying icons or labels. Only node builders are allowed to modify the
tree (by using the ITreeBuilderContext object). For example, the
AddReference command would add the reference to the project, but it
would not update the tree. It is the responsibility of the Project node
builder to subscribe to the ProjectReferenceAdded event and update the
tree when receiving that event. This is important to guarantee
consistency between the tree GUI and the project logic.

That's all for now. Comments are welcome.