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.

View | Details | Raw Unified | Return to bug 178301
Collapse All | Expand All

(-)a/spi.viewmodel/apichanges.xml (+15 lines)
Lines 366-371 Link Here
366
        <class package="org.netbeans.spi.viewmodel" name="DnDNodeModelFilter" />
366
        <class package="org.netbeans.spi.viewmodel" name="DnDNodeModelFilter" />
367
        <issue number="177506"/>
367
        <issue number="177506"/>
368
    </change>
368
    </change>
369
    <change>
370
        <api name="ViewModelAPI"/>
371
        <summary>Drag and Drop support.</summary>
372
        <version major="1" minor="25"/>
373
        <date day="15" month="12" year="2009"/>
374
        <author login="mentlicher"/>
375
        <compatibility binary="compatible" source="compatible" deletion="no" addition="yes" modification="no"/>
376
        <description>
377
            This API introduce ReorderableTreeModel and ReorderableTreeModelFilter
378
            that can be used to alter the order of children nodes.
379
        </description>
380
        <class package="org.netbeans.spi.viewmodel" name="ReorderableTreeModel" />
381
        <class package="org.netbeans.spi.viewmodel" name="ReorderableTreeModelFilter" />
382
        <issue number="178301"/>
383
    </change>
369
384
370
385
371
</changes>
386
</changes>
(-)a/spi.viewmodel/manifest.mf (-1 / +1 lines)
Lines 1-5 Link Here
1
Manifest-Version: 1.0
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.netbeans.spi.viewmodel/2
2
OpenIDE-Module: org.netbeans.spi.viewmodel/2
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/viewmodel/Bundle.properties
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/viewmodel/Bundle.properties
4
OpenIDE-Module-Specification-Version: 1.24
4
OpenIDE-Module-Specification-Version: 1.25
5
5
(-)a/spi.viewmodel/src/org/netbeans/modules/viewmodel/TreeModelNode.java (-3 / +102 lines)
Lines 64-69 Link Here
64
import javax.swing.KeyStroke;
64
import javax.swing.KeyStroke;
65
import javax.swing.SwingUtilities;
65
import javax.swing.SwingUtilities;
66
66
67
import javax.swing.event.ChangeEvent;
68
import javax.swing.event.ChangeListener;
67
import org.netbeans.spi.viewmodel.AsynchronousModelFilter;
69
import org.netbeans.spi.viewmodel.AsynchronousModelFilter;
68
import org.netbeans.spi.viewmodel.AsynchronousModelFilter.CALL;
70
import org.netbeans.spi.viewmodel.AsynchronousModelFilter.CALL;
69
import org.netbeans.spi.viewmodel.ColumnModel;
71
import org.netbeans.spi.viewmodel.ColumnModel;
Lines 76-81 Link Here
76
import org.openide.explorer.view.CheckableNode;
78
import org.openide.explorer.view.CheckableNode;
77
import org.openide.nodes.AbstractNode;
79
import org.openide.nodes.AbstractNode;
78
import org.openide.nodes.Children;
80
import org.openide.nodes.Children;
81
import org.openide.nodes.Index;
79
import org.openide.nodes.Node;
82
import org.openide.nodes.Node;
80
import org.openide.nodes.PropertySupport;
83
import org.openide.nodes.PropertySupport;
81
import org.openide.nodes.Sheet;
84
import org.openide.nodes.Sheet;
Lines 160-172 Link Here
160
        final TreeModelRoot treeModelRoot,
163
        final TreeModelRoot treeModelRoot,
161
        final Object object
164
        final Object object
162
    ) {
165
    ) {
166
        this(
167
            model,
168
            columns,
169
            children,
170
            treeModelRoot,
171
            object,
172
            new Index[] { null });
173
    }
174
175
    private TreeModelNode (
176
        final Models.CompoundModel model,
177
        final ColumnModel[] columns,
178
        final Children children,
179
        final TreeModelRoot treeModelRoot,
180
        final Object object,
181
        final Index[] indexPtr  // Hack, because we can not declare variables before call to super() :-(
182
    ) {
163
        super (
183
        super (
164
            children,
184
            children,
165
            Lookups.fixed(object, new CheckNodeCookieImpl(model, object))
185
            createLookup(object, model, children, indexPtr)
166
        );
186
        );
167
        this.model = model;
187
        this.model = model;
168
        this.treeModelRoot = treeModelRoot;
188
        this.treeModelRoot = treeModelRoot;
169
        this.object = object;
189
        this.object = object;
190
        if (indexPtr[0] != null) {
191
            ((IndexImpl) indexPtr[0]).setNode(this);
192
            setIndexWatcher(indexPtr[0]);
193
        }
170
        
194
        
171
        // <RAVE>
195
        // <RAVE>
172
        // Use the modified CompoundModel class's field to set the 
196
        // Use the modified CompoundModel class's field to set the 
Lines 180-185 Link Here
180
        treeModelRoot.registerNode (object, this); 
204
        treeModelRoot.registerNode (object, this); 
181
        refreshNode ();
205
        refreshNode ();
182
        initProperties (columns);
206
        initProperties (columns);
207
    }
208
209
    private static Lookup createLookup(Object object, Models.CompoundModel model,
210
                                       Children ch, Index[] indexPtr) {
211
        CheckNodeCookieImpl cnc = new CheckNodeCookieImpl(model, object);
212
        boolean canReorder;
213
        try {
214
            canReorder = model.canReorder(object);
215
        } catch (UnknownTypeException ex) {
216
            if (!(object instanceof String)) {
217
                Logger.getLogger(TreeModelNode.class.getName()).log(Level.CONFIG, "Model: "+model, ex);
218
            }
219
            canReorder = false;
220
        }
221
        if (canReorder) {
222
            Index i = new IndexImpl(model, object);
223
            indexPtr[0] = i;
224
            return Lookups.fixed(object, cnc, i);
225
        } else {
226
            return Lookups.fixed(object, cnc);
227
        }
228
    }
229
230
    private void setIndexWatcher(Index childrenIndex) {
231
        childrenIndex.addChangeListener(new ChangeListener() {
232
            public void stateChanged(ChangeEvent e) {
233
                Children ch = getChildren();
234
                if (ch instanceof TreeModelChildren) {
235
                    ((TreeModelChildren) ch).refreshChildren(new TreeModelChildren.RefreshingInfo(false));
236
                }
237
            }
238
        });
183
    }
239
    }
184
240
185
    private static Executor asynchronous(Models.CompoundModel model, CALL asynchCall, Object object) {
241
    private static Executor asynchronous(Models.CompoundModel model, CALL asynchCall, Object object) {
Lines 1211-1218 Link Here
1211
                return refreshSubNodes;
1267
                return refreshSubNodes;
1212
            }
1268
            }
1213
        }
1269
        }
1214
    } // ItemChildren
1270
    } // TreeModelChildren
1215
    
1271
1272
    private static final class IndexImpl extends Index.Support {
1273
1274
        private Models.CompoundModel model;
1275
        private Object object;
1276
        private Node node;
1277
1278
        IndexImpl(Models.CompoundModel model, Object object) {
1279
            this.model = model;
1280
            this.object = object;
1281
        }
1282
1283
        void setNode(Node node) {
1284
            this.node = node;
1285
        }
1286
1287
        @Override
1288
        public Node[] getNodes() {
1289
            return node.getChildren().getNodes();
1290
        }
1291
1292
        @Override
1293
        public int getNodesCount() {
1294
            return node.getChildren().getNodesCount();
1295
        }
1296
1297
        @Override
1298
        public void reorder(int[] perm) {
1299
            try {
1300
                model.reorder(object, perm);
1301
                fireChangeEvent(new ChangeEvent(this));
1302
            } catch (UnknownTypeException ex) {
1303
                if (!(object instanceof String)) {
1304
                    Logger.getLogger(TreeModelNode.class.getName()).log(Level.CONFIG, "Model: "+model, ex);
1305
                }
1306
            }
1307
        }
1308
1309
        void fireChange() {
1310
            fireChangeEvent(new ChangeEvent(this));
1311
        }
1312
1313
    }
