/*
* Copyright 2003-2010 Tufts University Licensed under the
* Educational Community License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.osedu.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an "AS IS"
* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package tufts.vue;
import tufts.vue.gui.*;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.geom.RectangularShape;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.AbstractButton;
import javax.swing.JLabel;
import javax.swing.Icon;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JList;
import javax.swing.JSeparator;
import javax.swing.ListCellRenderer;
import javax.swing.SwingConstants;
import javax.swing.border.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import edu.tufts.vue.preferences.implementations.ColorPreference;
/**
* This creates an editor panel for LWNode's
*
* @version $Revision: 1.18 $ / $Date: 2010-02-03 19:17:40 $ / $Author: mike $
< */
public class FillToolPanel extends ToolPanel implements ComponentListener
{
/** fill button **/
//protected ColorMenuButton mFillColorButton;
static ColorMenuButton mFillColorButton; // static hack till all the format tool code in once place
/** stroke color editor button **/
protected ColorMenuButton mStrokeColorButton;
private final Color [] fillColors = VueResources.getColorArray("fillColorValues");
// private final String [] fillColorNames = VueResources.getStringArray("fillColorNames");
private final Color[] strokeColors = VueResources.getColorArray("strokeColorValues");
private final String[] strokeColorNames = VueResources.getStringArray("strokeColorNames");
private final JLabel fillLabel = new JLabel(VueResources.getString("filltoolpanel.fill"));
private final JLabel lineLabel = new JLabel(VueResources.getString("filltoolpanel.line"));
private final ColorPreference fillPrefColor = ColorPreference.create(
edu.tufts.vue.preferences.PreferenceConstants.FORMATTING_CATEGORY,
"fillColor",
"Fill Color",
"Remember Fill Color?",
VueResources.getColor("defaultFillColor"),
false);
private final ColorPreference strokePrefColor = ColorPreference.create(
edu.tufts.vue.preferences.PreferenceConstants.FORMATTING_CATEGORY,
"strokeColor",
"Stroke Color",
"Remember Stroke Color?",
VueResources.getColor("defaultStrokeColor"),
false);
public FillToolPanel() {
//setBorder(BorderFactory.createLineBorder(Color.red));
}
public void buildBox()
{
//-------------------------------------------------------
// Fill Color menu
//-------------------------------------------------------
//TODO: need to come back here and move these tooltips into properties. -mikek
mFillColorButton = new ColorMenuButton(fillColors, true);
mFillColorButton.setPropertyKey(LWKey.FillColor);
//tufts.Util.printStackTrace("LOADING FILL COLOR BUTTON WITH " + tufts.Util.tags(fillPrefColor.getValue()));
mFillColorButton.setColor((Color)fillPrefColor.getValue());
mFillColorButton.setToolTipText("Fill Color");
//mFillColorButton.addPropertyChangeListener(this); // always last or we get prop change events for setup
mFillColorButton.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent e) {
if (e instanceof LWPropertyChangeEvent)
fillPrefColor.setValue(mFillColorButton.getColor());
}
});
//-------------------------------------------------------
// Stroke Color menu
//-------------------------------------------------------
mStrokeColorButton = new ColorMenuButton(strokeColors, true);
mStrokeColorButton.setPropertyKey(LWKey.StrokeColor);
mStrokeColorButton.setColor((Color)strokePrefColor.getValue());
//mStrokeColorButton.setButtonIcon(new LineIcon(16,16, 4, false));
mStrokeColorButton.setToolTipText("Stroke Color");
//mStrokeColorButton.addPropertyChangeListener(this);
mStrokeColorButton.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent e) {
if (e instanceof LWPropertyChangeEvent)
strokePrefColor.setValue(mStrokeColorButton.getColor());
}
});
lineLabel.addMouseListener(new MouseAdapter() {
// double-click on stroke color label swaps in with fill color
public void mouseClicked(java.awt.event.MouseEvent e) {
if (e.getClickCount() > 1 && e.getClickCount() % 2 == 0) {
final Color fill = mFillColorButton.getColor();
final Color stroke = mStrokeColorButton.getColor();
mFillColorButton.selectValue(stroke);
mStrokeColorButton.selectValue(fill);
}
}
});
fillLabel.setLabelFor(mFillColorButton);
fillLabel.setForeground(new Color(51,51,51));
fillLabel.setFont(tufts.vue.VueConstants.SmallFont);
lineLabel.setLabelFor(mStrokeColorButton);
lineLabel.setForeground(new Color(51,51,51));
lineLabel.setFont(tufts.vue.VueConstants.SmallFont);
if (tufts.Util.isMacPlatform())
buildBoxMac();
else
buildBoxWin();
VUE.getFormatDock().addComponentListener(this);
}
public void buildBoxWin()
{
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(6,3,0,0);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridwidth = 1;
//gbc.gridheight=1;
gbc.fill = GridBagConstraints.VERTICAL; // the label never grows
gbc.anchor = GridBagConstraints.EAST;
getBox().add(fillLabel,gbc);
gbc.gridx = 0;
gbc.gridy = 1;
gbc.gridwidth = 1; // next-to-last in row
// gbc.gridheight=1;
gbc.insets = new Insets(0,3,6,0);
gbc.fill = GridBagConstraints.VERTICAL; // the label never grows
gbc.anchor = GridBagConstraints.EAST;
getBox().add(lineLabel,gbc);
gbc.gridx = 1;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.VERTICAL; // the label never grows
gbc.insets = new Insets(5,0,0,0);
gbc.anchor = GridBagConstraints.WEST;
getBox().add(mFillColorButton, gbc);
gbc.gridx = 1;
gbc.gridy = 1;
gbc.fill = GridBagConstraints.NONE; // the label never grows
gbc.insets = new Insets(0,0,5,0);
gbc.anchor = GridBagConstraints.WEST;
getBox().add(mStrokeColorButton, gbc);
}
public void buildBoxMac()
{
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(3,3,5,3);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.gridwidth = 1;
gbc.gridheight=1;
gbc.fill = GridBagConstraints.VERTICAL; // the label never grows
gbc.anchor = GridBagConstraints.NORTHEAST;
getBox().add(fillLabel,gbc);
gbc.gridx = 0;
gbc.gridy = 1;
gbc.gridwidth = 1; // next-to-last in row
gbc.gridheight=1;
gbc.insets = new Insets(8,3,1,3);
gbc.fill = GridBagConstraints.VERTICAL; // the label never grows
gbc.anchor = GridBagConstraints.NORTHEAST;
getBox().add(lineLabel,gbc);
gbc.gridx = 1;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.NONE; // the label never grows
gbc.insets = new Insets(1,2,4,3);
gbc.anchor = GridBagConstraints.SOUTHWEST;
getBox().add(mFillColorButton, gbc);
gbc.gridx = 1;
gbc.gridy = 1;
gbc.fill = GridBagConstraints.NONE; // the label never grows
gbc.insets = new Insets(4,2,1,3);
gbc.anchor = GridBagConstraints.SOUTHWEST;
getBox().add(mStrokeColorButton, gbc);
}
public boolean isPreferredType(Object o) {
return o instanceof LWNode;
}
/*
static class ShapeMenuButton extends VueComboMenu<RectangularShape>
{
public ShapeMenuButton() {
super(LWKey.Shape, NodeTool.getTool().getShapeSetterActions());
setToolTipText("Node Shape");
ComboBoxRenderer renderer= new ComboBoxRenderer();
setRenderer(renderer);
this.setMaximumRowCount(10);
//setEnabled(false);
}
protected Dimension getButtonSize() {
return new Dimension(37,22);
}
/** @param o an instance of RectangularShape *
public void displayValue(RectangularShape shape) {
if (DEBUG.TOOL) System.out.println(this + " displayValue " + shape.getClass() + " [" + shape + "]");
if (mCurrentValue == null || !mCurrentValue.getClass().equals(shape.getClass())) {
mCurrentValue = shape;
// This is inefficent in that we there are already shape icons out there (produced
// in getShapeSetterActions()) that we could use, but doing it this way (creating a
// new one every time) will allow for ANY rectangular shape to display properly in
// the tool menu, even it is a deprecated shape or non-standard shape (not defined
// as a standard from for the node tool in VueResources.properties). (This is
// especially in-effecient if you look at what setButtonIcon does in MenuButton: it
// creates first a proxy icon, and then creates and installs a whole set of
// VueButtonIcons for all the various states the button can take, for a totale of 7
// objects every time we do this (1 for the clone, 1 for proxy, 5 via
// VueButtonIcon.installGenerated)
//setButtonIcon(makeIcon(shape));
}
}
class ComboBoxRenderer extends JLabel implements ListCellRenderer {
public ComboBoxRenderer() {
setOpaque(true);
setHorizontalAlignment(CENTER);
setVerticalAlignment(CENTER);
}
public Component getListCellRendererComponent(
JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus) {
if (isSelected) {
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
} else {
setBackground(Color.white);
setForeground(list.getForeground());
}
//Set the icon and text. If icon was null, say so.
Action a = (Action) value;
Icon icon = (Icon) a.getValue(Action.SMALL_ICON);
value = a.getValue(ValueKey);
if (icon == null)
icon = makeIcon(value);
if (icon != null)
setIcon(new MenuProxyIcon(icon));
// System.out.println("ICON SIZE NODE " + icon.getIconHeight() + " " + icon.getIconWidth());
this.setBorder(BorderFactory.createEmptyBorder(3,3,3,3));
return this;
}
/** @return new icon for the given shape */
protected Icon makeIcon(Object value) {
RectangularShape shape = (RectangularShape) value;
return new NodeTool.SubTool.ShapeIcon((RectangularShape) shape.clone());
}
/* @return new icon for the given shape *
// protected Icon makeIcon(RectangularShape shape) {
// return new NodeTool.SubTool.ShapeIcon((RectangularShape) shape.clone());
// }
}
}
*/
/*
static class LinkMenuButton extends VueComboMenu<Object>
{
public LinkMenuButton() {
super(LWKey.LinkCurves, LinkTool.getTool().getSetterActions());
setToolTipText("Node Shape");
ComboBoxRenderer renderer= new ComboBoxRenderer();
setRenderer(renderer);
this.setMaximumRowCount(10);
//setEnabled(false);
}
protected Dimension getButtonSize() {
return new Dimension(37,22);
}
public void displayValue(Object linkShape) {
// if (DEBUG.TOOL) System.out.println(this + " displayValue " + shape.getClass() + " [" + shape + "]");
//if (mCurrentValue == null || !mCurrentValue.getClass().equals(shape.getClass())) {
// mCurrentValue = shape;
// This is inefficent in that we there are already shape icons out there (produced
// in getShapeSetterActions()) that we could use, but doing it this way (creating a
// new one every time) will allow for ANY rectangular shape to display properly in
// the tool menu, even it is a deprecated shape or non-standard shape (not defined
// as a standard from for the node tool in VueResources.properties). (This is
// especially in-effecient if you look at what setButtonIcon does in MenuButton: it
// creates first a proxy icon, and then creates and installs a whole set of
// VueButtonIcons for all the various states the button can take, for a totale of 7
// objects every time we do this (1 for the clone, 1 for proxy, 5 via
// VueButtonIcon.installGenerated)
//setButtonIcon(makeIcon(shape));
}
class ComboBoxRenderer extends JLabel implements ListCellRenderer {
public ComboBoxRenderer() {
setOpaque(true);
setHorizontalAlignment(CENTER);
setVerticalAlignment(CENTER);
}
public Component getListCellRendererComponent(
JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus) {
if (isSelected) {
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
} else {
setBackground(Color.white);
setForeground(list.getForeground());
}
//Set the icon and text. If icon was null, say so.
Action a = (Action)value;
Icon icon = (Icon)a.getValue(Action.SMALL_ICON);
// System.out.println("ICON SIZE LINK " + icon.getIconHeight() + " " + icon.getIconWidth());
// if (icon != null)
//setIcon(new MenuProxyIcon(icon));
this.setBorder(BorderFactory.createEmptyBorder(2,2,2,2));
setIcon(icon);
return this;
}
}
}
*/
public static void main(String[] args) {
System.out.println("NodeToolPanel:main");
VUE.init(args);
LWCToolPanel.debug = true;
VueUtil.displayComponent(new NodeToolPanel());
}
public void componentHidden(ComponentEvent arg0) {
// TODO Auto-generated method stub
}
public void componentMoved(ComponentEvent arg0) {
if ((mFillColorButton != null) && (mFillColorButton.getPopupWindow().isVisible()))
mFillColorButton.getPopupWindow().setVisible(false);
if ((mStrokeColorButton != null) && (mStrokeColorButton.getPopupWindow().isVisible()))
mStrokeColorButton.getPopupWindow().setVisible(false);
}
public void componentResized(ComponentEvent arg0) {
// TODO Auto-generated method stub
}
public void componentShown(ComponentEvent arg0) {
// TODO Auto-generated method stub
}
}