/*
* @(#)ButtonFactory.java
*
* Copyright (c) 1996-2010 The authors and contributors of JHotDraw.
* You may not use, copy or modify this file, except in compliance with the
* accompanying license terms.
*/
package org.jhotdraw.draw.action;
import org.jhotdraw.geom.DoubleStroke;
import javax.annotation.Nullable;
import org.jhotdraw.app.action.edit.PasteAction;
import org.jhotdraw.app.action.edit.CutAction;
import org.jhotdraw.app.action.edit.CopyAction;
import org.jhotdraw.app.action.edit.DuplicateAction;
import org.jhotdraw.draw.tool.Tool;
import org.jhotdraw.draw.tool.DelegationSelectionTool;
import org.jhotdraw.draw.event.ToolEvent;
import org.jhotdraw.draw.event.ToolListener;
import org.jhotdraw.draw.decoration.LineDecoration;
import org.jhotdraw.draw.decoration.ArrowTip;
import org.jhotdraw.draw.event.SelectionComponentRepainter;
import org.jhotdraw.gui.JPopupButton;
import org.jhotdraw.util.*;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.event.*;
import java.beans.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
import javax.swing.plaf.ColorChooserUI;
import javax.swing.text.*;
import org.jhotdraw.app.action.*;
import org.jhotdraw.app.Disposable;
import org.jhotdraw.color.HSBColorSpace;
import static org.jhotdraw.draw.AttributeKeys.*;
import org.jhotdraw.draw.*;
import org.jhotdraw.draw.event.ToolAdapter;
import org.jhotdraw.gui.JComponentPopup;
import org.jhotdraw.gui.JFontChooser;
/**
* ButtonFactory. <p> Design pattern:<br> Name: Abstract Factory.<br> Role:
* Abstract Factory.<br> Partners: {@link org.jhotdraw.samples.draw.DrawApplicationModel}
* as Client,
* {@link org.jhotdraw.samples.draw.DrawView} as Client,
* {@link org.jhotdraw.samples.draw.DrawingPanel} as Client.
*
* FIXME - All buttons created using the ButtonFactory must automatically become
* disabled/enabled, when the DrawingEditor is disabled/enabled.
*
* @author Werner Randelshofer
* @version $Id$
*/
public class ButtonFactory {
/**
* Mac OS X 'Apple Color Palette'. This palette has 8 columns.
*/
public static final java.util.List<ColorIcon> DEFAULT_COLORS;
static {
LinkedList<ColorIcon> m = new LinkedList<>();
m.add(new ColorIcon(0x800000, "Cayenne"));
m.add(new ColorIcon(0x808000, "Asparagus"));
m.add(new ColorIcon(0x008000, "Clover"));
m.add(new ColorIcon(0x008080, "Teal"));
m.add(new ColorIcon(0x000080, "Midnight"));
m.add(new ColorIcon(0x800080, "Plum"));
m.add(new ColorIcon(0x7f7f7f, "Tin"));
m.add(new ColorIcon(0x808080, "Nickel"));
m.add(new ColorIcon(0xff0000, "Maraschino"));
m.add(new ColorIcon(0xffff00, "Lemon"));
m.add(new ColorIcon(0x00ff00, "Spring"));
m.add(new ColorIcon(0x00ffff, "Turquoise"));
m.add(new ColorIcon(0x0000ff, "Blueberry"));
m.add(new ColorIcon(0xff00ff, "Magenta"));
m.add(new ColorIcon(0x666666, "Steel"));
m.add(new ColorIcon(0x999999, "Aluminium"));
m.add(new ColorIcon(0xff6666, "Salmon"));
m.add(new ColorIcon(0xffff66, "Banana"));
m.add(new ColorIcon(0x66ff66, "Flora"));
m.add(new ColorIcon(0x66ffff, "Ice"));
m.add(new ColorIcon(0x6666ff, "Orchid"));
m.add(new ColorIcon(0xff66ff, "Bubblegum"));
m.add(new ColorIcon(0x4c4c4c, "Iron"));
m.add(new ColorIcon(0xb3b3b3, "Magnesium"));
m.add(new ColorIcon(0x804000, "Mocha"));
m.add(new ColorIcon(0x408000, "Fern"));
m.add(new ColorIcon(0x008040, "Moss"));
m.add(new ColorIcon(0x004080, "Ocean"));
m.add(new ColorIcon(0x400080, "Eggplant"));
m.add(new ColorIcon(0x800040, "Maroon"));
m.add(new ColorIcon(0x333333, "Tungsten"));
m.add(new ColorIcon(0xcccccc, "Silver"));
m.add(new ColorIcon(0xff8000, "Tangerine"));
m.add(new ColorIcon(0x80ff00, "Lime"));
m.add(new ColorIcon(0x00ff80, "Sea Foam"));
m.add(new ColorIcon(0x0080ff, "Aqua"));
m.add(new ColorIcon(0x8000ff, "Grape"));
m.add(new ColorIcon(0xff0080, "Strawberry"));
m.add(new ColorIcon(0x191919, "Lead"));
m.add(new ColorIcon(0xe6e6e6, "Mercury"));
m.add(new ColorIcon(0xffcc66, "Cantaloupe"));
m.add(new ColorIcon(0xccff66, "Honeydew"));
m.add(new ColorIcon(0x66ffcc, "Spindrift"));
m.add(new ColorIcon(0x66ccff, "Sky"));
m.add(new ColorIcon(0xcc66ff, "Lavender"));
m.add(new ColorIcon(0xff6fcf, "Carnation"));
m.add(new ColorIcon(0x000000, "Licorice"));
m.add(new ColorIcon(0xffffff, "Snow"));
DEFAULT_COLORS = Collections.unmodifiableList(m);
}
public static final int DEFAULT_COLORS_COLUMN_COUNT = 8;
/**
* Websave color palette as used by Macromedia Fireworks. This palette has
* 19 columns. The leftmost column contains a redundant set of color icons
* to make selection of gray scales and of the primary colors easier.
*/
public static final java.util.List<ColorIcon> WEBSAVE_COLORS;
static {
LinkedList<ColorIcon> m = new LinkedList<>();
for (int b = 0; b <= 0xff; b += 0x33) {
int rgb = (b << 16) | (b << 8) | b;
m.add(new ColorIcon(rgb));
for (int r = 0; r <= 0x66; r += 0x33) {
for (int g = 0; g <= 0xff; g += 0x33) {
rgb = (r << 16) | (g << 8) | b;
m.add(new ColorIcon(rgb));
}
}
}
int[] firstColumn = {
0xff0000,
0x00ff00,
0x0000ff,
0xff00ff,
0x00ffff,
0xffff00,};
for (int b = 0x0, i = 0; b <= 0xff; b += 0x33, i++) {
int rgb = (b << 16) | (b << 8) | b;
m.add(new ColorIcon(firstColumn[i]));
for (int r = 0x99; r <= 0xff; r += 0x33) {
for (int g = 0; g <= 0xff; g += 0x33) {
rgb = 0xff000000 | (r << 16) | (g << 8) | b;
m.add(new ColorIcon(rgb, "#" + Integer.toHexString(rgb).substring(2)));
}
}
}
WEBSAVE_COLORS = Collections.unmodifiableList(m);
}
public static final int WEBSAVE_COLORS_COLUMN_COUNT = 19;
/**
* HSB color palette with a set of colors chosen based on a physical
* criteria. <p> This is a 'human friendly' color palette which arranges the
* color in a way that makes it easy for humans to select the desired color.
* The colors are ordered in a way which minimizes the color contrast effect
* in the human visual system. <p> This palette has 12 columns and 10 rows.
* <p> The topmost row contains a null-color and a gray scale from white to
* black in 10 percent steps. <p> The remaining rows contain colors taken
* from the outer hull of the HSB color model: <p> The columns are ordered
* by hue starting with red - the lowest wavelength - and ending with purple
* - the highest wavelength. There are 12 different hues, so that all
* primary colors with their additive complements can be selected. <p> The
* rows are orderd by brightness with the brightest color at the top (sky)
* and the darkest color at the bottom (earth). The first 5 rows contain
* colors with maximal brightness and a saturation ranging form 20% up to
* 100%. The remaining 4 rows contain colors with maximal saturation and a
* brightness ranging from 90% to 20% (this also makes for a range from 100%
* to 20% if the 5th row is taken into account).
*/
public static final java.util.List<ColorIcon> HSB_COLORS;
public static final int HSB_COLORS_COLUMN_COUNT = 12;
/**
* This is the same palette as HSB_COLORS, but all color values are
* specified in the sRGB color space.
*/
public static final java.util.List<ColorIcon> HSB_COLORS_AS_RGB;
public static final int HSB_COLORS_AS_RGB_COLUMN_COUNT = 12;
static {
ColorSpace grayCS = ColorSpace.getInstance(ColorSpace.CS_GRAY);
HSBColorSpace hsbCS = HSBColorSpace.getInstance();
LinkedList<ColorIcon> m = new LinkedList<>();
ResourceBundleUtil labels = ResourceBundleUtil.getBundle("org.jhotdraw.draw.Labels");
m.add(new ColorIcon(new Color(0, true), labels.getToolTipTextProperty("attribute.color.noColor")));
for (int b = 10; b >= 0; b--) {
Color c = new Color(grayCS, new float[]{b / 10f}, 1f);
m.add(new ColorIcon(c,//
labels.getFormatted("attribute.color.grayComponents.toolTipText", b * 10)));
}
for (int s = 2; s <= 8; s += 2) {
for (int h = 0; h < 12; h++) {
Color c = new Color(hsbCS, new float[]{(h) / 12f, s * 0.1f, 1f}, 1f);
m.add(new ColorIcon(c,//
labels.getFormatted("attribute.color.hsbComponents.toolTipText", h * 360 / 12, s * 10, 100)));
}
}
for (int b = 10; b >= 2; b -= 2) {
for (int h = 0; h < 12; h++) {
Color c = new Color(hsbCS, new float[]{(h) / 12f, 1f, b * 0.1f}, 1f);
m.add(new ColorIcon(new Color(hsbCS, new float[]{(h) / 12f, 1f, b * 0.1f}, 1f),//
labels.getFormatted("attribute.color.hsbComponents.toolTipText", h * 360 / 12, 100, b * 10)));
}
}
HSB_COLORS = Collections.unmodifiableList(m);
m = new LinkedList<>();
for (ColorIcon ci : HSB_COLORS) {
if (ci.getColor() == null) {
m.add(new ColorIcon(new Color(0, true), labels.getToolTipTextProperty("attribute.color.noColor")));
} else {
Color c = ci.getColor();
c = c.getColorSpace() == grayCS //
? new Color(c.getGreen(), c.getGreen(), c.getGreen(), c.getAlpha())//workaround for rounding error
: new Color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
m.add(new ColorIcon(c,//
labels.getFormatted("attribute.color.rgbComponents.toolTipText", c.getRed(), c.getGreen(), c.getBlue())));
}
}
HSB_COLORS_AS_RGB = Collections.unmodifiableList(m);
}
private static class ToolButtonListener implements ItemListener {
private Tool tool;
private DrawingEditor editor;
public ToolButtonListener(Tool t, DrawingEditor editor) {
this.tool = t;
this.editor = editor;
}
@Override
public void itemStateChanged(ItemEvent evt) {
if (evt.getStateChange() == ItemEvent.SELECTED) {
editor.setTool(tool);
}
}
}
/**
* Prevent instance creation.
*/
private ButtonFactory() {
}
public static Collection<Action> createDrawingActions(DrawingEditor editor) {
return createDrawingActions(editor, new LinkedList<>());
}
public static Collection<Action> createDrawingActions(DrawingEditor editor, java.util.List<Disposable> dsp) {
LinkedList<Action> list = new LinkedList<>();
AbstractSelectedAction a;
list.add(new CutAction());
list.add(new CopyAction());
list.add(new PasteAction());
list.add(a = new SelectSameAction(editor));
dsp.add(a);
return list;
}
public static Collection<Action> createSelectionActions(DrawingEditor editor) {
LinkedList<Action> a = new LinkedList<>();
a.add(new DuplicateAction());
a.add(null); // separator
a.add(new GroupAction(editor));
a.add(new UngroupAction(editor));
a.add(null); // separator
a.add(new BringToFrontAction(editor));
a.add(new SendToBackAction(editor));
return a;
}
public static JToggleButton addSelectionToolTo(JToolBar tb, final DrawingEditor editor) {
return addSelectionToolTo(tb, editor, createDrawingActions(editor), createSelectionActions(editor));
}
public static JToggleButton addSelectionToolTo(JToolBar tb, final DrawingEditor editor,
Collection<Action> drawingActions, Collection<Action> selectionActions) {
Tool selectionTool = new DelegationSelectionTool(
drawingActions, selectionActions);
return addSelectionToolTo(tb, editor, selectionTool);
}
public static JToggleButton addSelectionToolTo(JToolBar tb, final DrawingEditor editor, Tool selectionTool) {
ResourceBundleUtil labels = ResourceBundleUtil.getBundle("org.jhotdraw.draw.Labels");
JToggleButton t;
Tool tool;
HashMap<String, Object> attributes;
ButtonGroup group;
if (tb.getClientProperty("toolButtonGroup") instanceof ButtonGroup) {
group = (ButtonGroup) tb.getClientProperty("toolButtonGroup");
} else {
group = new ButtonGroup();
tb.putClientProperty("toolButtonGroup", group);
}
// Selection tool
editor.setTool(selectionTool);
t = new JToggleButton();
final JToggleButton defaultToolButton = t;
if (!(tb.getClientProperty("toolHandler") instanceof ToolListener)) {
ToolListener toolHandler;
toolHandler = new ToolAdapter() {
@Override
public void toolDone(ToolEvent event) {
defaultToolButton.setSelected(true);
}
};
tb.putClientProperty("toolHandler", toolHandler);
}
labels.configureToolBarButton(t, "selectionTool");
t.setSelected(true);
t.addItemListener(
new ToolButtonListener(selectionTool, editor));
t.setFocusable(false);
group.add(t);
tb.add(t);
return t;
}
/**
* Method addSelectionToolTo must have been invoked prior to this on the
* JToolBar.
*
*/
public static JToggleButton addToolTo(JToolBar tb, DrawingEditor editor,
Tool tool, String labelKey,
ResourceBundleUtil labels) {
ButtonGroup group = (ButtonGroup) tb.getClientProperty("toolButtonGroup");
ToolListener toolHandler = (ToolListener) tb.getClientProperty("toolHandler");
JToggleButton t = new JToggleButton();
labels.configureToolBarButton(t, labelKey);
t.addItemListener(new ToolButtonListener(tool, editor));
t.setFocusable(false);
tool.addToolListener(toolHandler);
group.add(t);
tb.add(t);
return t;
}
public static void addZoomButtonsTo(JToolBar bar, final DrawingEditor editor) {
bar.add(createZoomButton(editor));
}
public static AbstractButton createZoomButton(final DrawingEditor editor) {
ResourceBundleUtil labels = ResourceBundleUtil.getBundle("org.jhotdraw.draw.Labels");
final JPopupButton zoomPopupButton = new JPopupButton();
labels.configureToolBarButton(zoomPopupButton, "view.zoomFactor");
zoomPopupButton.setFocusable(false);
if (editor.getDrawingViews().size() == 0) {
zoomPopupButton.setText("100 %");
} else {
zoomPopupButton.setText((int) (editor.getDrawingViews().iterator().next().getScaleFactor() * 100) + " %");
}
editor.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
// String constants are interned
if (evt.getPropertyName() == DrawingEditor.ACTIVE_VIEW_PROPERTY) {
if (evt.getNewValue() == null) {
zoomPopupButton.setText("100 %");
} else {
zoomPopupButton.setText((int) (editor.getActiveView().getScaleFactor() * 100) + " %");
}
}
}
});
double[] factors = {16, 8, 5, 4, 3, 2, 1.5, 1.25, 1, 0.75, 0.5, 0.25, 0.10};
for (int i = 0; i < factors.length; i++) {
zoomPopupButton.add(
new ZoomEditorAction(editor, factors[i], zoomPopupButton) {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(java.awt.event.ActionEvent e) {
super.actionPerformed(e);
zoomPopupButton.setText((int) (editor.getActiveView().getScaleFactor() * 100) + " %");
}
});
}
//zoomPopupButton.setPreferredSize(new Dimension(16,16));
zoomPopupButton.setFocusable(false);
return zoomPopupButton;
}
public static AbstractButton createZoomButton(DrawingView view) {
return createZoomButton(view, new double[]{
5, 4, 3, 2, 1.5, 1.25, 1, 0.75, 0.5, 0.25, 0.10
});
}
public static AbstractButton createZoomButton(final DrawingView view, double[] factors) {
ResourceBundleUtil labels = ResourceBundleUtil.getBundle("org.jhotdraw.draw.Labels");
final JPopupButton zoomPopupButton = new JPopupButton();
labels.configureToolBarButton(zoomPopupButton, "view.zoomFactor");
zoomPopupButton.setFocusable(false);
zoomPopupButton.setText((int) (view.getScaleFactor() * 100) + " %");
view.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
// String constants are interned
if (evt.getPropertyName() == "scaleFactor") {
zoomPopupButton.setText((int) (view.getScaleFactor() * 100) + " %");
}
}
});
for (int i = 0; i < factors.length; i++) {
zoomPopupButton.add(
new ZoomAction(view, factors[i], zoomPopupButton) {
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(java.awt.event.ActionEvent e) {
super.actionPerformed(e);
zoomPopupButton.setText((int) (view.getScaleFactor() * 100) + " %");
}
});
}
//zoomPopupButton.setPreferredSize(new Dimension(16,16));
zoomPopupButton.setFocusable(false);
return zoomPopupButton;
}
/**
* Creates toolbar buttons and adds them to the specified JToolBar
*/
public static void addAttributesButtonsTo(JToolBar bar, DrawingEditor editor) {
JButton b;
b = bar.add(new PickAttributesAction(editor));
b.setFocusable(false);
b = bar.add(new ApplyAttributesAction(editor));
b.setFocusable(false);
bar.addSeparator();
addColorButtonsTo(bar, editor);
bar.addSeparator();
addStrokeButtonsTo(bar, editor);
bar.addSeparator();
addFontButtonsTo(bar, editor);
}
public static void addColorButtonsTo(JToolBar bar, DrawingEditor editor) {
addColorButtonsTo(bar, editor, DEFAULT_COLORS, DEFAULT_COLORS_COLUMN_COUNT);
}
public static void addColorButtonsTo(JToolBar bar, DrawingEditor editor,
java.util.List<ColorIcon> colors, int columnCount) {
ResourceBundleUtil labels = ResourceBundleUtil.getBundle("org.jhotdraw.draw.Labels");
bar.add(createEditorColorButton(editor, STROKE_COLOR, colors, columnCount, "attribute.strokeColor", labels, new HashMap<>()));
bar.add(createEditorColorButton(editor, FILL_COLOR, colors, columnCount, "attribute.fillColor", labels, new HashMap<>()));
bar.add(createEditorColorButton(editor, TEXT_COLOR, colors, columnCount, "attribute.textColor", labels, new HashMap<>()));
}
/**
* Creates a color button, with an action region and a popup menu. The
* button works like the color button in Microsoft Office: <ul> <li>When the
* user clicks on the action region, the default color of the DrawingEditor
* is applied to the selected figures.</li> <li>When the user opens the
* popup menu, a color palette is displayed. Choosing a color from the
* palette changes the default color of the editor and also changes the
* color of the selected figures.</li> <li>A rectangle on the color button
* displays the current default color of the DrawingEditor. The rectangle
* has the dimensions 1, 17, 20, 4 (x, y, width, height).</li> </ul>
*
* @param editor The DrawingEditor.
* @param attributeKey The AttributeKey of the color.
* @param swatches A list with labeled colors containing the color palette
* of the popup menu. The actual labels are retrieved from the supplied
* resource bundle. This is usually a LinkedMap, so that the colors have a
* predictable order.
* @param columnCount The number of columns of the color palette.
* @param labelKey The resource bundle key used for retrieving the icon and
* the tooltip of the button.
* @param labels The resource bundle.
*/
public static JPopupButton createEditorColorButton(
DrawingEditor editor, AttributeKey<Color> attributeKey,
java.util.List<ColorIcon> swatches, int columnCount,
String labelKey, ResourceBundleUtil labels) {
return createEditorColorButton(
editor, attributeKey,
swatches, columnCount,
labelKey, labels,
null);
}
/**
* Creates a color button, with an action region and a popup menu. The
* button works like the color button in Microsoft Office: <ul> <li>When the
* user clicks on the action region, the default color of the DrawingEditor
* is applied to the selected figures.</li> <li>When the user opens the
* popup menu, a color palette is displayed. Choosing a color from the
* palette changes the default color of the editor and also changes the
* color of the selected figures.</li> <li>A rectangle on the color button
* displays the current default color of the DrawingEditor. The rectangle
* has the dimensions 1, 17, 20, 4 (x, y, width, height).</li> </ul>
*
* @param editor The DrawingEditor.
* @param attributeKey The AttributeKey of the color.
* @param swatches A list with labeled colors containing the color palette
* of the popup menu. The actual labels are retrieved from the supplied
* resource bundle. This is usually a LinkedMap, so that the colors have a
* predictable order.
* @param columnCount The number of columns of the color palette.
* @param labelKey The resource bundle key used for retrieving the icon and
* the tooltip of the button.
* @param labels The resource bundle.
* @param defaultAttributes A set of attributes which are also applied to
* the selected figures, when a color is selected. This can be used, to set
* attributes that otherwise prevent the color from being shown. For
* example, when the color attribute is set, we wan't the gradient attribute
* of the Figure to be cleared.
*/
public static JPopupButton createEditorColorButton(
DrawingEditor editor, AttributeKey<Color> attributeKey,
java.util.List<ColorIcon> swatches, int columnCount,
String labelKey, ResourceBundleUtil labels,
@Nullable Map<AttributeKey<?>, Object> defaultAttributes) {
return createEditorColorButton(editor, attributeKey,
swatches, columnCount, labelKey, labels, defaultAttributes,
new Rectangle(1, 17, 20, 4));
}
/**
* Creates a color button, with an action region and a popup menu. The
* button works like the color button in Microsoft Office: <ul> <li>When the
* user clicks on the action region, the default color of the DrawingEditor
* is applied to the selected figures.</li> <li>When the user opens the
* popup menu, a color palette is displayed. Choosing a color from the
* palette changes the default color of the editor and also changes the
* color of the selected figures.</li> <li>A shape on the color button
* displays the current default color of the DrawingEditor.</li> </ul>
*
* @param editor The DrawingEditor.
* @param attributeKey The AttributeKey of the color.
* @param swatches A list with labeled colors containing the color palette
* of the popup menu. The actual labels are retrieved from the supplied
* resource bundle. This is usually a LinkedHashMap, so that the colors have
* a predictable order.
* @param columnCount The number of columns of the color palette.
* @param labelKey The resource bundle key used for retrieving the icon and
* the tooltip of the button.
* @param labels The resource bundle.
* @param defaultAttributes A set of attributes which are also applied to
* the selected figures, when a color is selected. This can be used, to set
* attributes that otherwise prevent the color from being shown. For
* example, when the color attribute is set, we wan't the gradient attribute
* of the Figure to be cleared.
* @param colorShape This shape is superimposed on the icon of the button.
* The shape is drawn with the default color of the DrawingEditor.
*/
public static JPopupButton createEditorColorButton(
DrawingEditor editor, AttributeKey<Color> attributeKey,
java.util.List<ColorIcon> swatches, int columnCount,
String labelKey, ResourceBundleUtil labels,
@Nullable Map<AttributeKey<?>, Object> defaultAttributes,
Shape colorShape) {
final JPopupButton popupButton = new JPopupButton();
popupButton.setPopupAlpha(1f);
if (defaultAttributes == null) {
defaultAttributes = new HashMap<>();
}
popupButton.setAction(
new DefaultAttributeAction(editor, attributeKey, defaultAttributes),
new Rectangle(0, 0, 22, 22));
popupButton.setColumnCount(columnCount, false);
boolean hasNullColor = false;
for (ColorIcon swatch : swatches) {
AttributeAction a;
HashMap<AttributeKey<?>, Object> attributes = new HashMap<>(defaultAttributes);
Color swatchColor = swatch.getColor();
attributes.put(attributeKey, swatchColor);
if (swatchColor == null || swatchColor.getAlpha() == 0) {
hasNullColor = true;
}
popupButton.add(a =
new AttributeAction(
editor,
attributes,
labels.getToolTipTextProperty(labelKey),
swatch));
a.putValue(Action.SHORT_DESCRIPTION, swatch.getName());
a.setUpdateEnabledState(false);
}
// No color
if (!hasNullColor) {
AttributeAction a;
HashMap<AttributeKey<?>, Object> attributes = new HashMap<>(defaultAttributes);
attributes.put(attributeKey, null);
popupButton.add(a =
new AttributeAction(
editor,
attributes,
labels.getToolTipTextProperty("attribute.color.noColor"),
new ColorIcon(null, labels.getToolTipTextProperty("attribute.color.noColor"), swatches.get(0).getIconWidth(), swatches.get(0).getIconHeight())));
a.putValue(Action.SHORT_DESCRIPTION, labels.getToolTipTextProperty("attribute.color.noColor"));
a.setUpdateEnabledState(false);
}
// Color chooser
ImageIcon chooserIcon = new ImageIcon(
Images.createImage(
ButtonFactory.class, "/org/jhotdraw/draw/action/images/attribute.color.colorChooser.png"));
Action a;
popupButton.add(
a = new EditorColorChooserAction(
editor,
attributeKey,
"color",
chooserIcon,
defaultAttributes));
labels.configureToolBarButton(popupButton, labelKey);
a.putValue(Action.SHORT_DESCRIPTION, labels.getToolTipTextProperty("attribute.color.colorChooser"));
Icon icon = new EditorColorIcon(editor,
attributeKey,
labels.getLargeIconProperty(labelKey, ButtonFactory.class).getImage(),
colorShape);
popupButton.setIcon(icon);
popupButton.setDisabledIcon(icon);
popupButton.setFocusable(false);
editor.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
popupButton.repaint();
}
});
return popupButton;
}
/**
* Creates a color button, with an action region and a popup menu. The
* button works like the color button in Adobe Fireworks: <ul> <li>When the
* user clicks at the button a popup menu with a color palette is displayed.
* Choosing a color from the palette changes the default color of the editor
* and also changes the color of the selected figures.</li> <li>A shape on
* the color button displays the color of the selected figures. If no
* figures are selected, the default color of the DrawingEditor is
* displayed.</li> <li>A rectangle on the color button displays the current
* default color of the DrawingEditor. The rectangle has the dimensions 1,
* 17, 20, 4 (x, y, width, height).</li> </ul>
*
* @param editor The DrawingEditor.
* @param attributeKey The AttributeKey of the color.
* @param swatches A list with labeled colors containing the color palette
* of the popup menu. The actual labels are retrieved from the supplied
* resource bundle. This is usually a LinkedHashMap, so that the colors have
* a predictable order.
* @param columnCount The number of columns of the color palette.
* @param labelKey The resource bundle key used for retrieving the icon and
* the tooltip of the button.
* @param labels The resource bundle.
*/
public static JPopupButton createSelectionColorButton(
DrawingEditor editor, AttributeKey<Color> attributeKey,
java.util.List<ColorIcon> swatches, int columnCount,
String labelKey, ResourceBundleUtil labels) {
return createSelectionColorButton(
editor, attributeKey,
swatches, columnCount,
labelKey, labels,
null);
}
/**
* Creates a color button, with an action region and a popup menu. The
* button works like the color button in Adobe Fireworks: <ul> <li>When the
* user clicks at the button a popup menu with a color palette is displayed.
* Choosing a color from the palette changes the default color of the editor
* and also changes the color of the selected figures.</li> <li>A rectangle
* on the color button displays the current default color of the
* DrawingEditor. The rectangle has the dimensions 1, 17, 20, 4 (x, y,
* width, height).</li> </ul>
*
* @param editor The DrawingEditor.
* @param attributeKey The AttributeKey of the color.
* @param swatches A list with labeled colors containing the color palette
* of the popup menu. The actual labels are retrieved from the supplied
* resource bundle. This is usually a LinkedHashMap, so that the colors have
* a predictable order.
* @param columnCount The number of columns of the color palette.
* @param labelKey The resource bundle key used for retrieving the icon and
* the tooltip of the button.
* @param labels The resource bundle.
* @param defaultAttributes A set of attributes which are also applied to
* the selected figures, when a color is selected. This can be used, to set
* attributes that otherwise prevent the color from being shown. For
* example, when the color attribute is set, we wan't the gradient attribute
* of the Figure to be cleared.
*/
public static JPopupButton createSelectionColorButton(
DrawingEditor editor, AttributeKey<Color> attributeKey,
java.util.List<ColorIcon> swatches, int columnCount,
String labelKey, ResourceBundleUtil labels,
@Nullable Map<AttributeKey<?>, Object> defaultAttributes) {
return createSelectionColorButton(editor, attributeKey,
swatches, columnCount, labelKey, labels, defaultAttributes,
new Rectangle(1, 17, 20, 4));
}
/**
* Creates a color button, with an action region and a popup menu. The
* button works like the color button in Adobe Fireworks: <ul> <li>When the
* user clicks at the button a popup menu with a color palette is displayed.
* Choosing a color from the palette changes the default color of the editor
* and also changes the color of the selected figures.</li> <li>A shape on
* the color button displays the color of the selected figures. If no
* figures are selected, the default color of the DrawingEditor is
* displayed.</li> </ul>
*
* @param editor The DrawingEditor.
* @param attributeKey The AttributeKey of the color.
* @param swatches A list with labeled colors containing the color palette
* of the popup menu. The actual labels are retrieved from the supplied
* resource bundle. This is usually a LinkedHashMap, so that the colors have
* a predictable order.
* @param columnCount The number of columns of the color palette.
* @param labelKey The resource bundle key used for retrieving the icon and
* the tooltip of the button.
* @param labels The resource bundle.
* @param defaultAttributes A set of attributes which are also applied to
* the selected figures, when a color is selected. This can be used, to set
* attributes that otherwise prevent the color from being shown. For
* example, when the color attribute is set, we wan't the gradient attribute
* of the Figure to be cleared.
* @param colorShape This shape is superimposed on the icon of the button.
* The shape is drawn with the default color of the DrawingEditor.
*/
public static JPopupButton createSelectionColorButton(
DrawingEditor editor, AttributeKey<Color> attributeKey,
java.util.List<ColorIcon> swatches, int columnCount,
String labelKey, ResourceBundleUtil labels,
@Nullable Map<AttributeKey<?>, Object> defaultAttributes,
Shape colorShape) {
return createSelectionColorButton(editor, attributeKey,
swatches, columnCount, labelKey, labels, defaultAttributes,
colorShape, new LinkedList<>());
}
/**
* Creates a color button, with an action region and a popup menu. The
* button works like the color button in Adobe Fireworks: <ul> <li>When the
* user clicks at the button a popup menu with a color palette is displayed.
* Choosing a color from the palette changes the default color of the editor
* and also changes the color of the selected figures.</li> <li>A shape on
* the color button displays the color of the selected figures. If no
* figures are selected, the default color of the DrawingEditor is
* displayed.</li> </ul>
*
* @param editor The DrawingEditor.
* @param attributeKey The AttributeKey of the color.
* @param swatches A list with labeled colors containing the color palette
* of the popup menu. The actual labels are retrieved from the supplied
* resource bundle. This is usually a LinkedHashMap, so that the colors have
* a predictable order.
* @param columnCount The number of columns of the color palette.
* @param labelKey The resource bundle key used for retrieving the icon and
* the tooltip of the button.
* @param labels The resource bundle.
* @param defaultAttributes A set of attributes which are also applied to
* the selected figures, when a color is selected. This can be used, to set
* attributes that otherwise prevent the color from being shown. For
* example, when the color attribute is set, we wan't the gradient attribute
* of the Figure to be cleared.
* @param colorShape This shape is superimposed on the icon of the button.
* The shape is drawn with the default color of the DrawingEditor.
*/
public static JPopupButton createSelectionColorButton(
DrawingEditor editor, AttributeKey<Color> attributeKey,
java.util.List<ColorIcon> swatches, int columnCount,
String labelKey, ResourceBundleUtil labels,
@Nullable Map<AttributeKey<?>, Object> defaultAttributes,
Shape colorShape, java.util.List<Disposable> dsp) {
final JPopupButton popupButton = new JPopupButton();
popupButton.setPopupAlpha(1f);
if (defaultAttributes == null) {
defaultAttributes = new HashMap<>();
}
popupButton.setColumnCount(columnCount, false);
boolean hasNullColor = false;
for (ColorIcon swatch : swatches) {
AttributeAction a;
HashMap<AttributeKey<?>, Object> attributes = new HashMap<>(defaultAttributes);
if (swatch != null) {
Color swatchColor = swatch.getColor();
attributes.put(attributeKey, swatchColor);
if (swatchColor == null || swatchColor.getAlpha() == 0) {
hasNullColor = true;
}
popupButton.add(a =
new AttributeAction(
editor,
attributes,
labels.getToolTipTextProperty(labelKey),
swatch));
a.putValue(Action.SHORT_DESCRIPTION, swatch.getName());
a.setUpdateEnabledState(false);
dsp.add(a);
} else {
popupButton.add(new JPanel());
}
}
// No color
if (!hasNullColor) {
AttributeAction a;
HashMap<AttributeKey<?>, Object> attributes = new HashMap<>(defaultAttributes);
attributes.put(attributeKey, null);
popupButton.add(a =
new AttributeAction(
editor,
attributes,
labels.getToolTipTextProperty("attribute.color.noColor"),
new ColorIcon(null, labels.getToolTipTextProperty("attribute.color.noColor"))));
a.putValue(Action.SHORT_DESCRIPTION, labels.getToolTipTextProperty("attribute.color.noColor"));
a.setUpdateEnabledState(false);
dsp.add(a);
}
// Color chooser
ImageIcon chooserIcon = new ImageIcon(
Images.createImage(ButtonFactory.class, "/org/jhotdraw/draw/action/images/attribute.color.colorChooser.png"));
AttributeAction a;
popupButton.add(
a = new SelectionColorChooserAction(
editor,
attributeKey,
labels.getToolTipTextProperty("attribute.color.colorChooser"),
chooserIcon,
defaultAttributes));
a.putValue(Action.SHORT_DESCRIPTION, labels.getToolTipTextProperty("attribute.color.colorChooser"));
dsp.add(a);
labels.configureToolBarButton(popupButton, labelKey);
Icon icon = new SelectionColorIcon(editor,
attributeKey,
labels.getLargeIconProperty(labelKey, ButtonFactory.class).getImage(),
colorShape);
popupButton.setIcon(icon);
popupButton.setDisabledIcon(icon);
popupButton.setFocusable(false);
dsp.add(new SelectionComponentRepainter(editor, popupButton));
return popupButton;
}
public static JPopupButton createSelectionColorChooserButton(final DrawingEditor editor,
final AttributeKey<Color> attributeKey, String labelKey,
ResourceBundleUtil labels,
@Nullable Map<AttributeKey<?>, Object> defaultAttributes,
Shape colorShape, final java.util.List<Disposable> dsp) {
return createSelectionColorChooserButton(
editor, attributeKey, labelKey, labels, defaultAttributes, colorShape, null, dsp);
}
public static JPopupButton createSelectionColorChooserButton(final DrawingEditor editor,
final AttributeKey<Color> attributeKey, String labelKey,
ResourceBundleUtil labels,
@Nullable Map<AttributeKey<?>, Object> defaultAttributes,
Shape colorShape, @Nullable final Class<?> uiclass, @Nullable final java.util.List<Disposable> dsp) {
JPopupButton popupButton;
popupButton = new JPopupButton();
labels.configureToolBarButton(popupButton, labelKey);
popupButton.setFocusable(true);
popupButton.setRequestFocusEnabled(false);
// We lazily initialize the popup menu because creating a JColorChooser
// takes a lot of time.
JComponentPopup popupMenu = new JComponentPopup() {
private static final long serialVersionUID = 1L;
private JColorChooser colorChooser;
@Override
public void show(Component invoker, int x, int y) {
if (colorChooser == null) {
initialize();
}
Color c;
if (editor.getActiveView() != null && editor.getActiveView().getSelectionCount() > 0) {
c = editor.getActiveView().getSelectedFigures().iterator().next().get(attributeKey);
} else {
c = editor.getDefaultAttribute(attributeKey);
}
colorChooser.setColor(c == null ? new Color(0, true) : c);
super.show(invoker, x, y);
}
private void initialize() {
colorChooser = new JColorChooser();
colorChooser.setOpaque(true);
colorChooser.setBackground(Color.WHITE);
if (uiclass != null) {
try {
colorChooser.setUI((ColorChooserUI) Methods.invokeStatic(uiclass, "createUI", new Class<?>[]{JComponent.class}, new Object[]{colorChooser}));
} catch (NoSuchMethodException ex) {
ex.printStackTrace();
}
}
dsp.add(new SelectionColorChooserHandler(editor, attributeKey, colorChooser, this));
add(colorChooser);
}
};
popupButton.setPopupMenu(popupMenu);
popupButton.setPopupAlpha(1.0f);// must be set after we set the popup menu
Icon icon = new SelectionColorIcon(editor,
attributeKey,
labels.getLargeIconProperty(labelKey, ButtonFactory.class).getImage(),
colorShape);
popupButton.setIcon(icon);
popupButton.setDisabledIcon(icon);
popupButton.setFocusable(false);
if (dsp != null) {
dsp.add(new SelectionComponentRepainter(editor, popupButton));
}
return popupButton;
}
/**
* Creates a color button, with an action region and a popup menu. The
* button acts on attributes of the Drawing object in the current
* DrawingView of the DrawingEditor.
*
* @param editor The DrawingEditor.
* @param attributeKey The AttributeKey of the color.
* @param swatches A list with labeled colors containing the color palette
* of the popup menu. The actual labels are retrieved from the supplied
* resource bundle. This is usually a LinkedHashMap, so that the colors have
* a predictable order.
* @param columnCount The number of columns of the color palette.
* @param labelKey The resource bundle key used for retrieving the icon and
* the tooltip of the button.
* @param labels The resource bundle.
*/
public static JPopupButton createDrawingColorButton(
DrawingEditor editor, AttributeKey<Color> attributeKey,
java.util.List<ColorIcon> swatches, int columnCount,
String labelKey, ResourceBundleUtil labels) {
return createDrawingColorButton(
editor, attributeKey,
swatches, columnCount,
labelKey, labels,
null);
}
/**
* Creates a color button, with an action region and a popup menu. The
* button acts on attributes of the Drawing object in the current
* DrawingView of the DrawingEditor.
*
* @param editor The DrawingEditor.
* @param attributeKey The AttributeKey of the color.
* @param swatches A list with labeled colors containing the color palette
* of the popup menu. The actual labels are retrieved from the supplied
* resource bundle. This is usually a LinkedHashMap, so that the colors have
* a predictable order.
* @param columnCount The number of columns of the color palette.
* @param labelKey The resource bundle key used for retrieving the icon and
* the tooltip of the button.
* @param labels The resource bundle.
* @param defaultAttributes A set of attributes which are also applied to
* the selected figures, when a color is selected. This can be used, to set
* attributes that otherwise prevent the color from being shown. For
* example, when the color attribute is set, we wan't the gradient attribute
* of the Figure to be cleared.
*/
public static JPopupButton createDrawingColorButton(
DrawingEditor editor, AttributeKey<Color> attributeKey,
java.util.List<ColorIcon> swatches, int columnCount,
String labelKey, ResourceBundleUtil labels,
@Nullable Map<AttributeKey<?>, Object> defaultAttributes) {
return createDrawingColorButton(editor, attributeKey,
swatches, columnCount, labelKey, labels, defaultAttributes,
new Rectangle(1, 17, 20, 4));
}
/**
* Creates a color button, with an action region and a popup menu. The
* button acts on attributes of the Drawing object in the current
* DrawingView of the DrawingEditor.
*
* @param editor The DrawingEditor.
* @param attributeKey The AttributeKey of the color.
* @param swatches A list with labeled colors containing the color palette
* of the popup menu. The actual labels are retrieved from the supplied
* resource bundle. This is usually a LinkedHashMap, so that the colors have
* a predictable order.
* @param columnCount The number of columns of the color palette.
* @param labelKey The resource bundle key used for retrieving the icon and
* the tooltip of the button.
* @param labels The resource bundle.
* @param defaultAttributes A set of attributes which are also applied to
* the selected figures, when a color is selected. This can be used, to set
* attributes that otherwise prevent the color from being shown. For
* example, when the color attribute is set, we wan't the gradient attribute
* of the Figure to be cleared.
* @param colorShape This shape is superimposed on the icon of the button.
* The shape is drawn with the default color of the DrawingEditor.
*/
public static JPopupButton createDrawingColorButton(
DrawingEditor editor, AttributeKey<Color> attributeKey,
java.util.List<ColorIcon> swatches, int columnCount,
String labelKey, ResourceBundleUtil labels,
@Nullable Map<AttributeKey<?>, Object> defaultAttributes,
Shape colorShape) {
return createDrawingColorButton(editor, attributeKey,
swatches, columnCount, labelKey, labels, defaultAttributes,
colorShape, new LinkedList<>());
}
/**
* Creates a color button, with an action region and a popup menu. The
* button acts on attributes of the Drawing object in the current
* DrawingView of the DrawingEditor.
*
* @param editor The DrawingEditor.
* @param attributeKey The AttributeKey of the color.
* @param swatches A list with labeled colors containing the color palette
* of the popup menu. The actual labels are retrieved from the supplied
* resource bundle. This is usually a LinkedHashMap, so that the colors have
* a predictable order.
* @param columnCount The number of columns of the color palette.
* @param labelKey The resource bundle key used for retrieving the icon and
* the tooltip of the button.
* @param labels The resource bundle.
* @param defaultAttributes A set of attributes which are also applied to
* the selected figures, when a color is selected. This can be used, to set
* attributes that otherwise prevent the color from being shown. For
* example, when the color attribute is set, we wan't the gradient attribute
* of the Figure to be cleared.
* @param colorShape This shape is superimposed on the icon of the button.
* The shape is drawn with the default color of the DrawingEditor.
*/
public static JPopupButton createDrawingColorButton(
DrawingEditor editor, AttributeKey<Color> attributeKey,
java.util.List<ColorIcon> swatches, int columnCount,
String labelKey, ResourceBundleUtil labels,
@Nullable Map<AttributeKey<?>, Object> defaultAttributes,
Shape colorShape, java.util.List<Disposable> dsp) {
final JPopupButton popupButton = new JPopupButton();
popupButton.setPopupAlpha(1f);
if (defaultAttributes == null) {
defaultAttributes = new HashMap<>();
}
popupButton.setColumnCount(columnCount, false);
boolean hasNullColor = false;
for (ColorIcon swatch : swatches) {
DrawingAttributeAction a;
HashMap<AttributeKey<?>, Object> attributes = new HashMap<>(defaultAttributes);
if (swatch != null) {
Color swatchColor = swatch.getColor();
attributes.put(attributeKey, swatchColor);
if (swatchColor == null || swatchColor.getAlpha() == 0) {
hasNullColor = true;
}
popupButton.add(a =
new DrawingAttributeAction(
editor,
attributes,
labels.getToolTipTextProperty(labelKey),
swatch));
dsp.add(a);
a.putValue(Action.SHORT_DESCRIPTION, swatch.getName());
a.setUpdateEnabledState(false);
} else {
popupButton.add(new JPanel());
}
}
// No color
if (!hasNullColor) {
DrawingAttributeAction a;
HashMap<AttributeKey<?>, Object> attributes = new HashMap<>(defaultAttributes);
attributes.put(attributeKey, null);
popupButton.add(a =
new DrawingAttributeAction(
editor,
attributes,
labels.getToolTipTextProperty("attribute.color.noColor"),
new ColorIcon(null, labels.getToolTipTextProperty("attribute.color.noColor"))));
dsp.add(a);
a.putValue(Action.SHORT_DESCRIPTION, labels.getToolTipTextProperty("attribute.color.noColor"));
a.setUpdateEnabledState(false);
}
// Color chooser
ImageIcon chooserIcon = new ImageIcon(
Images.createImage(ButtonFactory.class, "/org/jhotdraw/draw/action/images/attribute.color.colorChooser.png"));
DrawingColorChooserAction a;
popupButton.add(
a = new DrawingColorChooserAction(
editor,
attributeKey,
"color",
chooserIcon,
defaultAttributes));
dsp.add(a);
labels.configureToolBarButton(popupButton, labelKey);
a.putValue(Action.SHORT_DESCRIPTION, labels.getToolTipTextProperty("attribute.color.colorChooser"));
Icon icon = new DrawingColorIcon(editor,
attributeKey,
labels.getLargeIconProperty(labelKey, ButtonFactory.class).getImage(),
colorShape);
popupButton.setIcon(icon);
popupButton.setDisabledIcon(icon);
popupButton.setFocusable(false);
if (editor != null) {
dsp.add(new SelectionComponentRepainter(editor, popupButton));
}
return popupButton;
}
public static JPopupButton createDrawingColorChooserButton(final DrawingEditor editor,
final AttributeKey<Color> attributeKey, String labelKey,
ResourceBundleUtil labels, @Nullable Map<AttributeKey<?>, Object> defaultAttributes,
Shape colorShape, @Nullable final java.util.List<Disposable> dsp) {
return createSelectionColorChooserButton(
editor, attributeKey, labelKey, labels, defaultAttributes, colorShape, null, dsp);
}
public static JPopupButton createDrawingColorChooserButton(final DrawingEditor editor,
final AttributeKey<Color> attributeKey, String labelKey,
ResourceBundleUtil labels, @Nullable Map<AttributeKey<?>, Object> defaultAttributes,
Shape colorShape, @Nullable final Class<?> uiclass, @Nullable final java.util.List<Disposable> dsp) {
JPopupButton popupButton;
popupButton = new JPopupButton();
labels.configureToolBarButton(popupButton, labelKey);
popupButton.setFocusable(true);
popupButton.setRequestFocusEnabled(false);
// We lazily initialize the popup menu because creating a JColorChooser
// takes a lot of time.
JComponentPopup popupMenu = new JComponentPopup() {
private static final long serialVersionUID = 1L;
private JColorChooser colorChooser;
@Override
public void show(Component invoker, int x, int y) {
if (colorChooser == null) {
initialize();
}
Color c;
if (editor.getActiveView() != null) {
c = editor.getActiveView().getDrawing().get(attributeKey);
} else {
c = editor.getDefaultAttribute(attributeKey);
}
colorChooser.setColor(c == null ? new Color(0, true) : c);
super.show(invoker, x, y);
}
private void initialize() {
colorChooser = new JColorChooser();
colorChooser.setOpaque(true);
colorChooser.setBackground(Color.WHITE);
if (uiclass != null) {
try {
colorChooser.setUI((ColorChooserUI) Methods.invokeStatic(uiclass, "createUI", new Class<?>[]{JComponent.class}, new Object[]{colorChooser}));
} catch (NoSuchMethodException ex) {
ex.printStackTrace();
}
}
dsp.add(new DrawingColorChooserHandler(editor, attributeKey, colorChooser, this));
add(colorChooser);
}
};
popupButton.setPopupMenu(popupMenu);
popupButton.setPopupAlpha(1.0f);// must be set after we set the popup menu
Icon icon = new DrawingColorIcon(editor,
attributeKey,
labels.getLargeIconProperty(labelKey, ButtonFactory.class).getImage(),
colorShape);
popupButton.setIcon(icon);
popupButton.setDisabledIcon(icon);
popupButton.setFocusable(false);
if (dsp != null) {
dsp.add(new SelectionComponentRepainter(editor, popupButton));
}
return popupButton;
}
public static void addStrokeButtonsTo(JToolBar bar, DrawingEditor editor) {
bar.add(createStrokeDecorationButton(editor));
bar.add(createStrokeWidthButton(editor));
bar.add(createStrokeDashesButton(editor));
bar.add(createStrokeTypeButton(editor));
bar.add(createStrokePlacementButton(editor));
bar.add(createStrokeCapButton(editor));
bar.add(createStrokeJoinButton(editor));
}
public static JPopupButton createStrokeWidthButton(DrawingEditor editor) {
return createStrokeWidthButton(
editor,
new double[]{0d, 0.5d, 1d, 2d, 3d, 5d, 9d, 13d},
ResourceBundleUtil.getBundle("org.jhotdraw.draw.Labels"));
}
public static JPopupButton createStrokeWidthButton(DrawingEditor editor,
ResourceBundleUtil labels) {
return createStrokeWidthButton(
editor,
new double[]{0.5d, 1d, 2d, 3d, 5d, 9d, 13d},
labels);
}
public static JPopupButton createStrokeWidthButton(DrawingEditor editor,
double[] widths) {
return createStrokeWidthButton(
editor, new double[]{0.5d, 1d, 2d, 3d, 5d, 9d, 13d},
ResourceBundleUtil.getBundle("org.jhotdraw.draw.Labels"));
}
public static JPopupButton createStrokeWidthButton(
DrawingEditor editor, double[] widths, ResourceBundleUtil labels) {
JPopupButton strokeWidthPopupButton = new JPopupButton();
labels.configureToolBarButton(strokeWidthPopupButton, "attribute.strokeWidth");
strokeWidthPopupButton.setFocusable(false);
NumberFormat formatter = NumberFormat.getInstance();
if (formatter instanceof DecimalFormat) {
((DecimalFormat) formatter).setMaximumFractionDigits(1);
((DecimalFormat) formatter).setMinimumFractionDigits(0);
}
for (int i = 0; i < widths.length; i++) {
String label = Double.toString(widths[i]);
Icon icon = new StrokeIcon(new BasicStroke((float) widths[i], BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
AttributeAction a = new AttributeAction(
editor,
STROKE_WIDTH, widths[i],
label,
icon);
a.putValue(ActionUtil.UNDO_PRESENTATION_NAME_KEY, labels.getString("attribute.strokeWidth.text"));
AbstractButton btn = strokeWidthPopupButton.add(a);
btn.setDisabledIcon(icon);
}
return strokeWidthPopupButton;
}
public static JPopupButton createStrokeDecorationButton(DrawingEditor editor) {
ResourceBundleUtil labels = ResourceBundleUtil.getBundle("org.jhotdraw.draw.Labels");
JPopupButton strokeDecorationPopupButton = new JPopupButton();
labels.configureToolBarButton(strokeDecorationPopupButton, "attribute.strokeDecoration");
strokeDecorationPopupButton.setFocusable(false);
strokeDecorationPopupButton.setColumnCount(2, false);
LineDecoration[] decorations = {
// Arrow
new ArrowTip(0.35, 12, 11.3),
// Arrow
new ArrowTip(0.35, 13, 7),
// Generalization triangle
new ArrowTip(Math.PI / 5, 12, 9.8, true, true, false),
// Dependency arrow
new ArrowTip(Math.PI / 6, 12, 0, false, true, false),
// Link arrow
new ArrowTip(Math.PI / 11, 13, 0, false, true, true),
// Aggregation diamond
new ArrowTip(Math.PI / 6, 10, 18, false, true, false),
// Composition diamond
new ArrowTip(Math.PI / 6, 10, 18, true, true, true),
null
};
for (LineDecoration decoration : decorations) {
strokeDecorationPopupButton.add(new AttributeAction(editor, START_DECORATION, decoration, null, new LineDecorationIcon(decoration, true)));
strokeDecorationPopupButton.add(new AttributeAction(editor, END_DECORATION, decoration, null, new LineDecorationIcon(decoration, false)));
}
return strokeDecorationPopupButton;
}
public static JPopupButton createStrokeDashesButton(DrawingEditor editor) {
return createStrokeDashesButton(editor,
ResourceBundleUtil.getBundle("org.jhotdraw.draw.Labels"));
}
public static JPopupButton createStrokeDashesButton(DrawingEditor editor,
ResourceBundleUtil labels) {
return createStrokeDashesButton(editor, new double[][]{
null,
{4d, 4d},
{2d, 2d},
{4d, 2d},
{2d, 4d},
{8d, 2d},
{6d, 2d, 2d, 2d},},
labels);
}
public static JPopupButton createStrokeDashesButton(DrawingEditor editor,
double[][] dashes) {
return createStrokeDashesButton(editor, dashes,
ResourceBundleUtil.getBundle("org.jhotdraw.draw.Labels"));
}
public static JPopupButton createStrokeDashesButton(DrawingEditor editor,
double[][] dashes,
ResourceBundleUtil labels) {
return createStrokeDashesButton(editor, dashes,
labels, new LinkedList<>());
}
public static JPopupButton createStrokeDashesButton(DrawingEditor editor, double[][] dashes,
ResourceBundleUtil labels, java.util.List<Disposable> dsp) {
JPopupButton strokeDashesPopupButton = new JPopupButton();
labels.configureToolBarButton(strokeDashesPopupButton, "attribute.strokeDashes");
strokeDashesPopupButton.setFocusable(false);
//strokeDashesPopupButton.setColumnCount(2, false);
for (double[] dashe : dashes) {
float[] fdashes;
if (dashe == null) {
fdashes = null;
} else {
fdashes = new float[dashe.length];
for (int j = 0; j < dashe.length; j++) {
fdashes[j] = (float) dashe[j];
}
}
Icon icon = new StrokeIcon(
new BasicStroke(2f, BasicStroke.CAP_BUTT,
BasicStroke.JOIN_BEVEL, 10f, fdashes, 0));
AttributeAction a;
AbstractButton btn = strokeDashesPopupButton.add(a = new AttributeAction(editor, STROKE_DASHES, dashe, null, icon));
dsp.add(a);
btn.setDisabledIcon(icon);
}
return strokeDashesPopupButton;
}
public static JPopupButton createStrokeTypeButton(DrawingEditor editor) {
ResourceBundleUtil labels = ResourceBundleUtil.getBundle("org.jhotdraw.draw.Labels");
JPopupButton strokeTypePopupButton = new JPopupButton();
labels.configureToolBarButton(strokeTypePopupButton, "attribute.strokeType");
strokeTypePopupButton.setFocusable(false);
strokeTypePopupButton.add(
new AttributeAction(
editor,
STROKE_TYPE,
AttributeKeys.StrokeType.BASIC,
labels.getString("attribute.strokeType.basic"),
new StrokeIcon(new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL))));
HashMap<AttributeKey<?>, Object> attr = new HashMap<>();
attr.put(STROKE_TYPE, AttributeKeys.StrokeType.DOUBLE);
attr.put(STROKE_INNER_WIDTH_FACTOR, 2d);
strokeTypePopupButton.add(
new AttributeAction(
editor,
attr,
labels.getString("attribute.strokeType.double"),
new StrokeIcon(new DoubleStroke(2, 1))));
attr = new HashMap<>();
attr.put(STROKE_TYPE, AttributeKeys.StrokeType.DOUBLE);
attr.put(STROKE_INNER_WIDTH_FACTOR, 3d);
strokeTypePopupButton.add(
new AttributeAction(
editor,
attr,
labels.getString("attribute.strokeType.double"),
new StrokeIcon(new DoubleStroke(3, 1))));
attr = new HashMap<>();
attr.put(STROKE_TYPE, AttributeKeys.StrokeType.DOUBLE);
attr.put(STROKE_INNER_WIDTH_FACTOR, 4d);
strokeTypePopupButton.add(
new AttributeAction(
editor,
attr,
labels.getString("attribute.strokeType.double"),
new StrokeIcon(new DoubleStroke(4, 1))));
return strokeTypePopupButton;
}
public static JPopupButton createStrokePlacementButton(DrawingEditor editor) {
ResourceBundleUtil labels = ResourceBundleUtil.getBundle("org.jhotdraw.draw.Labels");
JPopupButton strokePlacementPopupButton = new JPopupButton();
labels.configureToolBarButton(strokePlacementPopupButton, "attribute.strokePlacement");
strokePlacementPopupButton.setFocusable(false);
HashMap<AttributeKey<?>, Object> attr;
attr = new HashMap<>();
attr.put(STROKE_PLACEMENT, AttributeKeys.StrokePlacement.CENTER);
attr.put(FILL_UNDER_STROKE, AttributeKeys.Underfill.CENTER);
strokePlacementPopupButton.add(
new AttributeAction(
editor,
attr,
labels.getString("attribute.strokePlacement.center"),
null));
attr = new HashMap<>();
attr.put(STROKE_PLACEMENT, AttributeKeys.StrokePlacement.INSIDE);
attr.put(FILL_UNDER_STROKE, AttributeKeys.Underfill.CENTER);
strokePlacementPopupButton.add(
new AttributeAction(
editor,
attr,
labels.getString("attribute.strokePlacement.inside"),
null));
attr = new HashMap<>();
attr.put(STROKE_PLACEMENT, AttributeKeys.StrokePlacement.OUTSIDE);
attr.put(FILL_UNDER_STROKE, AttributeKeys.Underfill.CENTER);
strokePlacementPopupButton.add(
new AttributeAction(
editor,
attr,
labels.getString("attribute.strokePlacement.outside"),
null));
attr = new HashMap<>();
attr.put(STROKE_PLACEMENT, AttributeKeys.StrokePlacement.CENTER);
attr.put(FILL_UNDER_STROKE, AttributeKeys.Underfill.FULL);
strokePlacementPopupButton.add(
new AttributeAction(
editor,
attr,
labels.getString("attribute.strokePlacement.centerFilled"),
null));
attr = new HashMap<>();
attr.put(STROKE_PLACEMENT, AttributeKeys.StrokePlacement.INSIDE);
attr.put(FILL_UNDER_STROKE, AttributeKeys.Underfill.FULL);
strokePlacementPopupButton.add(
new AttributeAction(
editor,
attr,
labels.getString("attribute.strokePlacement.insideFilled"),
null));
attr = new HashMap<>();
attr.put(STROKE_PLACEMENT, AttributeKeys.StrokePlacement.OUTSIDE);
attr.put(FILL_UNDER_STROKE, AttributeKeys.Underfill.FULL);
strokePlacementPopupButton.add(
new AttributeAction(
editor,
attr,
labels.getString("attribute.strokePlacement.outsideFilled"),
null));
attr = new HashMap<>();
attr.put(STROKE_PLACEMENT, AttributeKeys.StrokePlacement.CENTER);
attr.put(FILL_UNDER_STROKE, AttributeKeys.Underfill.NONE);
strokePlacementPopupButton.add(
new AttributeAction(
editor,
attr,
labels.getString("attribute.strokePlacement.centerUnfilled"),
null));
attr = new HashMap<>();
attr.put(STROKE_PLACEMENT, AttributeKeys.StrokePlacement.INSIDE);
attr.put(FILL_UNDER_STROKE, AttributeKeys.Underfill.NONE);
strokePlacementPopupButton.add(
new AttributeAction(
editor,
attr,
labels.getString("attribute.strokePlacement.insideUnfilled"),
null));
attr = new HashMap<>();
attr.put(STROKE_PLACEMENT, AttributeKeys.StrokePlacement.OUTSIDE);
attr.put(FILL_UNDER_STROKE, AttributeKeys.Underfill.NONE);
strokePlacementPopupButton.add(
new AttributeAction(
editor,
attr,
labels.getString("attribute.strokePlacement.outsideUnfilled"),
null));
return strokePlacementPopupButton;
}
public static void addFontButtonsTo(JToolBar bar, DrawingEditor editor) {
bar.add(createFontButton(editor));
bar.add(createFontStyleBoldButton(editor));
bar.add(createFontStyleItalicButton(editor));
bar.add(createFontStyleUnderlineButton(editor));
}
public static JPopupButton createFontButton(DrawingEditor editor) {
return createFontButton(editor,
ResourceBundleUtil.getBundle("org.jhotdraw.draw.Labels"));
}
public static JPopupButton createFontButton(DrawingEditor editor,
ResourceBundleUtil labels) {
return createFontButton(editor, FONT_FACE, labels);
}
public static JPopupButton createFontButton(DrawingEditor editor,
AttributeKey<Font> key,
ResourceBundleUtil labels) {
return createFontButton(editor, key, labels, new LinkedList<>());
}
public static JPopupButton createFontButton(DrawingEditor editor,
AttributeKey<Font> key,
ResourceBundleUtil labels, java.util.List<Disposable> dsp) {
JPopupButton fontPopupButton;
fontPopupButton = new JPopupButton();
labels.configureToolBarButton(fontPopupButton, "attribute.font");
fontPopupButton.setFocusable(false);
JComponentPopup popupMenu = new JComponentPopup();
JFontChooser fontChooser = new JFontChooser();
dsp.add(new FontChooserHandler(editor, key, fontChooser, popupMenu));
popupMenu.add(fontChooser);
fontPopupButton.setPopupMenu(popupMenu);
fontPopupButton.setFocusable(false);
return fontPopupButton;
}
public static JButton createFontStyleBoldButton(DrawingEditor editor) {
return createFontStyleBoldButton(editor,
ResourceBundleUtil.getBundle("org.jhotdraw.draw.Labels"));
}
public static JButton createFontStyleBoldButton(DrawingEditor editor,
ResourceBundleUtil labels) {
return createFontStyleBoldButton(editor,
labels, new LinkedList<>());
}
public static JButton createFontStyleBoldButton(DrawingEditor editor,
ResourceBundleUtil labels, java.util.List<Disposable> dsp) {
JButton btn;
btn = new JButton();
labels.configureToolBarButton(btn, "attribute.fontStyle.bold");
btn.setFocusable(false);
AbstractAction a = new AttributeToggler<>(editor,
FONT_BOLD, Boolean.TRUE, Boolean.FALSE,
new StyledEditorKit.BoldAction());
a.putValue(ActionUtil.UNDO_PRESENTATION_NAME_KEY, labels.getString("attribute.fontStyle.bold.text"));
btn.addActionListener(a);
return btn;
}
public static JButton createFontStyleItalicButton(DrawingEditor editor) {
return createFontStyleItalicButton(editor,
ResourceBundleUtil.getBundle("org.jhotdraw.draw.Labels"));
}
public static JButton createFontStyleItalicButton(DrawingEditor editor,
ResourceBundleUtil labels) {
return createFontStyleItalicButton(editor,
labels, new LinkedList<>());
}
public static JButton createFontStyleItalicButton(DrawingEditor editor,
ResourceBundleUtil labels, java.util.List<Disposable> dsp) {
JButton btn;
btn = new JButton();
labels.configureToolBarButton(btn, "attribute.fontStyle.italic");
btn.setFocusable(false);
AbstractAction a = new AttributeToggler<>(editor,
FONT_ITALIC, Boolean.TRUE, Boolean.FALSE,
new StyledEditorKit.BoldAction());
a.putValue(ActionUtil.UNDO_PRESENTATION_NAME_KEY, labels.getString("attribute.fontStyle.italic.text"));
btn.addActionListener(a);
return btn;
}
public static JButton createFontStyleUnderlineButton(DrawingEditor editor) {
return createFontStyleUnderlineButton(editor,
ResourceBundleUtil.getBundle("org.jhotdraw.draw.Labels"));
}
public static JButton createFontStyleUnderlineButton(DrawingEditor editor,
ResourceBundleUtil labels) {
return createFontStyleUnderlineButton(editor,
labels, new LinkedList<>());
}
public static JButton createFontStyleUnderlineButton(DrawingEditor editor,
ResourceBundleUtil labels, java.util.List<Disposable> dsp) {
JButton btn;
btn = new JButton();
labels.configureToolBarButton(btn, "attribute.fontStyle.underline");
btn.setFocusable(false);
AbstractAction a = new AttributeToggler<>(editor,
FONT_UNDERLINE, Boolean.TRUE, Boolean.FALSE,
new StyledEditorKit.BoldAction());
a.putValue(ActionUtil.UNDO_PRESENTATION_NAME_KEY, labels.getString("attribute.fontStyle.underline.text"));
btn.addActionListener(a);
return btn;
}
/**
* Creates toolbar buttons and adds them to the specified JToolBar
*/
public static void addAlignmentButtonsTo(JToolBar bar, final DrawingEditor editor) {
addAlignmentButtonsTo(bar, editor, new LinkedList<>());
}
/**
* Creates toolbar buttons and adds them to the specified JToolBar.
*/
public static void addAlignmentButtonsTo(JToolBar bar, final DrawingEditor editor, java.util.List<Disposable> dsp) {
AbstractSelectedAction d;
bar.add(d = new AlignAction.West(editor)).setFocusable(false);
dsp.add(d);
bar.add(d = new AlignAction.East(editor)).setFocusable(false);
dsp.add(d);
bar.add(d = new AlignAction.Horizontal(editor)).setFocusable(false);
dsp.add(d);
bar.add(d = new AlignAction.North(editor)).setFocusable(false);
dsp.add(d);
bar.add(d = new AlignAction.South(editor)).setFocusable(false);
dsp.add(d);
bar.add(d = new AlignAction.Vertical(editor)).setFocusable(false);
dsp.add(d);
bar.addSeparator();
bar.add(d = new MoveAction.West(editor)).setFocusable(false);
dsp.add(d);
bar.add(d = new MoveAction.East(editor)).setFocusable(false);
dsp.add(d);
bar.add(d = new MoveAction.North(editor)).setFocusable(false);
dsp.add(d);
bar.add(d = new MoveAction.South(editor)).setFocusable(false);
dsp.add(d);
bar.addSeparator();
bar.add(new BringToFrontAction(editor)).setFocusable(false);
dsp.add(d);
bar.add(new SendToBackAction(editor)).setFocusable(false);
dsp.add(d);
}
/**
* Creates a button which toggles between two GridConstrainer for a
* DrawingView.
*/
public static AbstractButton createToggleGridButton(final DrawingView view) {
ResourceBundleUtil labels = ResourceBundleUtil.getBundle("org.jhotdraw.draw.Labels");
final JToggleButton toggleButton;
toggleButton = new JToggleButton();
labels.configureToolBarButton(toggleButton, "view.toggleGrid");
toggleButton.setFocusable(false);
toggleButton.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent event) {
view.setConstrainerVisible(toggleButton.isSelected());
//view.getComponent().repaint();
}
});
view.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
// String constants are interned
if (evt.getPropertyName() == DrawingView.CONSTRAINER_VISIBLE_PROPERTY) {
toggleButton.setSelected(view.isConstrainerVisible());
}
}
});
return toggleButton;
}
public static JPopupButton createStrokeCapButton(DrawingEditor editor) {
return createStrokeCapButton(editor,
ResourceBundleUtil.getBundle("org.jhotdraw.draw.Labels"));
}
public static JPopupButton createStrokeCapButton(DrawingEditor editor,
ResourceBundleUtil labels) {
return createStrokeCapButton(editor,
labels, new LinkedList<>());
}
public static JPopupButton createStrokeCapButton(DrawingEditor editor,
ResourceBundleUtil labels, java.util.List<Disposable> dsp) {
JPopupButton popupButton = new JPopupButton();
labels.configureToolBarButton(popupButton, "attribute.strokeCap");
popupButton.setFocusable(false);
HashMap<AttributeKey<?>, Object> attr;
attr = new HashMap<>();
attr.put(STROKE_CAP, BasicStroke.CAP_BUTT);
AttributeAction a;
popupButton.add(
a = new AttributeAction(
editor,
attr,
labels.getString("attribute.strokeCap.butt"),
null));
dsp.add(a);
attr = new HashMap<>();
attr.put(STROKE_CAP, BasicStroke.CAP_ROUND);
popupButton.add(
a = new AttributeAction(
editor,
attr,
labels.getString("attribute.strokeCap.round"),
null));
dsp.add(a);
attr = new HashMap<>();
attr.put(STROKE_CAP, BasicStroke.CAP_SQUARE);
popupButton.add(
a = new AttributeAction(
editor,
attr,
labels.getString("attribute.strokeCap.square"),
null));
dsp.add(a);
return popupButton;
}
public static JPopupButton createStrokeJoinButton(DrawingEditor editor) {
return createStrokeJoinButton(editor,
ResourceBundleUtil.getBundle("org.jhotdraw.draw.Labels"));
}
public static JPopupButton createStrokeJoinButton(DrawingEditor editor,
ResourceBundleUtil labels) {
return createStrokeJoinButton(editor,
labels, new LinkedList<>());
}
public static JPopupButton createStrokeJoinButton(DrawingEditor editor,
ResourceBundleUtil labels, java.util.List<Disposable> dsp) {
JPopupButton popupButton = new JPopupButton();
labels.configureToolBarButton(popupButton, "attribute.strokeJoin");
popupButton.setFocusable(false);
HashMap<AttributeKey<?>, Object> attr;
attr = new HashMap<>();
attr.put(STROKE_JOIN, BasicStroke.JOIN_BEVEL);
AttributeAction a;
popupButton.add(
a = new AttributeAction(
editor,
attr,
labels.getString("attribute.strokeJoin.bevel"),
null));
dsp.add(a);
attr = new HashMap<>();
attr.put(STROKE_JOIN, BasicStroke.JOIN_ROUND);
popupButton.add(
a = new AttributeAction(
editor,
attr,
labels.getString("attribute.strokeJoin.round"),
null));
dsp.add(a);
attr = new HashMap<>();
attr.put(STROKE_JOIN, BasicStroke.JOIN_MITER);
popupButton.add(
a = new AttributeAction(
editor,
attr,
labels.getString("attribute.strokeJoin.miter"),
null));
dsp.add(a);
return popupButton;
}
public static JButton createPickAttributesButton(DrawingEditor editor) {
return createPickAttributesButton(editor, new LinkedList<>());
}
public static JButton createPickAttributesButton(DrawingEditor editor, java.util.List<Disposable> dsp) {
JButton btn;
AbstractSelectedAction d;
btn = new JButton(d = new PickAttributesAction(editor));
dsp.add(d);
if (btn.getIcon() != null) {
btn.putClientProperty("hideActionText", Boolean.TRUE);
}
btn.setHorizontalTextPosition(JButton.CENTER);
btn.setVerticalTextPosition(JButton.BOTTOM);
btn.setText(null);
btn.setFocusable(false);
return btn;
}
/**
* Creates a button that applies the default attributes of the editor to the
* current selection.
*/
public static JButton createApplyAttributesButton(DrawingEditor editor) {
return createApplyAttributesButton(editor, new LinkedList<>());
}
public static JButton createApplyAttributesButton(DrawingEditor editor, java.util.List<Disposable> dsp) {
JButton btn;
AbstractSelectedAction d;
btn = new JButton(d = new ApplyAttributesAction(editor));
dsp.add(d);
if (btn.getIcon() != null) {
btn.putClientProperty("hideActionText", Boolean.TRUE);
}
btn.setHorizontalTextPosition(JButton.CENTER);
btn.setVerticalTextPosition(JButton.BOTTOM);
btn.setText(null);
btn.setFocusable(false);
return btn;
}
}