📄 mapview.java
字号:
userZoomFactor = Math.max(0,userZoomFactor); userZoomFactor = Math.min(2,userZoomFactor); // TODO: read user parameters from properties, make sure the multiple page // printing really works, have look at Book class. if (fitToPage && pageIndex > 0) { return Printable.NO_SUCH_PAGE; } Graphics2D graphics2D = (Graphics2D)graphics; _preparePrinting(); double zoomFactor = 1; if (fitToPage) { double zoomFactorX = pageFormat.getImageableWidth()/boundingRectangle.getWidth(); double zoomFactorY = pageFormat.getImageableHeight()/boundingRectangle.getHeight(); zoomFactor = Math.min (zoomFactorX, zoomFactorY); } else { zoomFactor = userZoomFactor; int nrPagesInWidth = (int)Math.ceil(zoomFactor * boundingRectangle.getWidth() / pageFormat.getImageableWidth()); int nrPagesInHeight = (int)Math.ceil(zoomFactor *boundingRectangle.getHeight() / pageFormat.getImageableHeight()); if (pageIndex >= nrPagesInWidth * nrPagesInHeight) { return Printable.NO_SUCH_PAGE; } int yPageCoord = (int)Math.floor(pageIndex / nrPagesInWidth); int xPageCoord = pageIndex - yPageCoord * nrPagesInWidth; graphics2D.translate(- pageFormat.getImageableWidth() * xPageCoord, - pageFormat.getImageableHeight() * yPageCoord); } graphics2D.translate(pageFormat.getImageableX(), pageFormat.getImageableY()); graphics2D.scale(zoomFactor, zoomFactor); graphics2D.translate(-boundingRectangle.getX(), -boundingRectangle.getY()); print(graphics2D); _endPrinting(); return Printable.PAGE_EXISTS; } /** For nodes, they can ask, whether or not the width must be bigger to prevent the "..." at the output. (Bug of java).*/ public boolean isCurrentlyPrinting() { return isPrinting;}; public Dimension getPreferredSize() { return getLayout().preferredLayoutSize(this); } /////////// // private methods. Internal implementation ///////// /** * Return the bounding box of all the descendants of the source view, that without BORDER. * Should that be implemented in LayoutManager as minimum size? */ public Rectangle getInnerBounds(NodeView source) { Rectangle innerBounds = source.getBounds(); for(ListIterator e = source.getChildrenViews().listIterator(); e.hasNext(); ) { NodeView target = (NodeView)e.next(); innerBounds.add(getInnerBounds(target));//recursive } // add heigth of the cloud int additionalCloudHeigth = (source.getAdditionalCloudHeigth() + 1) / 2; if (additionalCloudHeigth != 0){ innerBounds.grow(additionalCloudHeigth, additionalCloudHeigth); } if (source.getModel().isRoot()) { for(int i = 0; i < ArrowLinkViews.size(); ++i) { ArrowLinkView arrowView = (ArrowLinkView) ArrowLinkViews.get(i); Rectangle arrowViewBigBounds = arrowView.arrowLinkCurve.getBounds(); if (! innerBounds.contains(arrowViewBigBounds)){ Rectangle arrowViewBounds =PathBBox.getBBox(arrowView.arrowLinkCurve).getBounds(); innerBounds.add(arrowViewBounds); } } } return innerBounds; } private void paintEdges(NodeView source, Graphics2D g) { for(ListIterator e = source.getChildrenViews().listIterator(); e.hasNext(); ) { NodeView target = (NodeView)e.next(); target.getEdge().paint(g); paintEdges( target, g );//recursive } } protected NodeView getRoot() { return rootView; } private MindMapLayout getMindMapLayout() { return (MindMapLayout)getLayout(); } /** * This method is a workaround to allow the inner class access to "this". * Change it as soon the correct syntax is known. */ private MapView getMap() { return this; } public Controller getController() { return controller; } /////////// // Inner Class MapModelHandler ////////// /** * This inner class updates the Tree when the model is changed. */ private class MapModelHandler implements TreeModelListener { public void treeNodesChanged( TreeModelEvent e ) { // must be in structureChanged instead ? // or in is own Listerner setBackground(getModel().getBackgroundColor()); // Daniel: Why would I want to change background because some // nodes have changed? That's really strange. NodeView nodeView; try { nodeView = ( (MindMapNode)e.getChildren()[0] ).getViewer(); } catch (Exception ex) { //thrown if changed is root nodeView = ( (MindMapNode)e.getTreePath().getLastPathComponent() ).getViewer(); } // ^ This is not a good solution, but it works // here, the nodeView is checked for existence. if (nodeView != null) { logger.finest("The update node is " + nodeView + " with treemodelevent=" + e); nodeView.update(); getMindMapLayout() .updateTreeHeightsAndRelativeYOfDescendantsAndAncestors( nodeView); /* Layout only, if node is visible. fc, 03.07.2005 */ getMindMapLayout().layout(true); repaint(); /* end fc, 03.07.2005 */ } } public void treeNodesInserted( TreeModelEvent e ) { // Daniel: This is some kind of hackery implementation, which // does not keep the semantics of the method defined in // TreeModelListerer. This implementation does only that which // FreeMind actually needs, which I find dubious. MindMapNode parent = (MindMapNode)e.getTreePath().getLastPathComponent(); NodeView parentView = parent.getViewer(); // Works only with one child MindMapNode child = (MindMapNode)e.getChildren()[0]; if (child != null) { // if a node is folded, child is null. // Here, the view will be created if it does no exist already// for (int i = 0; i < e.getPath().length; i++) {// MindMapNode node = (MindMapNode) e.getPath()[i];// if(node.isFolded()) {// logger.info("Found folded node in path of a new children to be inserted.");// return;// }// } // Here, the view will be created if it does no exist already parentView.insert(child); getMindMapLayout().updateTreeGeometry(child.getViewer()); } getMindMapLayout().updateTreeHeightsAndRelativeYOfAncestors(parentView); // Here, the view of child gets its size and position getMindMapLayout().layout(false); //fc, 29.3.2004: here, I change parentView.requestFocus() to: child.getViewer().requestFocus(); repaint(); } public void treeNodesRemoved (TreeModelEvent e) { //This is called once for each removed node, with just one child (the removed) NodeView node = ( (MindMapNode)e.getChildren()[0] ).getViewer(); //Take care not to remove root in Controller NodeView parent = ( (MindMapNode)e.getTreePath().getLastPathComponent() ).getViewer(); if(node == null) { System.err.println("MapView.treeNodesRemoved tried to delete null as node."); return; } node.remove(); //Just that one MindMapNode preferred = parent.getModel().getPreferredChild(); if (preferred != null) { // after delete focus on a brother (PN) selectAsTheOnlyOneSelected(preferred.getViewer()); } else { selectAsTheOnlyOneSelected(parent); } getMindMapLayout().updateTreeHeightsAndRelativeYOfAncestors(parent); getMindMapLayout().layout(false); getSelected().requestFocus(); // scrollNodeToVisible(getSelected()); //fc, 5.4.2004. is already done by selectAsTheOnlyOneSelected: //parent.requestFocus(); repaint(); } /** * Assures that every and at least one selected node is visible. If this is not the case, * the node is deselected. * If every selected node is hidden, the first visible part in the path of the selected * node to the root is selected. */ public void treeStructureChanged (TreeModelEvent e) { // Keep selected nodes ArrayList selectedNodes = new ArrayList(); for (ListIterator it = getSelecteds().listIterator();it.hasNext();) { NodeView nodeView = (NodeView)it.next(); if (nodeView != null) { selectedNodes.add((nodeView).getModel()); } }// if the focussed is deleted: MindMapNode focussedNode = null; if (getSelected()!=null) { focussedNode = getSelected().getModel(); } // Update everything MindMapNode subtreeRoot = (MindMapNode)e.getTreePath().getLastPathComponent(); if(subtreeRoot == null || subtreeRoot.getViewer() == null) { // fc,14.1.2005: no viewer -> no update. } else { boolean nodeIsLeft = subtreeRoot.getViewer().isLeft(); NodeView oldNodeView = subtreeRoot.getViewer(); int x = oldNodeView.getX(); int y = oldNodeView.getY(); subtreeRoot.getViewer().remove(); NodeView nodeView = null; if (subtreeRoot.isRoot()) { nodeView = NodeView.newNodeView(getRoot().getModel(), getMap()); rootView = nodeView; } else { nodeView = NodeView.newNodeView(subtreeRoot, getMap()); } nodeView.setLocation(x, y); nodeView.setLeft(nodeIsLeft); nodeView.insert(); getMindMapLayout().updateTreeHeightsAndRelativeYOfDescendantsAndAncestors(subtreeRoot.getViewer()); // the layout function will be called later by AWT framework itself // comment it out // getMindMapLayout().layout(); } // Restore selected nodes // Warning, the old views still exist, because JVM has not deleted them. But don't use them! selected.clear(); for (ListIterator it = selectedNodes.listIterator();it.hasNext();) { MindMapNode mindMapNode = ((MindMapNode)it.next());// test, whether or not the node is still visible: if (mindMapNode.getViewer() != null) { selected.add(mindMapNode.getViewer()); } } // determine focussed node: if(focussedNode == null) {// if the focussed is deleted: focussedNode = getRoot().getModel(); } // test for visibility of the focussed: while(focussedNode.getParentNode()!= null && focussedNode.getViewer()==null) { focussedNode = focussedNode.getParentNode(); } if(focussedNode.getParentNode()==null) {// test, whether or not the node still belongs to the map: if(!focussedNode.equals(getRoot().getModel())) { focussedNode = getRoot().getModel(); } }// now select focussed: focussedNode.getViewer().requestFocus(); repaint(); } } // this property is used when the user navigates up/down using cursor keys (PN) // it will keep the level of nodes that are understand as "siblings" public int getSiblingMaxLevel() { return this.siblingMaxLevel; } public void setSiblingMaxLevel(int level) { this.siblingMaxLevel = level; } private int FOLDING_SYMBOL_WIDTH = -1; public int getZoomedFoldingSymbolHalfWidth() { if (FOLDING_SYMBOL_WIDTH == -1) { FOLDING_SYMBOL_WIDTH = getController().getIntProperty("foldingsymbolwidth", 8); } return (int) ((FOLDING_SYMBOL_WIDTH * getZoom()) / 2); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -