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.

Bug 29192 - Need substitute in Looks for org.openide.nodes.Index
Summary: Need substitute in Looks for org.openide.nodes.Index
Status: RESOLVED WONTFIX
Alias: None
Product: contrib
Classification: Unclassified
Component: Looks (show other bugs)
Version: 3.x
Hardware: All All
: P2 blocker (vote)
Assignee: Petr Hrebejk
URL:
Keywords: API
: 17660 (view as bug list)
Depends on: 33268
Blocks:
  Show dependency tree
 
Reported: 2002-11-30 23:58 UTC by Jesse Glick
Modified: 2008-11-18 11:34 UTC (History)
3 users (show)

See Also:
Issue Type: ENHANCEMENT
Exception Reporter:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jesse Glick 2002-11-30 23:58:44 UTC
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.
Comment 1 _ pkuzel 2003-03-20 11:49:54 UTC
*** Issue 17660 has been marked as a duplicate of this issue. ***
Comment 2 Jesse Glick 2003-04-28 15:51:56 UTC
Issue #33268 - could permit this to be ReorderableAspect.
Comment 3 Petr Hrebejk 2004-07-20 14:58:29 UTC
Changing target milestone on all Looks issues to future
Comment 4 Petr Hrebejk 2007-01-09 15:06:37 UTC
x