1.1 --- a/apisupport/src/org/netbeans/modules/apisupport/resources/templates/Nodes_API/__Sample_container__Children_java Sat Jan 11 01:38:19 2003 +0000
1.2 +++ b/apisupport/src/org/netbeans/modules/apisupport/resources/templates/Nodes_API/__Sample_container__Children_java Sat Jan 11 03:19:29 2003 +0000
1.3 @@ -4,61 +4,50 @@
1.4
1.5 import org.openide.nodes.*;
1.6
1.7 -/** List of children of a containing node.
1.8 +/**
1.9 + * List of children of a containing node.
1.10 + * Each child node is represented by one key from some data model.
1.11 * Remember to document what your permitted keys are!
1.12 - *
1.13 + * Edit this template to work with the classes and logic of your data model.
1.14 * @author __USER__
1.15 */
1.16 -public class __Sample_container__Children extends Children.Keys {
1.17 +public class __Sample_container__Children extends Children.Keys implements MyDataListener {
1.18
1.19 - /** Optional holder for the keys, to be used when changing them dynamically. */
1.20 - protected List myKeys;
1.21 + private final MyDataModel model;
1.22
1.23 - public __Sample_container__Children() {
1.24 - myKeys = null;
1.25 + public __Sample_container__Children(MyDataModel model) {
1.26 + this.model = model;
1.27 }
1.28
1.29 protected void addNotify() {
1.30 super.addNotify();
1.31 - if (myKeys != null) return;
1.32 - myKeys = new LinkedList();
1.33 - // add whatever keys you need
1.34 - setKeys(myKeys);
1.35 + // set the children to use:
1.36 + updateKeys();
1.37 + // and listen to changes in the model too:
1.38 + model.addModelListener(this);
1.39 + }
1.40 +
1.41 + private void updateKeys() {
1.42 + // get your keys somehow from the data model:
1.43 + MyDataElement[] keys = model.getChildren();
1.44 + // you can also use Collection rather than an array
1.45 + setKeys(keys);
1.46 }
1.47
1.48 protected void removeNotify() {
1.49 - myKeys = null;
1.50 + model.removeModelListener(this);
1.51 setKeys(Collections.EMPTY_SET);
1.52 super.removeNotify();
1.53 }
1.54
1.55 protected Node[] createNodes(Object key) {
1.56 // interpret your key here...usually one node generated, but could be zero or more
1.57 - return new Node[] {new MyNode((MyParameter)key)};
1.58 + return new Node[] {new MyNode((MyDataElement)key)};
1.59 }
1.60
1.61 - /** Optional accessor method for the keys, for use by the container node or maybe subclasses. */
1.62 - /*
1.63 - protected addKey(Object newKey) {
1.64 - // Make sure some keys already exist:
1.65 - addNotify();
1.66 - myKeys.add(newKey);
1.67 - // Ensure that the node(s) is displayed:
1.68 - refreshKey(newKey);
1.69 + public void modelChanged(MyModelEvent ev) {
1.70 + // your data model changed, so update the children to match:
1.71 + updateKeys();
1.72 }
1.73 - */
1.74 -
1.75 - /** Optional accessor method for keys, for use by the container node or maybe subclasses. */
1.76 - /*
1.77 - protected void setKeys(Collection keys) {
1.78 - myKeys = new LinkedList();
1.79 - myKeys.addAll(keys);
1.80 - super.setKeys(keys);
1.81 - }
1.82 - */
1.83 -
1.84 - // Could also write e.g. removeKey to be used by the nodes in this children.
1.85 - // Or, could listen to changes in their status (NodeAdapter.nodeDestroyed)
1.86 - // and automatically remove them from the keys list here. Etc.
1.87
1.88 }
2.1 --- a/apisupport/src/org/netbeans/modules/apisupport/resources/templates/Nodes_API/__Sample_container__Node_java Sat Jan 11 01:38:19 2003 +0000
2.2 +++ b/apisupport/src/org/netbeans/modules/apisupport/resources/templates/Nodes_API/__Sample_container__Node_java Sat Jan 11 03:19:29 2003 +0000
2.3 @@ -6,14 +6,19 @@
2.4 import org.openide.util.NbBundle;
2.5 import org.openide.util.actions.SystemAction;
2.6
2.7 -/** A node with some children.
2.8 - *
2.9 +/**
2.10 + * A node with some children.
2.11 + * The children are controlled by some underlying data model.
2.12 + * Edit this template to work with the classes and logic of your data model.
2.13 * @author __USER__
2.14 */
2.15 public class __Sample_container__Node extends AbstractNode {
2.16
2.17 - public __Sample_container__Node() {
2.18 - super(new __NAME$Node$Children$MyChildren__());
2.19 + private final MyDataModel model;
2.20 +
2.21 + public __Sample_container__Node(MyDataModel model) {
2.22 + super(new __NAME$Node$Children$MyChildren__(model));
2.23 + this.model = model;
2.24 setIconBase("__PACKAGE_AND_NAME_SLASHES$Node$NodeIcon$MyIcon__");
2.25 // Whatever is most relevant to a user:
2.26 setDefaultAction(SystemAction.get(PropertiesAction.class));
2.27 @@ -26,10 +31,11 @@
2.28 getCookieSet().add(new OpenCookie() {
2.29 public void open() {
2.30 // Open something useful...
2.31 + // typically using the data model.
2.32 }
2.33 });
2.34 */
2.35 - // Make reorderable:
2.36 + // Make reorderable (typically will pass in the data model):
2.37 // getCookieSet().add(new ReorderMe());
2.38 }
2.39
2.40 @@ -65,15 +71,11 @@
2.41 // return new HelpCtx(__NAME__.class);
2.42 }
2.43
2.44 - protected __NAME$Node$Children$MyChildren__ get__NAME$Node$Children$MyChildren__() {
2.45 - return (__NAME$Node$Children$MyChildren__)getChildren();
2.46 - }
2.47 -
2.48 // RECOMMENDED - handle cloning specially (so as not to invoke the overhead of FilterNode):
2.49 /*
2.50 public Node cloneNode() {
2.51 // Try to pass in similar constructor params to what you originally got:
2.52 - return new __NAME__();
2.53 + return new __NAME__(model);
2.54 }
2.55 */
2.56
2.57 @@ -84,15 +86,16 @@
2.58 // from the root node, traversed by Node.name.
2.59 /*
2.60 public Node.Handle getHandle() {
2.61 - return new __NAME$Node$Handle$NodeHandle__();
2.62 + return new __NAME$Node$Handle$NodeHandle__(model);
2.63 }
2.64 private static final class __NAME$Node$Handle$NodeHandle__ implements Node.Handle {
2.65 private static final long serialVersionUID = 1L;
2.66 - public __NAME$Node$Handle$NodeHandle__() {
2.67 - // store any state for the node as nontransient instance fields...
2.68 + private MyDataModel model; // must be serializable for this to work of course!
2.69 + public __NAME$Node$Handle$NodeHandle__(MyDataModel model) {
2.70 + this.model = model;
2.71 }
2.72 public Node getNode() throws IOException {
2.73 - return new __NAME__();
2.74 + return new __NAME__(model);
2.75 }
2.76 }
2.77 */
2.78 @@ -107,6 +110,7 @@
2.79 props = Sheet.createPropertiesSet();
2.80 sheet.put(props);
2.81 }
2.82 + // Typically will pass the model to the property classes:
2.83 props.put(new MyProp(someParams));
2.84 return sheet;
2.85 }
2.86 @@ -124,10 +128,11 @@
2.87 // return __NAME__.class.getName() + ".newType";
2.88 // }
2.89 public void create() throws IOException {
2.90 - // do whatever you need, e.g.:
2.91 - get__NAME$Node$Children$MyChildren__().addKey(someNewKey);
2.92 - // Throw an IOException if you are creating an underlying
2.93 - // object and this fails.
2.94 + // Normally implemented by prompting the user with a dialog
2.95 + // for some information; then creating and adding a new element
2.96 + // with those parameters to the data model. This should cause the
2.97 + // children to update automatically because of its listener.
2.98 + // throw IOException if the data model operation fails.
2.99 }
2.100 }
2.101 };
2.102 @@ -155,10 +160,8 @@
2.103 // Node n = NodeTransfer.node(t, NodeTransfer.COPY);
2.104 // Node[] ns = NodeTransfer.nodes(t, NodeTransfer.MOVE);
2.105 // MyCookie cookie = (MyCookie)NodeTransfer.cookie(t, NodeTransfer.COPY, MyCookie.class);
2.106 - // do something, e.g.:
2.107 - get__NAME$Node$Children$MyChildren__().addKey(data);
2.108 - // Throw an IOException if you are creating an underlying
2.109 - // object and this fails.
2.110 + // do something, typically involving the data model...
2.111 + // throw IOException if the data model operation fails.
2.112 // To leave the clipboard as is:
2.113 return null;
2.114 // To clear the clipboard:
2.115 @@ -179,9 +182,18 @@
2.116 return true;
2.117 }
2.118 public void setName(String nue) {
2.119 - // Update visible name, fire property changes:
2.120 - super.setName(nue);
2.121 - // perform additional actions, i.e. rename underlying object
2.122 + // Typically implemented by changing the name of an element from an underlying
2.123 + // data model. This node class should be listening to changes in the name of the
2.124 + // element and calling super.setName when it notices any (or better, override getName
2.125 + // and perhaps getDisplayName and call fireNameChange).
2.126 + // For example, you might write this method as:
2.127 + // model.setName(nue);
2.128 + // where you would also have:
2.129 + // public String getName() {return model.getName();}
2.130 + // and in the constructor, if __NAME__ implements ModelListener:
2.131 + // model.addModelListener((ModelListener)WeakListener.create(ModelListener.class, this, model));
2.132 + // where the interface is implemented as:
2.133 + // public void modelChanged(ModelEvent ev) {fireNameChange(null, null);}
2.134 }
2.135 */
2.136
2.137 @@ -191,10 +203,12 @@
2.138 return true;
2.139 }
2.140 public void destroy() throws IOException {
2.141 - // Actually remove the node itself and fire property changes:
2.142 - super.destroy();
2.143 - // perform additional actions, i.e. delete underlying object
2.144 - // (and don't forget about objects represented by your children!)
2.145 + // Typically implemented by removing an element from an underlying data model.
2.146 + // For example, you might write this method as:
2.147 + // model.getParentModel().removeSubModel(model);
2.148 + // The parent container children should be listening to the model, notice
2.149 + // the removal, set a new key list without this data element, and thus
2.150 + // remove this node from its children list.
2.151 }
2.152 */
2.153
2.154 @@ -211,6 +225,7 @@
2.155 ExTransferable et = ExTransferable.create(super.clipboardCopy());
2.156 et.put(new ExTransferable.Single(DataFlavor.stringFlavor) {
2.157 protected Object getData() {
2.158 + // typically based on the data model, but for example:
2.159 return __NAME__.this.getDisplayName();
2.160 }
2.161 });
2.162 @@ -224,6 +239,7 @@
2.163 // and it is not safe to assume that getData will only be called once):
2.164 et.put(new ExTransferable.Single(DataFlavor.stringFlavor) {
2.165 protected Object getData() {
2.166 + // typically based on the data model, but for example:
2.167 return __NAME__.this.getDisplayName();
2.168 }
2.169 });
2.170 @@ -237,6 +253,7 @@
2.171 return true;
2.172 }
2.173 public Component getCustomizer() {
2.174 + // will typically be passed the data model to customize:
2.175 return new MyCustomizingPanel(this);
2.176 }
2.177 */
2.178 @@ -260,12 +277,15 @@
2.179 // of the Index cookie.
2.180 public void reorder(int[] perm) {
2.181 // Remember: {2, 0, 1} cycles three items forwards.
2.182 - List old = __NAME__.this.get__NAME$Node$Children$MyChildren__().myKeys;
2.183 - if (list.size() != perm.length) throw new IllegalArgumentException();
2.184 - List nue = new ArrayList(perm.length);
2.185 - for (int i = 0; i < perm.length; i++)
2.186 - nue.set(i, old.get(perm[i]));
2.187 - __NAME__.this.get__NAME$Node$Children$MyChildren__().setKeys(nue);
2.188 + MyDataElement[] items = model.getChildElements();
2.189 + if (items.length != perm.length) throw new IllegalArgumentException();
2.190 + MyDataElement[] nue = new MyDataElement[perm.length];
2.191 + for (int i = 0; i < perm.length; i++) {
2.192 + nue[i] = old[perm[i]];
2.193 + }
2.194 + // Should trigger an automatic child node update because the children
2.195 + // should be listening:
2.196 + model.setChildElements(nue);
2.197 }
2.198
2.199 }
3.1 --- a/apisupport/src/org/netbeans/modules/apisupport/resources/templates/Nodes_API/__Sample_leaf__Node_java Sat Jan 11 01:38:19 2003 +0000
3.2 +++ b/apisupport/src/org/netbeans/modules/apisupport/resources/templates/Nodes_API/__Sample_leaf__Node_java Sat Jan 11 03:19:29 2003 +0000
3.3 @@ -6,12 +6,17 @@
3.4 import org.openide.util.NbBundle;
3.5 import org.openide.util.actions.SystemAction;
3.6
3.7 -/** A simple node with no children.
3.8 - *
3.9 +/**
3.10 + * A simple node with no children.
3.11 + * Often used in conjunction with some kind of underlying data model, where
3.12 + * each node represents an element in that model. In this case, you should see
3.13 + * the Container Node template which will permit you to create a whole tree of
3.14 + * such nodes with the proper behavior.
3.15 * @author __USER__
3.16 */
3.17 public class __Sample_leaf__Node extends AbstractNode {
3.18
3.19 + // will frequently accept an element from some data model in the constructor:
3.20 public __Sample_leaf__Node() {
3.21 super(Children.LEAF);
3.22 setIconBase("__PACKAGE_AND_NAME_SLASHES$Node$NodeIcon$MyIcon__");
3.23 @@ -26,9 +31,15 @@
3.24 getCookieSet().add(new OpenCookie() {
3.25 public void open() {
3.26 // Open something useful...
3.27 + // will typically use the data model somehow
3.28 }
3.29 });
3.30 */
3.31 + // If this node represents an element in a data model of some sort, consider
3.32 + // creating your own cookie which captures the existence of that underlying data,
3.33 + // and add it to the cookie set. Then you can write actions sensitive to that cookie,
3.34 + // and they will not need to directly refer to this node class - only to the cookie
3.35 + // and the data model.
3.36 }
3.37
3.38 // Create the popup menu:
3.39 @@ -59,7 +70,8 @@
3.40 // RECOMMENDED - handle cloning specially (so as not to invoke the overhead of FilterNode):
3.41 /*
3.42 public Node cloneNode() {
3.43 - // Try to pass in similar constructor params to what you originally got:
3.44 + // Try to pass in similar constructor params to what you originally got,
3.45 + // typically meaning passing in the same data model element:
3.46 return new __NAME__();
3.47 }
3.48 */
3.49 @@ -74,6 +86,7 @@
3.50 props = Sheet.createPropertiesSet();
3.51 sheet.put(props);
3.52 }
3.53 + // typically the property will be constructed based on some underlying data model:
3.54 props.put(new MyProp(someParams));
3.55 return sheet;
3.56 }
3.57 @@ -85,9 +98,20 @@
3.58 return true;
3.59 }
3.60 public void setName(String nue) {
3.61 - // Update visible name, fire property changes:
3.62 - super.setName(nue);
3.63 - // perform additional actions, i.e. rename underlying object
3.64 + // Typically implemented by changing the name of an element from an underlying
3.65 + // data model. This node class should be listening to changes in the name of the
3.66 + // element and calling super.setName when it notices any (or better, override getName
3.67 + // and perhaps getDisplayName and call fireNameChange).
3.68 + // For example, if there is an instance field
3.69 + // private final MyDataElement data;
3.70 + // then you might write this method as:
3.71 + // data.setID(nue);
3.72 + // where you would also have:
3.73 + // public String getName() {return data.getID();}
3.74 + // and in the constructor, if __NAME__ implements ModelListener:
3.75 + // data.addModelListener((ModelListener)WeakListener.create(ModelListener.class, this, data));
3.76 + // where the interface is implemented as:
3.77 + // public void modelChanged(ModelEvent ev) {fireNameChange(null, null);}
3.78 }
3.79 */
3.80
3.81 @@ -97,9 +121,14 @@
3.82 return true;
3.83 }
3.84 public void destroy() throws IOException {
3.85 - // Actually remove the node itself and fire property changes:
3.86 - super.destroy();
3.87 - // perform additional actions, i.e. delete underlying object
3.88 + // Typically implemented by removing an element from an underlying data model.
3.89 + // For example, if there is an instance field
3.90 + // private final MyDataElement data;
3.91 + // then you might write this method as:
3.92 + // data.getContainingModel().removeElement(data);
3.93 + // The parent container children should be listening to the model, notice
3.94 + // the removal, set a new key list without this data element, and thus
3.95 + // remove this node from its children list.
3.96 }
3.97 */
3.98
3.99 @@ -116,7 +145,9 @@
3.100 ExTransferable et = ExTransferable.create(super.clipboardCopy());
3.101 et.put(new ExTransferable.Single(DataFlavor.stringFlavor) {
3.102 protected Object getData() {
3.103 + // just an example:
3.104 return __NAME__.this.getDisplayName();
3.105 + // more commonly, will use some underlying data model
3.106 }
3.107 });
3.108 return et;
3.109 @@ -129,7 +160,9 @@
3.110 // and it is not safe to assume that getData will only be called once):
3.111 et.put(new ExTransferable.Single(DataFlavor.stringFlavor) {
3.112 protected Object getData() {
3.113 + // just an example:
3.114 return __NAME__.this.getDisplayName();
3.115 + // more commonly, will use some underlying data model
3.116 }
3.117 });
3.118 return et;
3.119 @@ -142,6 +175,7 @@
3.120 return true;
3.121 }
3.122 public Component getCustomizer() {
3.123 + // more commonly, will pass in underlying data:
3.124 return new MyCustomizingPanel(this);
3.125 }
3.126 */