/*FreeMind - A Program for creating and viewing Mindmaps *Copyright (C) 2000-2007 Joerg Mueller, Daniel Polansky, Christian Foltin, Dimitri Polivaev and others. *See COPYING for Details * *This program is free software; you can redistribute it and/or *modify it under the terms of the GNU General Public License *as published by the Free Software Foundation; either version 2 *of the License, or (at your option) any later version. * *This program is distributed in the hope that it will be useful, *but WITHOUT ANY WARRANTY; without even the implied warranty of *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *GNU General Public License for more details. * *You should have received a copy of the GNU General Public License *along with this program; if not, write to the Free Software *Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package freemind.view.mindmapview; import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; import java.awt.GradientPaint; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.event.KeyEvent; import java.awt.geom.AffineTransform; import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import freemind.controller.Controller; import freemind.controller.MenuBar; import freemind.main.HtmlTools; import freemind.main.Tools; import freemind.modes.MindMapNode; /** * Base class for all node views. * */ public abstract class MainView extends JLabel { static Dimension minimumSize = new Dimension(0, 0); static Dimension maximumSize = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); private static java.util.logging.Logger logger = null; private static final int MIN_HOR_NODE_SIZE = 10; int getZoomedFoldingSymbolHalfWidth() { return getNodeView().getZoomedFoldingSymbolHalfWidth(); } MainView() { if (logger == null) { logger = freemind.main.Resources.getInstance().getLogger( this.getClass().getName()); } isPainting = false; setAlignmentX(NodeView.CENTER_ALIGNMENT); setHorizontalAlignment(CENTER); setVerticalAlignment(CENTER); } public Dimension getMinimumSize() { return minimumSize; } public Dimension getMaximumSize() { return maximumSize; } private boolean isPainting; public NodeView getNodeView() { return (NodeView) SwingUtilities.getAncestorOfClass(NodeView.class, this); } /* * (non-Javadoc) * * @see javax.swing.JComponent#getPreferredSize() */ public Dimension getPreferredSize() { final String text = getText(); boolean isEmpty = text.length() == 0 || (HtmlTools.isHtmlNode(text) && text.indexOf("<img") < 0 && HtmlTools .htmlToPlain(text).length() == 0); if (isEmpty) { setText("!"); } Dimension prefSize = super.getPreferredSize(); final float zoom = getNodeView().getMap().getZoom(); if (zoom != 1F) { // TODO: Why 0.99? fc, 23.4.2011 prefSize.width = (int) (0.99 + prefSize.width * zoom); prefSize.height = (int) (0.99 + prefSize.height * zoom); } if (isCurrentlyPrinting() && MapView.NEED_PREF_SIZE_BUG_FIX) { prefSize.width += getNodeView().getMap().getZoomed(10); } prefSize.width = Math.max( getNodeView().getMap().getZoomed(MIN_HOR_NODE_SIZE), prefSize.width); if (isEmpty) { setText(""); } prefSize.width += getNodeView().getMap().getZoomed(12); prefSize.height += getNodeView().getMap().getZoomed(4); // /*@@@@@@@@@@@@@@*/ // prefSize.width = 150; // prefSize.height = 20; return prefSize; } public void paint(Graphics g) { float zoom = getZoom(); if (zoom != 1F) { // Dimitry: Workaround because Swing do not use fractional metrics // for laying JLabels out final Graphics2D g2 = (Graphics2D) g; zoom *= ZOOM_CORRECTION_FACTOR; final AffineTransform transform = g2.getTransform(); g2.scale(zoom, zoom); isPainting = true; super.paint(g); isPainting = false; g2.setTransform(transform); } else { super.paint(g); } } Controller getController() { return getNodeView().getMap().getController(); } protected boolean isCurrentlyPrinting() { return getNodeView().getMap().isCurrentlyPrinting(); } private float getZoom() { float zoom = getNodeView().getMap().getZoom(); return zoom; } protected void printComponent(Graphics g) { super.paintComponent(g); } public void paintSelected(Graphics2D graphics) { if (getNodeView().useSelectionColors()) { paintBackground(graphics, getNodeView().getSelectedColor()); } else { final Color backgroundColor = getNodeView().getModel() .getBackgroundColor(); if (backgroundColor != null) { paintBackground(graphics, backgroundColor); } } } protected void paintBackground(Graphics2D graphics, Color color) { graphics.setColor(color); graphics.fillRect(0, 0, getWidth() - 1, getHeight() - 1); } public void paintDragOver(Graphics2D graphics) { if (isDraggedOver == NodeView.DRAGGED_OVER_SON) { if (getNodeView().isLeft()) { graphics.setPaint(new GradientPaint(getWidth() * 3 / 4, 0, getNodeView().getMap().getBackground(), getWidth() / 4, 0, NodeView.dragColor)); graphics.fillRect(0, 0, getWidth() * 3 / 4, getHeight() - 1); } else { graphics.setPaint(new GradientPaint(getWidth() / 4, 0, getNodeView().getMap().getBackground(), getWidth() * 3 / 4, 0, NodeView.dragColor)); graphics.fillRect(getWidth() / 4, 0, getWidth() - 1, getHeight() - 1); } } if (isDraggedOver == NodeView.DRAGGED_OVER_SIBLING) { graphics.setPaint(new GradientPaint(0, getHeight() * 3 / 5, getNodeView().getMap().getBackground(), 0, getHeight() / 5, NodeView.dragColor)); graphics.fillRect(0, 0, getWidth() - 1, getHeight() - 1); } } /* * (non-Javadoc) * * @see javax.swing.JComponent#getHeight() */ public int getHeight() { if (isPainting) { final float zoom = getZoom(); if (zoom != 1F) { return (int) (super.getHeight() / zoom); } } return super.getHeight(); } /* * (non-Javadoc) * * @see javax.swing.JComponent#getWidth() */ public int getWidth() { if (isPainting) { final float zoom = getZoom(); if (zoom != 1F) { return (int) (0.99f + super.getWidth() / zoom); } } return super.getWidth(); } /* * (non-Javadoc) * * @see javax.swing.JComponent#processKeyBinding(javax.swing.KeyStroke, * java.awt.event.KeyEvent, int, boolean) */ protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) { if (super.processKeyBinding(ks, e, condition, pressed)) return true; // try key bindings of the menu bar even if the menu bar is not visible final MenuBar freeMindMenuBar = getController().getFrame() .getFreeMindMenuBar(); return !freeMindMenuBar.isVisible() && freeMindMenuBar.processKeyBinding(ks, e, JComponent.WHEN_IN_FOCUSED_WINDOW, pressed); } abstract Point getCenterPoint(); abstract Point getLeftPoint(); abstract Point getRightPoint(); /** get x coordinate including folding symbol */ public int getDeltaX() { return 0; } /** get y coordinate including folding symbol */ public int getDeltaY() { return 0; } /** get height including folding symbol */ protected int getMainViewHeightWithFoldingMark() { return getHeight(); } /** get width including folding symbol */ protected int getMainViewWidthWithFoldingMark() { return getWidth(); } protected void convertPointToMap(Point p) { Tools.convertPointToAncestor(this, p, getNodeView().getMap()); } protected void convertPointFromMap(Point p) { Tools.convertPointFromAncestor(getNodeView().getMap(), p, this); } protected int isDraggedOver = NodeView.DRAGGED_OVER_NO; public static final float ZOOM_CORRECTION_FACTOR = 1.0F;// former value, but // not very // understandable, // was: 0.97F; public void setDraggedOver(int draggedOver) { isDraggedOver = draggedOver; } public void setDraggedOver(Point p) { setDraggedOver((dropAsSibling(p.getX())) ? NodeView.DRAGGED_OVER_SIBLING : NodeView.DRAGGED_OVER_SON); } public int getDraggedOver() { return isDraggedOver; } public boolean dropAsSibling(double xCoord) { return isInVerticalRegion(xCoord, 1. / 3); } /** @return true if should be on the left, false otherwise. */ public boolean dropPosition(double xCoord) { /* here it is the same as me. */ return getNodeView().isLeft(); } /** * Determines whether or not the xCoord is in the part p of the node: if * node is on the left: part [1-p,1] if node is on the right: part[ 0,p] of * the total width. */ public boolean isInVerticalRegion(double xCoord, double p) { return getNodeView().isLeft() ? xCoord > getSize().width * (1.0 - p) : xCoord < getSize().width * p; } abstract String getStyle(); abstract int getAlignment(); public int getTextWidth() { return getWidth() - getIconWidth(); } public int getTextX() { int gap = (getWidth() - getPreferredSize().width) / 2; final boolean isLeft = getNodeView().isLeft(); if (isLeft) { gap = -gap; } return gap + (isLeft && !getNodeView().isRoot() ? 0 : getIconWidth()); } protected int getIconWidth() { final Icon icon = getIcon(); if (icon == null) { return 0; } return getNodeView().getMap().getZoomed(icon.getIconWidth()); } public boolean isInFollowLinkRegion(double xCoord) { final MindMapNode model = getNodeView().getModel(); return model.getLink() != null && (model.isRoot() || !model.hasChildren() || isInVerticalRegion( xCoord, 1. / 2)); } /** * @return true if a link is to be displayed and the cursor is the hand now. */ public boolean updateCursor(double xCoord) { boolean followLink = isInFollowLinkRegion(xCoord); int requiredCursor = followLink ? Cursor.HAND_CURSOR : Cursor.DEFAULT_CURSOR; if (getCursor().getType() != requiredCursor) { setCursor(requiredCursor != Cursor.DEFAULT_CURSOR ? new Cursor( requiredCursor) : null); } return followLink; } }