/* ****************************************************************************** * * Copyright 2008-2010 Hans Dijkema * * JRichTextEditor is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * JRichTextEditor 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with JRichTextEditor. If not, see <http://www.gnu.org/licenses/>. * * ******************************************************************************/ package nl.dykema.jxmlnote.toolbar; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.geom.Rectangle2D; import javax.swing.Icon; import nl.dykema.jxmlnote.icons.Close; import nl.dykema.jxmlnote.icons.Document_new; import nl.dykema.jxmlnote.icons.Document_open; import nl.dykema.jxmlnote.icons.Document_save; import nl.dykema.jxmlnote.icons.Edit_copy; import nl.dykema.jxmlnote.icons.Edit_cut; import nl.dykema.jxmlnote.icons.Edit_paste; import nl.dykema.jxmlnote.icons.Edit_redo; import nl.dykema.jxmlnote.icons.Edit_select_all; import nl.dykema.jxmlnote.icons.Edit_undo; import nl.dykema.jxmlnote.icons.First; import nl.dykema.jxmlnote.icons.FlamencoIconAdapter; import nl.dykema.jxmlnote.icons.Format_indent_less; import nl.dykema.jxmlnote.icons.Format_indent_more; import nl.dykema.jxmlnote.icons.Help; import nl.dykema.jxmlnote.icons.InsertHyperlink; import nl.dykema.jxmlnote.icons.Last; import nl.dykema.jxmlnote.icons.Next; import nl.dykema.jxmlnote.icons.NoImage; import nl.dykema.jxmlnote.icons.Previous; import nl.dykema.jxmlnote.icons.Print; import nl.dykema.jxmlnote.icons.PrintPrefs; import nl.dykema.jxmlnote.icons.Quit; import nl.dykema.jxmlnote.icons.RemoveHyperlink; import nl.dykema.jxmlnote.icons.Zoom100; import nl.dykema.jxmlnote.icons.ZoomFitHeight; import nl.dykema.jxmlnote.icons.ZoomFitWidth; import nl.dykema.jxmlnote.icons.ZoomLess; import nl.dykema.jxmlnote.icons.ZoomMore; /** * This icon class paints icons using draw functions instead of bitmaps. * * @author Hans Dijkema * */ public class JXMLNoteIcon implements Icon { private int _width = 18; private int _height = 18; private String _iconType = "none"; private boolean _selected = false; private JXMLNoteIconPainter _painter = null; private SizeProvider _provider = null; private DimensionProvider _dprovider = null; private void provideSize() { if (_dprovider != null) { this.setWHSize(_dprovider.buttonSize()); } else if (_provider != null) { setWHSize(_provider.buttonSize()); } } /** * Interface that can be used to set the size of an JXMLNoteIcon dynamically * <p> * * @author Hans Dijkema */ public interface SizeProvider { public int buttonSize(); }; /** * Interface that can be used to set the size of an JXMLNoteicon dynamically. width and height individually * @author hans Oesteholt * */ public interface DimensionProvider { public Dimension buttonSize(); } /** * This function returns the current painter for an icon. Returns null, if * no painter has been set. * * @return */ public JXMLNoteIconPainter getPainter() { return _painter; } /** * This function sets the selection state of the icon. * * @param x * <code>true</code> means "selected"; <code>false</code> * otherwhise. */ public void setSelected(boolean x) { _selected = x; } /** * This function returns the selected state of the icon. * * @return <code>true</code> is "selected"; <code>false</code> otherwise. */ public boolean selected() { return _selected; } private void drawTextAttr(int x, int y, int w, int h, Graphics2D g, String _type) { Font F; Rectangle2D r = g.getFontMetrics().getStringBounds(_type, g); double sWidth = r.getWidth(); double sHeight = r.getHeight(); double currentPointSize = g.getFont().getSize2D(); double scaleFactorW = w / sWidth; double scaleFactorH = h / sHeight; double newPointSize = currentPointSize * ((scaleFactorW < scaleFactorH) ? scaleFactorW : scaleFactorH); if (_type.equals("B")) { F = g.getFont().deriveFont(Font.BOLD, (float) newPointSize); } else if (_type.equals("U")) { F = g.getFont().deriveFont((float) newPointSize); } else if (_type.equals("I")) { F = g.getFont().deriveFont(Font.ITALIC, (float) newPointSize); } else { F = g.getFont(); } g.setFont(F); FontMetrics met = g.getFontMetrics(); // int l=met.getLeading(); // int a=met.getAscent(); double d = ((double) met.getDescent()) / 2.0; r = met.getStringBounds(_type, g); sHeight = r.getHeight(); sWidth = r.getWidth(); double yOffset = (h - sHeight) / 2 + d; double xOffset = (w - sWidth) / 2; // yOffset+=(double) g.getFontMetrics().getLeading(); g.setColor(Color.DARK_GRAY); g.drawString(_type, (int) (x + xOffset), (int) (y + h - yOffset)); if (_type.equals("U")) { g.drawLine((int) (x + xOffset - 2), (int) (y + h - yOffset + 2), (int) (x + xOffset + sWidth), (int) (y + h - yOffset + 2)); } } private void drawList(int x, int y, int w, int _h, Graphics2D g, String _type) { int N = _h / 4; int i; int stepH = (_h / N); int indent = (int) (w * 0.1); int rw = w - indent; if (stepH <= 1) { stepH = 1; } int h = y + (stepH / 2 + 1); int R = stepH / 2; int type = 0; if (_type.equals("bullits")) { type = 0; } else if (_type.equals("numbers")) { type = 1; } if (type == 1) { Font F = g.getFont().deriveFont((float) 4.0); g.setFont(F); } g.setColor(Color.DARK_GRAY); for (i = 0; i < N; i++) { switch (type) { case 0: { int RW = rw; g.fillArc(x + indent, h - R / 2, R, R, 0, 360); g.drawLine(x + indent + 2 * R, h, x + RW, h); break; } case 1: { int M = g.getFontMetrics().getMaxAdvance(); int H = g.getFontMetrics().getHeight() / 2; g.drawString(String.format("%d", (i + 1) % 10), x + indent, h + H); g.drawLine(x + indent + M, h, x + rw, h); break; } } h += stepH; } } private void drawAlign(int x, int y, int w, int _h, Graphics2D g, String _type) { int N = _h / 2; int i; int stepH = (_h / N); int indent = (int) (w * 0.1); int rw = w - indent; if (stepH <= 1) { stepH = 1; } int h = y + (stepH / 2 + 1); int type; if (_type.equals("left")) { type = 0; } else if (_type.equals("right")) { type = 1; } else if (_type.equals("center")) { type = 2; } else { type = 3; } g.setColor(Color.DARK_GRAY); for (i = 0; i < N; i++) { double rnd = 0.3 * Math.random(); switch (type) { case 0: { int RW = (int) (rw - (rw * rnd)); g.drawLine(x + indent, h, x + RW, h); break; } case 1: { int M = (int) (rw * rnd); g.drawLine(x + indent + M, h, x + rw, h); break; } case 2: { int M = (int) (rw * rnd); int RW = (int) (rw - M); g.drawLine(x + indent + M, h, x + RW, h); break; } case 3: { g.drawLine(x + indent, h, x + rw, h); break; } } h += stepH; } } public static Graphics2D prepareG(int x, int y, int w, int h, int ww, int hh, Graphics2D gg) { Graphics2D g = (Graphics2D) gg.create(); g.translate(x, y); g.scale(((float) w) / ((float) ww), ((float) h) / ((float) hh)); return g; } private void drawIcon(FlamencoIconAdapter adapter, int x, int y, int w, int h, Graphics2D g) { Graphics2D gg = prepareG(x, y, w, h, adapter.getOrigWidth(), adapter .getOrigHeight(), g); adapter.paint(gg); } /** * This function paints the icon. It is implements the paintIcon function of * {@link Icon}. This function knows how to paint the following standard * iconTypes: * * <ul> * <li>align-left,align-right,align-center,align-justify</li> * <li>unordered-list,numbered-list</li> * <li>font-bold,font-italic,font-underline</li> * <li>style:h1,style:h2,style:h3,style:h4,style:par</li> * <li>save,load</li> * <ul> * * If JXMLNoteIcon has been initialized with a {@link JXMLNoteIconPainter}. * This {@link JXMLNoteIconPainter#paint} member will be called with the * appropriate parameters. * * If the iconType is not known and no {@link JXMLNoteIconPainter} as been * given, the icon will be filled with the color red, indicating there is no * icon. * */ public void paintIcon(Component c, Graphics _g, int x, int y) { provideSize(); Graphics2D g = (Graphics2D) _g; g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); x = x - 2; y = y - 2; if (_selected) { g.draw3DRect(x, y, _width + 2, _width + 2, false); } x += 2; y += 2; int w = _width - 2; int h = _height - 2; if (_painter != null) { _painter.paint(x, y, w, h, g, c, _iconType); } else { if (_iconType == "none") { g.setColor(Color.white); g.fillRect(x, y, _width, _width); } else if (_iconType.equals("align-left")) { drawAlign(x, y, w, h, g, "left"); } else if (_iconType.equals("align-right")) { drawAlign(x, y, w, h, g, "right"); } else if (_iconType.equals("align-center")) { drawAlign(x, y, w, h, g, "center"); } else if (_iconType.equals("align-justify")) { drawAlign(x, y, w, h, g, "justify"); } else if (_iconType.equals("unordered-list")) { drawList(x, y, w, h, g, "bullits"); } else if (_iconType.equals("numbered-list")) { drawList(x, y, w, h, g, "numbers"); } else if (_iconType.equals("font-bold")) { drawTextAttr(x, y, w, h, g, "B"); } else if (_iconType.equals("font-italic")) { drawTextAttr(x, y, w, h, g, "I"); } else if (_iconType.equals("font-underline")) { drawTextAttr(x, y, w, h, g, "U"); } else if (_iconType.equals("style:h1")) { drawTextAttr(x, y, w, h, g, "h1"); } else if (_iconType.equals("style:h2")) { drawTextAttr(x, y, w, h, g, "h2"); } else if (_iconType.equals("style:h3")) { drawTextAttr(x, y, w, h, g, "h3"); } else if (_iconType.equals("style:h4")) { drawTextAttr(x, y, w, h, g, "h4"); } else if (_iconType.equals("style:par")) { drawTextAttr(x, y, w, h, g, "-"); } else if (_iconType.startsWith("style:")) { // draw nothing } else if (_iconType.equals("new")) { drawIcon(NEW, x, y, w, h, g); } else if (_iconType.equals("save")) { drawIcon(SAVE, x, y, w, h, g); } else if (_iconType.equals("load")) { drawIcon(LOAD, x, y, w, h, g); } else if (_iconType.equals("copy-to-clipboard")) { drawIcon(COPY, x, y, w, h, g); } else if (_iconType.equals("cut-to-clipboard")) { drawIcon(CUT, x, y, w, h, g); } else if (_iconType.equals("paste-from-clipboard")) { drawIcon(PASTE, x, y, w, h, g); } else if (_iconType.equals("redo")) { drawIcon(REDO, x, y, w, h, g); } else if (_iconType.equals("undo")) { drawIcon(UNDO, x, y, w, h, g); } else if (_iconType.equals("select-all")) { drawIcon(SELECT_ALL, x, y, w, h, g); } else if (_iconType.equals("indent-more")) { drawIcon(INDENTMORE, x, y, w, h, g); } else if (_iconType.equals("indent-less")) { drawIcon(INDENTLESS, x, y, w, h, g); } else if (_iconType.equals("NoImage")) { drawIcon(NOIMAGE, x, y, w, h, g); } else if (_iconType.equals("quit")) { drawIcon(QUIT, x, y, w, h, g); } else if (_iconType.equals("help")) { drawIcon(HELP, x, y, w, h, g); } else if (_iconType.equals("zoom-100") || _iconType.equals("zoom-100%")) { drawIcon(ZOOM_100, x, y, w, h, g); } else if (_iconType.equals("zoom-more") || _iconType.equals("zoom-125%") || _iconType.equals("zoom-150%") || _iconType.equals("zoom-200%")) { drawIcon(ZOOM_MORE, x, y, w, h, g); } else if (_iconType.equals("zoom-less") || _iconType.equals("zoom-75%") || _iconType.equals("zoom-50%")) { drawIcon(ZOOM_LESS, x, y, w, h, g); } else if (_iconType.equals("zoom-fit-width") || _iconType.equals("set-zoom")) { drawIcon(ZOOM_FIT_WIDTH, x, y, w, h, g); } else if (_iconType.equals("zoom-fit-height")) { drawIcon(ZOOM_FIT_HEIGHT, x, y, w, h, g); } else if (_iconType.equals("next")) { drawIcon(NEXT, x, y, w, h, g); } else if (_iconType.equals("previous")) { drawIcon(PREVIOUS, x, y, w, h, g); } else if (_iconType.equals("last")) { drawIcon(LAST, x, y, w, h, g); } else if (_iconType.equals("first")) { drawIcon(FIRST, x, y, w, h, g); } else if (_iconType.equals("close")) { drawIcon(CLOSE, x, y, w, h, g); } else if (_iconType.equals("print")) { drawIcon(PRINT, x, y, w, h, g); } else if (_iconType.equals("print-prefs")) { drawIcon(PRINT_PREFS, x, y, w, h, g); } else if (_iconType.equals("insert-hyperlink")) { drawIcon(INSERT_HYPERLINK, x, y, w, h, g); } else if (_iconType.equals("remove-hyperlink")) { drawIcon(REMOVE_HYPERLINK, x, y, w, h, g); } else { g.setColor(Color.red); g.fillRect(x, y, _width, _width); } } } /** * @return _height the current icon height in (screen) pixels. */ public int getIconHeight() { provideSize(); return _height; } /** * @return _width the current icon width in (screen) pixels. */ public int getIconWidth() { provideSize(); return _width; } /** * Sets the size of an icon (width==height) to size. Does not override a * SizeProvider! * * @param size * The size of the width and the height (pixels). */ public void setWHSize(int size) { _width = size; _height = size; } /** * Sets the size of an icon to dimension d. Does not override a SizeProvider! * @param d */ public void setWHSize(Dimension d) { _width=d.width; _height=d.height; } /** * Set a size provider on this icon. To be able to dynamically adjust the * size. * * @param provider */ public void setSizeProvider(SizeProvider provider) { _provider = provider; } /** * Sets a dimension size provider. Overrides setSizeProvider for the SizeProvider interface. * @param prov */ public void setSizeProvider(DimensionProvider prov) { _dprovider=prov; } // Constructors private static boolean initialized = false; private static FlamencoIconAdapter NEW; private static FlamencoIconAdapter SAVE; private static FlamencoIconAdapter LOAD; private static FlamencoIconAdapter CUT; private static FlamencoIconAdapter COPY; private static FlamencoIconAdapter PASTE; private static FlamencoIconAdapter UNDO; private static FlamencoIconAdapter REDO; private static FlamencoIconAdapter SELECT_ALL; private static FlamencoIconAdapter INDENTMORE; private static FlamencoIconAdapter INDENTLESS; private static FlamencoIconAdapter NOIMAGE; private static FlamencoIconAdapter QUIT; private static FlamencoIconAdapter HELP; private static FlamencoIconAdapter ZOOM_100; private static FlamencoIconAdapter ZOOM_MORE; private static FlamencoIconAdapter ZOOM_LESS; private static FlamencoIconAdapter ZOOM_FIT_WIDTH; private static FlamencoIconAdapter ZOOM_FIT_HEIGHT; private static FlamencoIconAdapter NEXT; private static FlamencoIconAdapter PREVIOUS; private static FlamencoIconAdapter LAST; private static FlamencoIconAdapter FIRST; private static FlamencoIconAdapter CLOSE; private static FlamencoIconAdapter PRINT; private static FlamencoIconAdapter PRINT_PREFS; private static FlamencoIconAdapter INSERT_HYPERLINK; private static FlamencoIconAdapter REMOVE_HYPERLINK; private void initIcons() { if (!initialized) { initialized = true; NEW = new Document_new(); SAVE = new Document_save(); LOAD = new Document_open(); CUT = new Edit_cut(); COPY = new Edit_copy(); PASTE = new Edit_paste(); UNDO = new Edit_undo(); REDO = new Edit_redo(); SELECT_ALL = new Edit_select_all(); INDENTMORE = new Format_indent_more(); INDENTLESS = new Format_indent_less(); NOIMAGE = new NoImage(); QUIT = new Quit(); HELP = new Help(); ZOOM_100 = new Zoom100(); ZOOM_MORE = new ZoomMore(); ZOOM_LESS = new ZoomLess(); ZOOM_FIT_WIDTH = new ZoomFitWidth(); ZOOM_FIT_HEIGHT = new ZoomFitHeight(); NEXT = new Next(); PREVIOUS = new Previous(); LAST = new Last(); FIRST = new First(); CLOSE = new Close(); PRINT = new Print(); PRINT_PREFS=new PrintPrefs(); INSERT_HYPERLINK=new InsertHyperlink(); INSERT_HYPERLINK=new RemoveHyperlink(); } } /** * Constructs a JXMLNoteIcon of type <code>type</code> with width * <code>w</code> and height <code>h</code> * * @param type * @param w * @param h */ public JXMLNoteIcon(String type, int w, int h) { _width = w; _height = h; _iconType = type; initIcons(); } /** * * Constructs a JXMLNoteIcon of type <code>type</code> with standard width * and height (18,18). * * @param type */ public JXMLNoteIcon(String type) { _iconType = type; initIcons(); } /** * * Constructs a JXMLNoteIcon of type <code>type</code> with width * <code>w</code> and height <code>h</code> and an associated * {@link JXMLNoteIconPainter} that is called to paint the icon, instead of * the standard paint functions. * * @param type * @param p * @param w * @param h * */ public JXMLNoteIcon(String type, JXMLNoteIconPainter p, int w, int h) { _painter = p; _iconType = type; _width = w; _height = h; initIcons(); } /** * Constructs a JXMLNoteIcon of type <code>type</code> with standard width * and height (18,18) and an associated {@link JXMLNoteIconPainter} that is * called to paint the icon, instead of the standard paint functions. * * @param type * @param p */ public JXMLNoteIcon(String type, JXMLNoteIconPainter p) { _painter = p; _iconType = type; initIcons(); } protected JXMLNoteIcon(JXMLNoteIcon icn) { this._painter=icn._painter; this._iconType=icn._iconType; this._width=icn._width; this._height=icn._height; initIcons(); } }