📄 basictreeui.java
字号:
pBounds); if (pBounds != null && pBounds.y < endY) { minX = Math.min(minX, pBounds.x); } else { pBounds = null; } } return minX; } return minX; } /** * Messaged from the VisibleTreeNode after it has been expanded. */ protected void pathWasExpanded(TreePath path) { if(tree != null) { tree.fireTreeExpanded(path); } } /** * Messaged from the VisibleTreeNode after it has collapsed. */ protected void pathWasCollapsed(TreePath path) { if(tree != null) { tree.fireTreeCollapsed(path); } } /** * Ensures that the rows identified by beginRow through endRow are * visible. */ protected void ensureRowsAreVisible(int beginRow, int endRow) { if(tree != null && beginRow >= 0 && endRow < getRowCount(tree)) { if(beginRow == endRow) { Rectangle scrollBounds = getPathBounds(tree, getPathForRow (tree, beginRow)); if(scrollBounds != null) { tree.scrollRectToVisible(scrollBounds); } } else { Rectangle beginRect = getPathBounds(tree, getPathForRow (tree, beginRow)); Rectangle visRect = tree.getVisibleRect(); Rectangle testRect = beginRect; int beginY = beginRect.y; int maxY = beginY + visRect.height; for(int counter = beginRow + 1; counter <= endRow; counter++) { testRect = getPathBounds(tree, getPathForRow(tree, counter)); if((testRect.y + testRect.height) > maxY) counter = endRow; } tree.scrollRectToVisible(new Rectangle(visRect.x, beginY, 1, testRect.y + testRect.height- beginY)); } } } /** Sets the preferred minimum size. */ public void setPreferredMinSize(Dimension newSize) { preferredMinSize = newSize; } /** Returns the minimum preferred size. */ public Dimension getPreferredMinSize() { if(preferredMinSize == null) return null; return new Dimension(preferredMinSize); } /** Returns the preferred size to properly display the tree, * this is a cover method for getPreferredSize(c, false). */ public Dimension getPreferredSize(JComponent c) { return getPreferredSize(c, true); } /** Returns the preferred size to represent the tree in * <I>c</I>. If <I>checkConsistancy</I> is true * <b>checkConsistancy</b> is messaged first. */ public Dimension getPreferredSize(JComponent c, boolean checkConsistancy) { Dimension pSize = this.getPreferredMinSize(); if(!validCachedPreferredSize) updateCachedPreferredSize(); if(tree != null) { if(pSize != null) return new Dimension(Math.max(pSize.width, preferredSize.width), Math.max(pSize.height, preferredSize.height)); return new Dimension(preferredSize.width, preferredSize.height); } else if(pSize != null) return pSize; else return new Dimension(0, 0); } /** * Returns the minimum size for this component. Which will be * the min preferred size or 0, 0. */ public Dimension getMinimumSize(JComponent c) { if(this.getPreferredMinSize() != null) return this.getPreferredMinSize(); return new Dimension(0, 0); } /** * Returns the maximum size for this component, which will be the * preferred size if the instance is currently in a JTree, or 0, 0. */ public Dimension getMaximumSize(JComponent c) { if(tree != null) return getPreferredSize(tree); if(this.getPreferredMinSize() != null) return this.getPreferredMinSize(); return new Dimension(0, 0); } /** * Messages to stop the editing session. If the UI the receiver * is providing the look and feel for returns true from * <code>getInvokesStopCellEditing</code>, stopCellEditing will * invoked on the current editor. Then completeEditing will * be messaged with false, true, false to cancel any lingering * editing. */ protected void completeEditing() { /* If should invoke stopCellEditing, try that */ if(tree.getInvokesStopCellEditing() && stopEditingInCompleteEditing && editingComponent != null) { cellEditor.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. */ protected void completeEditing(boolean messageStop, boolean messageCancel, boolean messageTree) { if(stopEditingInCompleteEditing && editingComponent != null) { Component oldComponent = editingComponent; TreePath oldPath = editingPath; TreeCellEditor oldEditor = cellEditor; Object newValue = oldEditor.getCellEditorValue(); Rectangle editingBounds = getPathBounds(tree, editingPath); boolean requestFocus = (tree != null && (tree.hasFocus() || SwingUtilities. findFocusOwner(editingComponent) != null)); editingComponent = null; editingPath = null; if(messageStop) oldEditor.stopCellEditing(); else if(messageCancel) oldEditor.cancelCellEditing(); tree.remove(oldComponent); if(editorHasDifferentSize) { treeState.invalidatePathBounds(oldPath); updateSize(); } else { editingBounds.x = 0; editingBounds.width = tree.getSize().width; tree.repaint(editingBounds); } if(requestFocus) tree.requestFocus(); if(messageTree) treeModel.valueForPathChanged(oldPath, newValue); } } /** * Will start editing for node if there is a cellEditor and * shouldSelectCell returns true.<p> * This assumes that path is valid and visible. */ protected boolean startEditing(TreePath path, MouseEvent event) { if (isEditing(tree) && tree.getInvokesStopCellEditing() && !stopEditing(tree)) { return false; } completeEditing(); if(cellEditor != null && tree.isPathEditable(path)) { int row = getRowForPath(tree, path); if(cellEditor.isCellEditable(event)) { editingComponent = cellEditor.getTreeCellEditorComponent (tree, path.getLastPathComponent(), tree.isPathSelected(path), tree.isExpanded(path), treeModel.isLeaf(path.getLastPathComponent()), row); Rectangle nodeBounds = getPathBounds(tree, path); editingRow = row; Dimension editorSize = editingComponent.getPreferredSize(); // Only allow odd heights if explicitly set. if(editorSize.height != nodeBounds.height && getRowHeight() > 0) editorSize.height = getRowHeight(); if(editorSize.width != nodeBounds.width || editorSize.height != nodeBounds.height) { // Editor wants different width or height, invalidate // treeState and relayout. editorHasDifferentSize = true; treeState.invalidatePathBounds(path); updateSize(); } else editorHasDifferentSize = false; tree.add(editingComponent); editingComponent.setBounds(nodeBounds.x, nodeBounds.y, editorSize.width, editorSize.height); editingPath = path; editingComponent.validate(); Rectangle visRect = tree.getVisibleRect(); tree.paintImmediately(nodeBounds.x, nodeBounds.y, visRect.width + visRect.x - nodeBounds.x, editorSize.height); if(cellEditor.shouldSelectCell(event)) { stopEditingInCompleteEditing = false; try { tree.setSelectionRow(row); } catch (Exception e) { System.err.println("Editing exception: " + e); } stopEditingInCompleteEditing = true; } BasicLookAndFeel.compositeRequestFocus(editingComponent); if(event != null && event instanceof MouseEvent) { /* Find the component that will get forwarded all the mouse events until mouseReleased. */ Point componentPoint = SwingUtilities.convertPoint (tree, new Point(event.getX(), event.getY()), editingComponent); /* Create an instance of BasicTreeMouseListener to handle passing the mouse/motion events to the necessary component. */ // We really want similar behavior to getMouseEventTarget, // but it is package private. Component activeComponent = SwingUtilities. getDeepestComponentAt(editingComponent, componentPoint.x, componentPoint.y); if (activeComponent != null) { new MouseInputHandler(tree, activeComponent, event); } } return true; } else editingComponent = null; } 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 checkForClickInExpandControl(TreePath path, int mouseX, int mouseY) { if (isLocationInExpandControl(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(TreePath path, int mouseX, int mouseY) { if(path != null && !treeModel.isLeaf(path.getLastPathComponent())){ int boxWidth; Insets i = tree.getInsets(); if(getExpandedIcon() != null) boxWidth = getExpandedIcon().getIconWidth(); else boxWidth = 8; int boxLeftX = (i != null) ? i.left : 0; if (leftToRight) { boxLeftX += (((path.getPathCount() + depthOffset - 2) * totalChildIndent) + getLeftChildIndent()) - boxWidth / 2; } else { boxLeftX += lastWidth - 1 - ((path.getPathCount() - 2 + depthOffset) * totalChildIndent) - getLeftChildIndent() - boxWidth / 2; } int boxRightX = boxLeftX + boxWidth; return mouseX >= boxLeftX && mouseX <= boxRightX; } 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, ensureRowsAreVisible * is invoked to scroll as many of the children to visible as possible * (tries to scroll to last visible descendant of path). */ protected void toggleExpandState(TreePath path) { if(!tree.isExpanded(path)) { int row = getRowForPath(tree, path); tree.expandPath(path); updateSize(); if(row != -1) { if(tree.getScrollsOnExpand()) ensureRowsAreVisible(row, row + treeState. getVisibleChildCount(path)); else ensureRowsAreVisible(row, row); } } else { tree.collapsePath(path); updateSize(); } } /** * Returning true signifies a mouse event on the node should toggle * the selection of only the row under mouse. */ protected boolean isToggleSelectionEvent(MouseEvent event) { return (SwingUtilities.isLeftMouseButton(event) && event.isControlDown()); } /** * Returning true signifies a mouse event on the node should select * from the anchor point. */ protected boolean isMultiSelectEvent(MouseEvent event) { return (SwingUtilities.isLeftMouseButton(event) && event.isShiftDown()); } /** * Returning true indicates the row under the mouse should be toggled * based on the event. This is invoked after checkForClickInExpandControl, * implying the location is not in the expand (toggle) control */ protected boolean isToggleEvent(MouseEvent event) { if(!SwingUtilities.isLeftMouseButton(event)) { return false; } int clickCount = tree.getToggleClickCount(); if(clickCount <= 0) { return false; } return (event.getClickCount() == clickCount); } /** * Messaged to update the selection based on a MouseEvent over a * particular row. If the event is a toggle selection event, the * row is either selected, or deselected. If the event identifies * a multi selection event, the selection is updated from the * anchor point. Otherwise the row is selected, and if the event * specified a toggle event the row is expanded/collapsed. */ protected void selectPathForEvent(TreePath path, MouseEvent event) { // Should this event toggle the selection of this row? /* Control toggles just this node. */ if(isToggleSelectionEvent(event)) { if(tree.isPathSelected(path)) tree.removeSelectionPath(path); else tree.addSelectionPath(path); lastSelectedRow = getRowForPath(tree, path); setAnchorSelectionPath(path); setLeadSelectionPath(path); } /* Adjust from the anchor point. */ else if(isMultiSelectEvent(event)) { TreePath anchor = getAnchorSelectionPath(); int anchorRow = (anchor == null) ? -1 :
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -