package edu.princeton.toy.choosers; import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.border.*; import javax.swing.event.*; import edu.princeton.swing.*; import edu.princeton.swing.text.*; /** * TStyleChooserPane manages a set of styles for various indices and allows the user to change the * colors for those indices. * * @author btsang * @version 7.1 */ public class TStyleChooserPane extends JPanel implements ActionListener, ListSelectionListener { private static final String CLASS_STRING = TStyleChooserPane.class.toString(); /** * The command that causes the TStyleChooserPane to update its components with the internal * data. */ public static final String UPDATE_COMMAND = CLASS_STRING + "#updateCommand"; /** * The command that causes the TStyleChooserPane to open a color chooser dialog. */ public static final String CHANGE_COMMAND = CLASS_STRING + "#changeCommand"; private static final Border BLACK_BORDER = LineBorder.createBlackLineBorder(); private static final Border ETCHED_BORDER = new EtchedBorder(); private PList styleList; private JLabel previewLabel; private JPanel previewPanel; private JButton changeButton; private JCheckBox boldCheckbox; private JCheckBox italicCheckbox; private HighlightStyle styles[]; private Color colors[]; private boolean bold[]; private boolean italic[]; private String styleNames[]; /** * Creates a new TStyleChooserPane. */ public TStyleChooserPane(String styleNames[]) { super(new GridBagLayout()); int length = styleNames.length; this.styleNames = new String[length]; this.styles = new HighlightStyle[length]; this.colors = new Color[length]; this.bold = new boolean[length]; this.italic = new boolean[length]; for (int ctr = 0; ctr < length; ctr++) { this.styleNames[ctr] = styleNames[ctr]; } { // Prepare the inner panel JPanel innerPanel = new JPanel(new GridBagLayout()); innerPanel.setBorder(ETCHED_BORDER); { // Prepare the style list styleList = new PList(this.styleNames); styleList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); styleList.setSelectedIndex(0); styleList.addListSelectionListener(this); JScrollPane scrollPane = new JScrollPane( styleList, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED ); Dimension preferredSize = scrollPane.getPreferredSize(); preferredSize.width = 150; scrollPane.setPreferredSize(preferredSize); innerPanel.add( scrollPane, new GridBagConstraints( 0, 0, 1, 5, 0.0, 2.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(2, 2, 2, 2), 0, 0 ) ); } { // Prepare the preview label previewLabel = new JLabel("Current color"); innerPanel.add( previewLabel, new GridBagConstraints( 1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0 ) ); } { // Prepare the preview panel previewPanel = new JPanel(); previewPanel.setPreferredSize(new Dimension(100, 100)); previewPanel.setBorder(BLACK_BORDER); innerPanel.add( previewPanel, new GridBagConstraints( 1, 1, 1, 1, 1.0, 1.0, GridBagConstraints.SOUTH, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0 ) ); } { // Prepare the change button changeButton = new JButton("Change..."); changeButton.setActionCommand(CHANGE_COMMAND); changeButton.addActionListener(this); innerPanel.add( changeButton, new GridBagConstraints( 1, 2, 1, 1, 1.0, 1.0, GridBagConstraints.NORTH, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0 ) ); } { // Prepare the bold checkbox boldCheckbox = new JCheckBox("Bold"); boldCheckbox.setActionCommand(UPDATE_COMMAND); boldCheckbox.addActionListener(this); innerPanel.add( boldCheckbox, new GridBagConstraints( 1, 3, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0 ) ); } { // Prepare the italic checkbox italicCheckbox = new JCheckBox("Italic"); italicCheckbox.setActionCommand(UPDATE_COMMAND); italicCheckbox.addActionListener(this); innerPanel.add( italicCheckbox, new GridBagConstraints( 1, 4, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0 ) ); } add( innerPanel, new GridBagConstraints( 0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(50, 25, 50, 25), 0, 0 ) ); } doCommand(UPDATE_COMMAND, null); } /** * Gets the style for a given index. * * @param index The index of the requested style. An invalid value will result in an * ArrayIndexOutOfBoundsException. * @return The style for that index. */ public HighlightStyle getStyle(int index) { if (styles[index] == null) styles[index] = new HighlightStyle(colors[index], bold[index], italic[index]); return styles[index]; } /** * Sets the style for a given index. * * @param style The new style for the given index. A null value will result in a * NullPointerException. * @param index The index of the style we're setting. An invalid value will result in an * ArrayIndexOutOfBoundsException. */ public void setStyle(HighlightStyle style, int index) { if (style == null) throw new NullPointerException(); styles[index] = style; colors[index] = style.getColor(); bold[index] = style.isBold(); italic[index] = style.isItalic(); if (styleList.getSelectedIndex() == index) { doCommand(UPDATE_COMMAND, null); } } /** * Performs a command based on the argument. * * @param command A string representing the command. Note that pointer equality (not string * equality) is tested here, so it is important to use the string constants defined in this * class. An IllegalArgumentException will be thrown if the argument is invalid. * @return True iff the command was executed sucessfully. */ public synchronized boolean doCommand(String command, Object extraInfo) { //////////////////////////////////////////////////////////////////////////////////////////// if (command == UPDATE_COMMAND) { int index = styleList.getSelectedIndex(); if (index == -1) { index = 0; styleList.setSelectedIndex(0); } previewPanel.setBackground(colors[index]); boldCheckbox.getModel().setSelected(bold[index]); italicCheckbox.getModel().setSelected(italic[index]); return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == CHANGE_COMMAND) { int index = styleList.getSelectedIndex(); if (index == -1) { index = 0; styleList.setSelectedIndex(0); } Component comp = this; while (comp != null && !(comp instanceof Window)) comp = comp.getParent(); Color selection = JColorChooser.showDialog( comp, "Color selection for " + styleNames[index], colors[index] ); if (selection != null && !colors[index].equals(selection)) { colors[index] = selection; styles[index] = null; } doCommand(UPDATE_COMMAND, null); return true; } throw new IllegalArgumentException(); } /** * Implement ActionListener to pay attention to changes in the boldCheckbox and * changeButton. */ public void actionPerformed(ActionEvent e) { int index = styleList.getSelectedIndex(); if (index != -1) { if (bold[index] != boldCheckbox.getModel().isSelected()) { bold[index] = !bold[index]; styles[index] = null; } if (italic[index] != italicCheckbox.getModel().isSelected()) { italic[index] = !italic[index]; styles[index] = null; } } doCommand(e.getActionCommand(), null); } /** * Implement ListSelectionListener to pay attention to changes in the styleList. */ public void valueChanged(ListSelectionEvent e) { doCommand(UPDATE_COMMAND, null); } }