This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.
The Index cookie in the Nodes API is basically broken: since it is a cookie, yet explicitly deals with nodes rather than the data they represent, it works very poorly with FilterNode, which thus required the current broken implementation of FilterNode.{equals,hashCode} and indirectly a bunch of related evils. With the Looks API, for the first time there is an explicit notion of the data model behind nodes; we can thus fix the historical mistake. I suggest introducing a new "cookie" (i.e. interface in lookup) to be used specifically by looks and to represent the ability to reorder things. package org.netbeans.api.looks; /** * Adapter representing ability to reorder child represented * objects. * A look which provides an instance of this interface in the lookup * created in the node substitute by Look.attachTo (i.e. a look * which adds this "cookie" to the "cookie set" of the look node) * signals that the look node should provide the * org.openide.nodes.Index cookie and thus be reorderable. * (Creation of the Index cookie is automatic if Reorderable is * present and there would not otherwise be an Index * implementation in the node lookup.) * Reordering is done semantically based on child objects, not * nodes as such. * Looks.compositeLook will pay attention to the presence of * Reorderable in delegate looks: the composite look will have * Reorderable if and only if exactly one delegate look does. * Looks.filterLook will pass along Reorderable if and only if * ProxyLook.GET_CHILD_OBJECTS is not masked. */ public interface Reorderable { /** * Return the child represented objects currently beneath * this parent. */ Object[] getChildObjects(); /** * Change the order of the child represented objects. * @throws IllegalArgumentException if the new list is not a * permutation of the original list */ void setChildObjects(Object[] nue) throws IllegalArgumentException; // possible methods that I don't think are strictly necessary, // but might be desirable: /** * Check for validity of a certain permutation. * The passed-in list must be a permutation of the current * list of children; this method is included to permit * additional constraints on the reordering. * @return true if the new order is acceptable */ boolean isValid(Object[] nue); /** * Produce a look used to represent one of the child objects * in some reordering UI. Typically such a look will only be * asked to supply a display name and icon for use in a reorder * dialog. May return null to use whatever the default look * would be for the given child in the current context. */ Look getLookForChild(Object child); } Accompanying implementation changes: - CompositeLook to proxy Reorderable as described above - FilterLook to proxy Reorderable as described above - LookNode to implement getCookie(Index) to produce a reorder dialog based on this interface - default look for DataFolder (in dsui, I suppose) to supply a Reorderable based on DataFolder.[gs]etChildren Why will this solve the problems currently found in FilterNode? 1. LookNode.cloneNode just creates a new LookNode with the same Look and represented object. 2. So normal cloning of a LookNode will keep the same Reorderable, which will work on the same underlying data model, i.e. behave the same as in the original. 3. If you manually proxy to another look and use a subset of its children, you can suppress its Reorderable; or keep it as is (the reorder dialog will just show the original children); or manually create a proxy Reorderable that can reordered your visible subset the way you want it to be reordered (usually domain-specific logic). 4. If you use composite looks, you can still reorder children with no extra work, provided that only one delegate look was providing children to begin with. Otherwise you would need to manually provide a Reorderable that delegates to the original Reorderable's in some domain-specific way. Although FilterNode could simply suppress delegation of Index cookie, this would mean in effect that all filter nodes (= all of the visible Explorer and Options windows, I think) would not be reorderable. The only known workaround is the special behavior whereby filter nodes are considered somehow "equal" to the original nodes, enough to make typical Index implementations accept either the original or filtered nodes in their Index methods, such as indexOf. In contrast, Reorderable with Looks can safely support delegation where it makes intuitive sense. Also writing a Reorderable implementation should be much simpler than writing an Index implementation (try it sometime). BTW - I have never been fond of such methods in Node as: - destroy - getPasteTypes - getNewTypes - clipboardCopy, clipboardCut - can* - drag, getDropType All of these methods are properly part of the data model, not the node itself. I think putting these methods in Node is wrong for the same reason that Index is wrong - the node should only mirror the data. So I would be in favor of letting Looks replace these historical methods in Look with new capabilities, similar in spirit to Reorderable, e.g.: /** Can be attached to a look node for a deletable object */ public interface Deletable { boolean canDelete(); void delete() throws IOException; } /** Can be attached to a look node for a parent that can add children */ public interface ChildCreator { NewType[] getNewTypes(); interface NewType extends HelpCtx.Provider { String getName(); /** should add new children to the parent object, and also return the newly created child objects */ Object[] create() throws IOException; } } /** Attach to a look node for participation in data transfer */ public interface DataTransferable { boolean canCopy(); Transferable clipboardCopy(); boolean canCut(); Transferable clipboardCut(); Transferable drag(); PasteType getDropType(Transferable, int, int); PasteType[] getPasteTypes(Transferable); interface PasteType extends HelpCtx.Provider { getName(); /** paste, and return any new child objects thus created */ PasteResult paste(); final class PasteResult { public PasteResult(Object[] children, Transferable nue); public static PasteResult retainClipboard(Object[] children); public static PasteResult clearClipboard(Object[] children); public Object[] getChildren(); public Transferable getNewTransferable(); } } } However for all of these cases, the current situation in Node is not nearly so dangerous and uncomfortable as for Index: FilterNode can proxy the Node methods since the methods do not in turn refer to Node's. So this suggestion is much lower priority than Reorderable.
*** Issue 17660 has been marked as a duplicate of this issue. ***
Issue #33268 - could permit this to be ReorderableAspect.
Changing target milestone on all Looks issues to future
x