synthtreeui.java

来自「java jdk 1.4的源码」· Java 代码 · 共 1,971 行 · 第 1/5 页

JAVA
1,971
字号
    }    /**     * Returns the amount to indent the given row. NOTE: This does not     * include insets, nor should it!     */    private int getRowX(int row, int depth) {        return getIndent() * (depth + rootOffset - 1) + controlSize;    }    /**     * Makes all the nodes that are expanded in JTree expanded in LayoutCache.     * This invokes updateExpandedDescendants with the root path.     */    private void updateLayoutCacheExpandedNodes() {        TreeModel treeModel = tree.getModel();	if (treeModel != null && treeModel.getRoot() != null) {	    updateExpandedDescendants(new TreePath(treeModel.getRoot()));        }    }    /**     * Updates the expanded state of all the descendants of <code>path</code>     * by getting the expanded descendants from the tree and forwarding     * to the tree state.     */    private void updateExpandedDescendants(TreePath path) {	completeEditing();        treeState.setExpandedState(path, true);        Enumeration   descendants = tree.getExpandedDescendants(path);        if (descendants != null) {            while (descendants.hasMoreElements()) {                path = (TreePath)descendants.nextElement();                treeState.setExpandedState(path, true);            }        }        updateLeadRow();        invalidateSize();    }    /**     * Returns a path to the last child of <code>parent</code>.     */    private TreePath getLastChildPath(TreePath parent) {        TreeModel treeModel = tree.getModel();	if (treeModel != null) {	    int         childCount = treeModel.getChildCount		                         (parent.getLastPathComponent());	    	    if(childCount > 0) {		return parent.pathByAddingChild(treeModel.getChild			   (parent.getLastPathComponent(), childCount - 1));            }	}	return null;    }    /**     * Updates the offset for the root. This should be invoked as the     * properties the rootOffset depends upon change, eg root visibility,     * showing root handles...     */    private void updateRootOffset() {	if (tree.isRootVisible()) {	    if (tree.getShowsRootHandles()) {		rootOffset = 1;            }	    else {		rootOffset = 0;            }	}	else if (!tree.getShowsRootHandles()) {	    rootOffset = -1;        }	else {	    rootOffset = 0;        }    }    /**     * If the JTree's renderer is null, this will install a default one.     * Additionaly if we have installed an editor, we're reinstall it.      */    private void updateRenderer() {        TreeCellRenderer      newCellRenderer = tree.getCellRenderer();        if (newCellRenderer == null) {            tree.setCellRenderer(createCellRenderer());        }        if (tree.isEditable() && (tree.getCellEditor() instanceof                                  UIResource)) {            // We do this as the editor gets state from the renderer,            // so that any time one changes we need to update the other.            tree.setCellEditor(createCellEditor());        }    }    /**     * Configures the AbstractLayoutCache based on the tree we're     * providing the look and feel for.     */    private void configureLayoutCache() {        if (nodeDimensions == null) {            nodeDimensions = createNodeDimensions();        }        treeState.setNodeDimensions(nodeDimensions);        treeState.setRootVisible(tree.isRootVisible());        treeState.setRowHeight(tree.getRowHeight());        treeState.setSelectionModel(tree.getSelectionModel());        // Only do this if necessary, may loss state if call with        // same model as it currently has.        if (treeState.getModel() != tree.getModel()) {            treeState.setModel(tree.getModel());        }        updateLayoutCacheExpandedNodes();        // Create a listener to update preferred size when bounds        // changes, if necessary.        if (largeModel) {            if (componentListener == null) {                componentListener = createComponentListener();                if (componentListener != null) {                    tree.addComponentListener(componentListener);                }            }        }	else if(componentListener != null) {	    tree.removeComponentListener(componentListener);	    componentListener = null;	}    }    /**     * Invalides the size of the AbstractLayoutCache and marks the tree as     * needing to redisplay.     */    private void invalidateStateAndSize() {        treeState.invalidateSizes();	invalidateSize();    }    /**     * Marks the cached size as being invalid, and messages the     * tree with <code>treeDidChange</code>.     */    private void invalidateSize() {	validCachedPreferredSize = false;	tree.treeDidChange();    }    /**     * Recalculates the preferred size needed to display the tree.     */    private void updateCachedPreferredSize() {        Insets               i = tree.getInsets();        if (largeModel) {            Rectangle            visRect = tree.getVisibleRect();            visRect.x -= i.left;            visRect.y -= i.top;            preferredSize.width = treeState.getPreferredWidth(visRect);        }        else if (leftToRight) {            preferredSize.width = treeState.getPreferredWidth(null);        }        preferredSize.height = treeState.getPreferredHeight();        preferredSize.width += i.left + i.right;        preferredSize.height += i.top + i.bottom;	validCachedPreferredSize = true;    }    //     // Editing related methods    //    /**     * Returns the row being edited, -1 if not editing.     */    private int getEditingRow() {        return (editingState != null) ? editingState.row : -1;    }    /**     * Returns the Component responsible for editing, or null if not     * editing.     */    private Component getEditingComponent() {        return (editingState != null) ? editingState.component : null;    }    /**     * Messaged to stop the editing session. If the tree the receiver     * is providing the look and feel for returns true from     * <code>getInvokesStopCellEditing</code>, stopCellEditing will be     * invoked on the current editor, otherwise cancelCellEditing will be     * invoked     */    private void completeEditing() {	if (tree.getInvokesStopCellEditing() && getEditingComponent() != null){	    tree.getCellEditor().stopCellEditing();	}	// Invoke cancelCellEditing, this will do nothing if stopCellEditing        // was successful.	completeEditing(false, true, false);    }    /**      * Stops the editing session.  If messageStop is true the editor      * is messaged with stopEditing, if messageCancel is true the      * editor is messaged with cancelEditing. If messageTree is true      * the treeModel is messaged with valueForPathChanged.      */    private void completeEditing(boolean messageStop,                                 boolean messageCancel,                                 boolean messageTree) {	if (editingState != null) {            EditingState oldState = editingState;	    Object newValue = editingState.editor.getCellEditorValue();	    Rectangle editingBounds = tree.getPathBounds(oldState.path);	    boolean requestFocus = (tree != null && (tree.hasFocus() ||               SwingUtilities.findFocusOwner(editingState.component) != null));            editingState = null;	    if (messageStop) {		oldState.editor.stopCellEditing();            }	    else if (messageCancel) {		oldState.editor.cancelCellEditing();            }	    tree.remove(oldState.component);	    if (oldState.editorHasDifferentSize) {		treeState.invalidatePathBounds(oldState.path);		invalidateSize();	    }	    else {		editingBounds.x = 0;		editingBounds.width = tree.getSize().width;		tree.repaint(editingBounds);	    }	    if (requestFocus) {		tree.requestFocus();            }	    if (messageTree) {		tree.getModel().valueForPathChanged(oldState.path, newValue);            }	}    }    /**      * Will start editing for node if there is a cellEditor and      * shouldSelectCell returns true.<p>      * This assumes that path is valid and visible.      */    private boolean startEditing(TreePath path, MouseEvent event) {        if (tree.isEditing() && tree.getInvokesStopCellEditing() &&                               !tree.stopEditing()) {            return false;        }	completeEditing();        TreeCellEditor cellEditor = tree.getCellEditor();	if (cellEditor != null && tree.isPathEditable(path)) {	    int           row = getRowForPath(tree, path);	    if (cellEditor.isCellEditable(event)) {                EditingState state = new EditingState();                editingState = state;                state.component = cellEditor.getTreeCellEditorComponent		      (tree, path.getLastPathComponent(),		       tree.isPathSelected(path), tree.isExpanded(path),		       tree.getModel().isLeaf(path.getLastPathComponent()),                       row);                state.editor = cellEditor;		Rectangle           nodeBounds = getPathBounds(tree, path);		state.row = row;		Dimension editorSize = state.component.getPreferredSize();		// Only allow odd heights if explicitly set.		if (editorSize.height != nodeBounds.height &&                                         tree.getRowHeight() > 0) {		    editorSize.height = tree.getRowHeight();                }		if (editorSize.width != nodeBounds.width ||		               editorSize.height != nodeBounds.height) {		    // Editor wants different width or height, invalidate 		    // treeState and relayout.		    state.editorHasDifferentSize = true;		    treeState.invalidatePathBounds(path);		    invalidateSize();		}		else {		    state.editorHasDifferentSize = false;                }		tree.add(state.component);		state.component.setBounds(nodeBounds.x, nodeBounds.y,					   editorSize.width,					   editorSize.height);		state.path = path;		state.component.validate();		Rectangle              visRect = tree.getVisibleRect();                tree.repaint(nodeBounds.x, nodeBounds.y, visRect.width +                             visRect.x - nodeBounds.x, editorSize.height);		if (cellEditor.shouldSelectCell(event)) {                    stopEditingWhenSelectionChanges = false;                    tree.setSelectionRow(row);                    stopEditingWhenSelectionChanges = true;		}		SynthLookAndFeel.compositeRequestFocus(state.component);		return true;	    }	}	return false;    }    //    // Following are primarily for handling mouse events.    //    /**     * If the <code>mouseX</code> and <code>mouseY</code> are in the     * expand/collapse region of the <code>row</code>, this will toggle     * the row.     */    protected void expandPathIfNecessary(SynthContext context,                                         TreePath path, int mouseX,                                         int mouseY) {        if (isLocationInExpandControl(context, path, mouseX, mouseY)) {            handleExpandControlClick(path, mouseX, mouseY);	}    }    /**     * Returns true if <code>mouseX</code> and <code>mouseY</code> fall     * in the area of row that is used to expand/collapse the node and     * the node at <code>row</code> does not represent a leaf.     */    protected boolean isLocationInExpandControl(SynthContext context,                                  TreePath path, int mouseX, int mouseY) {        TreeModel treeModel = tree.getModel();	if (path != null && !treeModel.isLeaf(path.getLastPathComponent())){	    int                     boxWidth;	    if (getExpandedIcon() != null) {		boxWidth = SynthIcon.getIconWidth(getExpandedIcon(), context);            }	    else {		boxWidth = 8;            }	    Insets i = tree.getInsets();            int boxX = getRowX(tree.getRowForPath(path),                               path.getPathCount() - 1) -                          getTrailingControlOffset() - boxWidth / 2;            if (leftToRight) {                boxX += i.left;            }            else {                boxX = tree.getWidth() - getRowX(                       tree.getRowForPath(path), path.getPathCount() - 1) +                       getTrailingControlOffset() - boxWidth / 2;            }	    return mouseX >= boxX && (mouseX <= boxX + boxWidth);	}	return false;    }    /**     * Messaged when the user clicks the particular row, this invokes     * toggleExpandState.     */    protected void handleExpandControlClick(TreePath path, int mouseX,					    int mouseY) {	toggleExpandState(path);    }    /**     * Expands path if it is not expanded, or collapses row if it is expanded.     * If expanding a path and JTree scrolls on expand, en

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?