1314
1216
    private class MyProperty extends PropertySupport implements Runnable { //LazyEvaluator.Evaluable {
1315
    private class MyProperty extends PropertySupport implements Runnable { //LazyEvaluator.Evaluable {
1217
        
1316
        
1218
        private String      id;
1317
        private String      id;
(-)a/spi.viewmodel/src/org/netbeans/spi/viewmodel/Models.java (-12 / +100 lines)
Lines 450-460 Link Here
450
     *
450
     *
451
     * @returns compund tree model
451
     * @returns compund tree model
452
     */
452
     */
453
    private static TreeModel createCompoundTreeModel (
453
    private static ReorderableTreeModel createCompoundTreeModel (
454
        TreeModel originalTreeModel,
454
        ReorderableTreeModel originalTreeModel,
455
        List treeModelFilters
455
        List treeModelFilters
456
    ) {
456
    ) {
457
        TreeModel tm = originalTreeModel;
457
        ReorderableTreeModel tm = originalTreeModel;
458
        int i, k = treeModelFilters.size ();
458
        int i, k = treeModelFilters.size ();
459
        for (i = 0; i < k; i++)
459
        for (i = 0; i < k; i++)
460
            tm = new CompoundTreeModel (
460
            tm = new CompoundTreeModel (
Lines 686-695 Link Here
686
     * 
686
     * 
687
     * @author   Jan Jancura
687
     * @author   Jan Jancura
688
     */
688
     */
689
    private final static class CompoundTreeModel implements TreeModel, ModelListener {
689
    private final static class CompoundTreeModel implements ReorderableTreeModel, ModelListener {
690
690
691
691
692
        private TreeModel model;
692
        private ReorderableTreeModel model;
693
        private TreeModelFilter filter;
693
        private TreeModelFilter filter;
694
        
694
        
695
        private final Collection<ModelListener> modelListeners = new HashSet<ModelListener>();
695
        private final Collection<ModelListener> modelListeners = new HashSet<ModelListener>();
Lines 699-705 Link Here
699
         * Creates {@link org.netbeans.spi.viewmodel.TreeModel} for given TreeModel and
699
         * Creates {@link org.netbeans.spi.viewmodel.TreeModel} for given TreeModel and
700
         * {@link org.netbeans.spi.viewmodel.TreeModelFilter}.
700
         * {@link org.netbeans.spi.viewmodel.TreeModelFilter}.
701
         */
701
         */
702
        CompoundTreeModel (TreeModel model, TreeModelFilter filter) {
702
        CompoundTreeModel (ReorderableTreeModel model, TreeModelFilter filter) {
703
            this.model = model;
703
            this.model = model;
704
            this.filter = filter;
704
            this.filter = filter;
705
        }
705
        }
Lines 754-759 Link Here
754
         */
754
         */
755
        public boolean isLeaf (Object node) throws UnknownTypeException {
755
        public boolean isLeaf (Object node) throws UnknownTypeException {
756
            return filter.isLeaf (model, node);
756
            return filter.isLeaf (model, node);
757
        }
758
759
        public boolean canReorder(Object parent) throws UnknownTypeException {
760
            if (filter instanceof ReorderableTreeModelFilter) {
761
                return ((ReorderableTreeModelFilter) filter).canReorder(model, parent);
762
            } else {
763
                return model.canReorder(parent);
764
            }
765
        }
766
767
        public void reorder(Object parent, int[] perm) throws UnknownTypeException {
768
            if (filter instanceof ReorderableTreeModelFilter) {
769
                ((ReorderableTreeModelFilter) filter).reorder(model, parent, perm);
770
            } else {
771
                model.reorder(parent, perm);
772
            }
757
        }
773
        }
758
774
759
        /** 
775
        /** 
Lines 1278-1284 Link Here
1278
     *
1294
     *
1279
     * @author   Jan Jancura
1295
     * @author   Jan Jancura
1280
     */
1296
     */
1281
    private final static class DelegatingTreeModel implements TreeModel {
1297
    private final static class DelegatingTreeModel implements ReorderableTreeModel {
1282
1298
1283
        private TreeModel[] models;
1299
        private TreeModel[] models;
1284
        private HashMap<String, TreeModel> classNameToModel = new HashMap<String, TreeModel>();
1300
        private HashMap<String, TreeModel> classNameToModel = new HashMap<String, TreeModel>();
Lines 1305-1311 Link Here
1305
         *
1321
         *
1306
         * @param models a array of TreeModel
1322
         * @param models a array of TreeModel
1307
         */
1323
         */
1308
        DelegatingTreeModel (TreeModel[] models) {
1324
        private DelegatingTreeModel (TreeModel[] models) {
1309
            this.models = models;        
1325
            this.models = models;        
1310
        }
1326
        }
1311
        
1327
        
Lines 1410-1416 Link Here
1410
                }
1426
                }
1411
            }
1427
            }
1412
            throw new UnknownTypeException (node);
1428
            throw new UnknownTypeException (node);
1413
        }    
1429
        }
1430
1431
        public boolean canReorder(Object parent) throws UnknownTypeException {
1432
            UnknownTypeException uex = null;
1433
            TreeModel model = classNameToModel.get (
1434
                parent.getClass ().getName ()
1435
            );
1436
            if (model != null) {
1437
                if (model instanceof ReorderableTreeModel) {
1438
                    try {
1439
                        return ((ReorderableTreeModel) model).canReorder (parent);
1440
                    } catch (UnknownTypeException e) {
1441
                        uex = e;
1442
                    }
1443
                }
1444
            }
1445
            int i, k = models.length;
1446
            boolean isIndexed = false;
1447
            for (i = 0; i < k; i++) {
1448
                if (models[i] instanceof ReorderableTreeModel) {
1449
                    try {
1450
                        boolean cr = ((ReorderableTreeModel) models [i]).canReorder (parent);
1451
                        //classNameToModel.put (parent.getClass ().getName (), models [i]);
1452
                        return cr;
1453
                    } catch (UnknownTypeException e) {
1454
                        uex = e;
1455
                    }
1456
                    isIndexed = true;
1457
                }
1458
            }
1459
            if (!isIndexed) {
1460
                return false;
1461
            }
1462
            if (uex != null) {
1463
                throw uex;
1464
            } else {
1465
                throw new UnknownTypeException (parent);
1466
            }
1467
        }
1468
1469
        public void reorder(Object parent, int[] perm) throws UnknownTypeException {
1470
            TreeModel model = (TreeModel) classNameToModel.get (
1471
                parent.getClass ().getName ()
1472
            );
1473
            if (model instanceof ReorderableTreeModel) {
1474
                try {
1475
                    ((ReorderableTreeModel) model).reorder(parent, perm);
1476
                    return ;
1477
                } catch (UnknownTypeException e) {
1478
                }
1479
            }
1480
            int i, k = models.length;
1481
            for (i = 0; i < k; i++) {
1482
                if (models[i] instanceof ReorderableTreeModel) {
1483
                    try {
1484
                        ((ReorderableTreeModel) models[i]).reorder(parent, perm);
1485
                        //classNameToModel.put (parent.getClass ().getName (), models [i]);
1486
                        return ;
1487
                    } catch (UnknownTypeException e) {
1488
                    }
1489
                }
1490
            }
1491
            throw new UnknownTypeException (parent);
1492
        }
1414
1493
1415
        /** 
1494
        /** 
1416
         * Registers given listener.
1495
         * Registers given listener.
Lines 3236-3245 Link Here
3236
     * @see Models#createCompoundModel
3315
     * @see Models#createCompoundModel
3237
     * @author   Jan Jancura
3316
     * @author   Jan Jancura
3238
     */
3317
     */
3239
    public static final class CompoundModel implements TreeModel, 
3318
    public static final class CompoundModel implements ReorderableTreeModel,
3240
    ExtendedNodeModel, CheckNodeModel, DnDNodeModel, NodeActionsProvider, TableModel, TreeExpansionModel {
3319
    ExtendedNodeModel, CheckNodeModel, DnDNodeModel, NodeActionsProvider, TableModel, TreeExpansionModel {
3241
3320
3242
        private TreeModel       treeModel;
3321
        private ReorderableTreeModel treeModel;
3243
        private ExtendedNodeModel nodeModel;
3322
        private ExtendedNodeModel nodeModel;
3244
        private CheckNodeModel cnodeModel;
3323
        private CheckNodeModel cnodeModel;
3245
        private DnDNodeModel    dndNodeModel;
3324
        private DnDNodeModel    dndNodeModel;
Lines 3270-3276 Link Here
3270
         * @param nodeActionsProvider a columns modeol to delegate on
3349
         * @param nodeActionsProvider a columns modeol to delegate on
3271
         */
3350
         */
3272
        private CompoundModel (
3351
        private CompoundModel (
3273
            TreeModel treeModel, 
3352
            ReorderableTreeModel treeModel,
3274
            TreeExpansionModel treeExpansionModel,
3353
            TreeExpansionModel treeExpansionModel,
3275
            ExtendedNodeModel nodeModel, 
3354
            ExtendedNodeModel nodeModel, 
3276
            NodeActionsProvider nodeActionsProvider,
3355
            NodeActionsProvider nodeActionsProvider,
Lines 3394-3399 Link Here
3394
            return treeModel.isLeaf (node);
3473
            return treeModel.isLeaf (node);
3395
        }
3474
        }
3396
3475
3476
        // ReorderableTreeModel ...............................................................
3477
3478
        public boolean canReorder(Object parent) throws UnknownTypeException {
3479
            return treeModel.canReorder(parent);
3480
        }
3481
3482
        public void reorder(Object parent, int[] perm) throws UnknownTypeException {
3483
            treeModel.reorder(parent, perm);
3484
        }
3397
3485
3398
        // NodeModel ...............................................................
3486
        // NodeModel ...............................................................
3399
3487
(-)a/spi.viewmodel/src/org/netbeans/spi/viewmodel/ReorderableTreeModel.java (+79 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.spi.viewmodel;
41
42
/**
43
 * Data model for tree that supports reordering
44
 * of child nodes. The created {@link org.openide.nodes.Children} will
45
 * implement {@link org.openide.nodes.Index} if {@link #canReorder(java.lang.Object)}
46
 * returns <code>true</code>.
47
 * <p>
48
 * When used together with {@link DnDNodeModel}, children can be reordered
49
 * by Drag and Drop.
50
 *
51
 * @author Martin Entlicher
52
 * @since 1.25
53
 */
54
public interface ReorderableTreeModel extends TreeModel {
55
56
    /**
57
     * Provide if this model implementation can reorder children nodes.
58
     * @param parent The parent node of children that are test for reorder
59
     * @return <code>true</code> if this model can handle reordering of children,
60
     *         <code>false</code> otherwise
61
     * @throws UnknownTypeException if this model implementation is not
62
     *         able to decide the reorder capability for given node type
63
     */
64
    public boolean canReorder(Object parent) throws UnknownTypeException;
65
66
    /**
67
     * Reorder children nodes with a given permutation.
68
     * @param parent The parent node of children that are being reordered
69
     * @param perm permutation with the length of current child nodes. The permutation
70
     * lists the new positions of the original nodes, that is, for nodes
71
     * <code>[A,B,C,D]</code> and permutation <code>[0,3,1,2]</code>, the final
72
     * order would be <code>[A,C,D,B]</code>.
73
     * @throws IllegalArgumentException if the permutation is not valid
74
     * @throws UnknownTypeException if this model implementation is not
75
     *         able to perform the reorder for given node type
76
     */
77
    public void reorder(Object parent, int[] perm) throws UnknownTypeException;
78
79
}
(-)a/spi.viewmodel/src/org/netbeans/spi/viewmodel/ReorderableTreeModelFilter.java (+78 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.spi.viewmodel;
41
42
/**
43
 * Filters an original tree data model that supports reordering
44
 * of child nodes. The created {@link org.openide.nodes.Children} will
45
 * implement {@link org.openide.nodes.Index} if
46
 * {@link #canReorder(org.netbeans.spi.viewmodel.ReorderableTreeModel, java.lang.Object)}
47
 * returns <code>true</code>.
48
 *
49
 * @author Martin Entlicher
50
 * @since 1.25
51
 */
52
public interface ReorderableTreeModelFilter extends TreeModelFilter {
53
54
    /**
55
     * Provide if this filter implementation can reorder children nodes.
56
     * @param original The original ReorderableTreeModel
57
     * @param parent The parent node of children that are test for reorder
58
     * @return <code>true</code> if this model can handle reordering of children,
59
     *         <code>false</code> otherwise
60
     * @throws UnknownTypeException if this model implementation is not
61
     *         able to decide the reorder capability for given node type
62
     */
63
    public boolean canReorder(ReorderableTreeModel original, Object parent) throws UnknownTypeException;
64
65
    /**
66
     * Reorder children nodes with a given permutation.
67
     * @param parent The parent node of children that are being reordered
68
     * @param perm permutation with the length of current child nodes. The permutation
69
     * lists the new positions of the original nodes, that is, for nodes
70
     * <code>[A,B,C,D]</code> and permutation <code>[0,3,1,2]</code>, the final
71
     * order would be <code>[A,C,D,B]</code>.
72
     * @throws IllegalArgumentException if the permutation is not valid
73
     * @throws UnknownTypeException if this model implementation is not
74
     *         able to perform the reorder for given node type
75
     */
76
    public void reorder(ReorderableTreeModel original, Object parent, int[] perm) throws UnknownTypeException;
77
78
}
(-)a/spi.viewmodel/test/unit/src/org/netbeans/modules/viewmodel/ReorderableTreeModelTest.java (+199 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.viewmodel;
41
42
import java.util.ArrayList;
43
import java.util.Arrays;
44
import org.netbeans.junit.NbTestCase;
45
import org.netbeans.spi.viewmodel.Model;
46
import org.netbeans.spi.viewmodel.ModelEvent;
47
import org.netbeans.spi.viewmodel.ModelListener;
48
import org.netbeans.spi.viewmodel.Models;
49
import org.netbeans.spi.viewmodel.NodeModel;
50
import org.netbeans.spi.viewmodel.ReorderableTreeModel;
51
import org.netbeans.spi.viewmodel.TreeModel;
52
import org.netbeans.spi.viewmodel.UnknownTypeException;
53
import org.openide.nodes.Index;
54
import org.openide.nodes.Node;
55
import org.openide.util.RequestProcessor;
56
57
/**
58
 * Tests that reorderable model produces node with Index implementation
59
 * 
60
 * @author Martin Entlicher
61
 */
62
public class ReorderableTreeModelTest extends NbTestCase {
63
64
    private Node root;
65
66
    public ReorderableTreeModelTest (String s) {
67
        super (s);
68
    }
69
70
    private void setUpModel() {
71
        Model m = new ReorderableModelImpl();
72
73
        ArrayList l = new ArrayList ();
74
        l.add(m);
75
        Models.CompoundModel mcm = Models.createCompoundModel(l);
76
        OutlineTable tt = BasicTest.createView(mcm);
77
        
78
        RequestProcessor rp = tt.currentTreeModelRoot.getRootNode().getRequestProcessor();
79
        BasicTest.waitFinished (rp);
80
81
        root = tt.getExplorerManager ().getRootContext ();
82
    }
83
84
    public void testChildrenReorder() {
85
        setUpModel();
86
87
        Index indexImpl = root.getLookup().lookup(Index.class);
88
        assertNull("Root must not provide Index, root is not reordeable!", indexImpl);
89
90
        Node[] ch1 = root.getChildren().getNodes();
91
        assertEquals(2, ch1.length);
92
93
        indexImpl = ch1[1].getLookup().lookup(Index.class);
94
        assertNull(ch1[1]+ " must not provide Index, it is not reordeable!", indexImpl);
95
        indexImpl = ch1[0].getLookup().lookup(Index.class);
96
        assertNotNull(ch1[0]+ " must provide Index, it is reordeable!", indexImpl);
97
98
        indexImpl.reorder(new int[] { 2, 0, 1, 4, 3 });
99
        //                      =>  "3", "1", "2", "5", "4"
100
        String[] reorderedNames = new String[] { "2", "3", "1", "5", "4" };
101
        Node[] reorderedNodes = ch1[0].getChildren().getNodes();
102
        assertEquals(reorderedNames.length, reorderedNodes.length);
103
        String nodes = "Nodes = "+Arrays.toString(reorderedNodes);
104
        for (int i = 0; i < reorderedNodes.length; i++) {
105
            assertEquals(nodes, reorderedNames[i], reorderedNodes[i].getDisplayName());
106
        }
107
    }
108
109
    private static final class ReorderableModelImpl implements ReorderableTreeModel, NodeModel {
110
111
        private static final String CAN_REORDER = "canReorder";
112
        private static final String CAN_NOT_REORDER = "canNotReorder";
113
114
        private final String[] childrenReordered = new String[] { "1", "2", "3", "4", "5" };
115
116
        public boolean canReorder(Object parent) throws UnknownTypeException {
117
            return /*ROOT == parent ||*/ CAN_REORDER.equals(parent);
118
        }
119
120
        public void reorder(Object parent, int[] perm) throws UnknownTypeException {
121
            //System.err.println("reorder("+parent+", "+Arrays.toString(perm)+")");
122
            //Thread.dumpStack();
123
            if (!(/*ROOT == parent ||*/ CAN_REORDER.equals(parent))) {
124
                throw new IllegalStateException("reorder called on "+parent);
125
            }
126
            if (perm.length != childrenReordered.length) {
127
                throw new IllegalArgumentException("Permutation of length "+perm.length+", but have "+childrenReordered.length+" children.");
128
            }
129
            checkPermutation(perm);
130
            String[] ch = childrenReordered.clone();
131
            for (int i = 0; i < ch.length; i++) {
132
                //System.err.println("ch["+perm[i]+"] = "+ch[i]);
133
                childrenReordered[perm[i]] = ch[i];
134
            }
135
        }
136
137
        private static void checkPermutation(int[] permutation) throws IllegalArgumentException {
138
            int max = permutation.length;
139
            int[] check = new int[max];
140
            for (int i = 0; i < max; i++) {
141
                int p = permutation[i];
142
                if (p >= max) {
143
                    throw new IllegalArgumentException("Permutation "+Arrays.toString(permutation)+" is not a valid permutation, it contains element "+p+", which is bigger than the length of the permutation.");
144
                }
145
                if (p < 0) {
146
                    throw new IllegalArgumentException("Permutation "+Arrays.toString(permutation)+" is not a valid permutation, it contains element "+p+", which is negative.");
147
                }
148
                if (check[p] != 0) {
149
                    throw new IllegalArgumentException("Permutation "+Arrays.toString(permutation)+" is not a valid permutation, it contains element "+p+" twice or more times.");
150
                }
151
                check[p] = 1;
152
            }
153
        }
154
155
        public Object getRoot() {
156
            return ROOT;
157
        }
158
159
        public Object[] getChildren(Object parent, int from, int to) throws UnknownTypeException {
160
            if (ROOT == parent) {
161
                return new String[] { CAN_REORDER, CAN_NOT_REORDER };
162
            } else if (CAN_REORDER.equals(parent)) {
163
                return childrenReordered;
164
            } else if (CAN_NOT_REORDER.equals(parent)) {
165
                return new String[] { "a", "b", "c", "d", "e" };
166
            } else {
167
                return new Object[] {};
168
            }
169
        }
170
171
        public boolean isLeaf(Object node) throws UnknownTypeException {
172
            return ((String) node).length() == 1;
173
        }
174
175
        public int getChildrenCount(Object node) throws UnknownTypeException {
176
            return Integer.MAX_VALUE;
177
        }
178
179
        public void addModelListener(ModelListener l) {
180
        }
181
182
        public void removeModelListener(ModelListener l) {
183
        }
184
185
        public String getDisplayName(Object node) throws UnknownTypeException {
186
            return (String) node;
187
        }
188
189
        public String getIconBase(Object node) throws UnknownTypeException {
190
            return null;
191
        }
192
193
        public String getShortDescription(Object node) throws UnknownTypeException {
194
            return node+" of "+getClass().getSimpleName();
195
        }
196
        
197
    }
198
            
199
}

Return to bug 178301