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 + -
显示快捷键?