components/visual-panels/core/src/java/vpanels/panel/com/oracle/solaris/vp/panel/swing/control/TreeSelectorControl.java
changeset 3553 f1d133b09a8c
parent 3552 077ebe3d0d24
child 3554 ef58713bafc4
equal deleted inserted replaced
3552:077ebe3d0d24 3553:f1d133b09a8c
     1 /*
       
     2  * CDDL HEADER START
       
     3  *
       
     4  * The contents of this file are subject to the terms of the
       
     5  * Common Development and Distribution License (the "License").
       
     6  * You may not use this file except in compliance with the License.
       
     7  *
       
     8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
       
     9  * or http://www.opensolaris.org/os/licensing.
       
    10  * See the License for the specific language governing permissions
       
    11  * and limitations under the License.
       
    12  *
       
    13  * When distributing Covered Code, include this CDDL HEADER in each
       
    14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
       
    15  * If applicable, add the following below this CDDL HEADER, with the
       
    16  * fields enclosed by brackets "[]" replaced with your own identifying
       
    17  * information: Portions Copyright [yyyy] [name of copyright owner]
       
    18  *
       
    19  * CDDL HEADER END
       
    20  */
       
    21 
       
    22 /*
       
    23  * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
       
    24  */
       
    25 
       
    26 package com.oracle.solaris.vp.panel.swing.control;
       
    27 
       
    28 import java.awt.EventQueue;
       
    29 import java.util.*;
       
    30 import javax.swing.JTree;
       
    31 import javax.swing.event.*;
       
    32 import javax.swing.tree.*;
       
    33 import com.oracle.solaris.vp.panel.common.control.Control;
       
    34 import com.oracle.solaris.vp.panel.common.model.PanelDescriptor;
       
    35 import com.oracle.solaris.vp.panel.swing.view.TreeSelectorPanel;
       
    36 
       
    37 @SuppressWarnings({"serial"})
       
    38 public abstract class TreeSelectorControl<P extends PanelDescriptor,
       
    39     C extends TreeSelectorPanel, S> extends SelectorControl<P, C, S> {
       
    40 
       
    41     //
       
    42     // Inner classes
       
    43     //
       
    44 
       
    45     protected class NavTreeSelectionModel extends DefaultTreeSelectionModel {
       
    46 	//
       
    47 	// TreeSelectionModel methods
       
    48 	//
       
    49 
       
    50 	@Override
       
    51 	public void setSelectionPaths(TreePath[] paths) {
       
    52 	    setSelectionPathsDirectly(paths);
       
    53 	    goToSelected();
       
    54 	}
       
    55 
       
    56 	//
       
    57 	// NavTreeSelectionModel methods
       
    58 	//
       
    59 
       
    60 	public void setSelectionPathsDirectly(TreePath... paths) {
       
    61 	    super.setSelectionPaths(paths);
       
    62 
       
    63 	    if (paths != null & paths.length != 0) {
       
    64 		getComponent().getSelectionComponent().scrollPathToVisible(
       
    65 		    paths[0]);
       
    66 	    }
       
    67 	}
       
    68     }
       
    69 
       
    70     //
       
    71     // Instance data
       
    72     //
       
    73 
       
    74     private NavTreeSelectionModel treeSelModel;
       
    75 
       
    76     //
       
    77     // Constructors
       
    78     //
       
    79 
       
    80     public TreeSelectorControl(String id, String name, P descriptor) {
       
    81 	super(id, name, descriptor);
       
    82     }
       
    83 
       
    84     //
       
    85     // SwingControl methods
       
    86     //
       
    87 
       
    88     @Override
       
    89     protected void configComponent(C panel) {
       
    90 	super.configComponent(panel);
       
    91 
       
    92 	JTree tree = panel.getSelectionComponent();
       
    93 	tree.setModel(getTreeModel());
       
    94 
       
    95 	treeSelModel = new NavTreeSelectionModel();
       
    96 	tree.setSelectionModel(treeSelModel);
       
    97 
       
    98 	treeSelModel.addTreeSelectionListener(
       
    99 	    new TreeSelectionListener() {
       
   100 		@Override
       
   101 		public void valueChanged(TreeSelectionEvent e) {
       
   102 		    updateActions();
       
   103 		}
       
   104 	    });
       
   105 
       
   106 	initExpand();
       
   107     }
       
   108 
       
   109     //
       
   110     // SelectorControl methods
       
   111     //
       
   112 
       
   113     @Override
       
   114     protected List<S> getSelectableValues() {
       
   115 	List<S> values = new LinkedList<S>();
       
   116 	TreeModel model = getTreeModel();
       
   117 	TreePath path = new TreePath(model.getRoot());
       
   118 	addValues(values, model, path, true);
       
   119 
       
   120 	return values;
       
   121     }
       
   122 
       
   123     @Override
       
   124     protected List<S> getSelectedValues() {
       
   125 	TreePath[] selection =
       
   126 	    getComponent().getSelectionComponent().getSelectionPaths();
       
   127 
       
   128 	List<S> objects;
       
   129 	if (selection == null || selection.length == 0) {
       
   130 	    objects = Collections.emptyList();
       
   131 	} else {
       
   132 	    objects = new ArrayList<S>(selection.length);
       
   133 	    for (TreePath path : selection) {
       
   134 		S object = getSelectionForPath(path);
       
   135 		objects.add(object);
       
   136 	    }
       
   137 	}
       
   138 
       
   139 	return objects;
       
   140     }
       
   141 
       
   142     @Override
       
   143     protected void selectRunningChild() {
       
   144 	Control child = getRunningChild();
       
   145 	if (child != null) {
       
   146 	    final TreePath path = getTreePathOf(child);
       
   147 	    if (path != null) {
       
   148 		EventQueue.invokeLater(
       
   149 		    new Runnable() {
       
   150 			@Override
       
   151 			public void run() {
       
   152 			    // Set tree selection directly without going through
       
   153 			    // the Navigator
       
   154 			    treeSelModel.setSelectionPathsDirectly(path);
       
   155 			}
       
   156 		    });
       
   157 	    }
       
   158 	}
       
   159     }
       
   160 
       
   161     //
       
   162     // TreeSelectorControl methods
       
   163     //
       
   164 
       
   165     /**
       
   166      * Determines whether the given {@code TreePath} should be expanded when the
       
   167      * expanded/collapsed state of each node in the tree is initialized.
       
   168      * <p/>
       
   169      * This default implementation returns {@code false}.
       
   170      *
       
   171      * @param	    path
       
   172      *		    a path to a non-leaf node in the tree
       
   173      *
       
   174      * @return	    {@code true} to expand the given path, {@code false}
       
   175      *		    to collapse it
       
   176      *
       
   177      * @see	    #initExpand
       
   178      */
       
   179     public boolean getExpandOnInit(TreePath path) {
       
   180 	return false;
       
   181     }
       
   182 
       
   183     /**
       
   184      * Convert the given {@link TreePath} into a selected object.
       
   185      * <p/>
       
   186      * This default implementation assumes the last node in the given path is a
       
   187      * {@code DefaultMutableTreeNode} and returns the value from its {@code
       
   188      * getUserObject} method, cast to an {@code S}.
       
   189      *
       
   190      * @throws	    ClassCastException
       
   191      *		    if the underlying {@code TreeModel} does not follow the
       
   192      *		    above convention
       
   193      */
       
   194     protected S getSelectionForPath(TreePath path) {
       
   195 	DefaultMutableTreeNode node = (DefaultMutableTreeNode)
       
   196 	    path.getLastPathComponent();
       
   197 
       
   198 	@SuppressWarnings({"unchecked"})
       
   199 	S value = (S)node.getUserObject();
       
   200 
       
   201 	return value;
       
   202     }
       
   203 
       
   204     /**
       
   205      * Gets the model to use in the {@link TreeSelectorPanel}'s tree.
       
   206      */
       
   207     protected abstract TreeModel getTreeModel();
       
   208 
       
   209     /**
       
   210      * Gets the {@code TreePath} that corresponds to the given child {@code
       
   211      * Control}.
       
   212      *
       
   213      * @return	    a {@code TreePath}, or {@code null} if no {@code TreePath}
       
   214      *		    is appropriate
       
   215      */
       
   216     protected abstract TreePath getTreePathOf(Control child);
       
   217 
       
   218     /**
       
   219      * Initializes the expanded/collapsed state of each node in the tree.
       
   220      *
       
   221      * @see	    #getExpandOnInit
       
   222      */
       
   223     protected void initExpand() {
       
   224 	JTree tree = getComponent().getSelectionComponent();
       
   225 	TreeModel model = tree.getModel();
       
   226 
       
   227 	for (int row = 0; row < tree.getRowCount(); row++) {
       
   228 	    TreePath path = tree.getPathForRow(row);
       
   229 	    Object node = path.getLastPathComponent();
       
   230 	    if (!model.isLeaf(node)) {
       
   231 		if (getExpandOnInit(path)) {
       
   232 		    tree.expandRow(row);
       
   233 		} else {
       
   234 		    tree.collapseRow(row);
       
   235 		}
       
   236 	    }
       
   237 	}
       
   238     }
       
   239 
       
   240     //
       
   241     // Private methods
       
   242     //
       
   243 
       
   244     private void addValues(List<S> values, TreeModel model, TreePath path,
       
   245 	boolean isRoot) {
       
   246 
       
   247 	if (!isRoot || getComponent().getSelectionComponent().isRootVisible()) {
       
   248 	    S value = getSelectionForPath(path);
       
   249 	    values.add(value);
       
   250 	}
       
   251 
       
   252 	Object object = path.getLastPathComponent();
       
   253 	for (int i = 0, n = model.getChildCount(object); i < n; i++) {
       
   254 	    Object child = model.getChild(object, i);
       
   255 	    TreePath childPath = path.pathByAddingChild(child);
       
   256 	    addValues(values, model, childPath, false);
       
   257 	}
       
   258     }
       
   259 }