001 /*
002 * Copyright (c) 2005 Einar Pehrson <einar@pehrson.nu>.
003 *
004 * This file is part of
005 * CleanSheets - a spreadsheet application for the Java platform.
006 *
007 * CleanSheets is free software; you can redistribute it and/or modify
008 * it under the terms of the GNU General Public License as published by
009 * the Free Software Foundation; either version 2 of the License, or
010 * (at your option) any later version.
011 *
012 * CleanSheets is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015 * GNU General Public License for more details.
016 *
017 * You should have received a copy of the GNU General Public License
018 * along with CleanSheets; if not, write to the Free Software
019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020 */
021 package csheets.ext.style.ui;
022
023 import java.awt.BorderLayout;
024 import java.awt.Color;
025 import java.awt.Component;
026 import java.awt.Dimension;
027 import java.awt.GridBagConstraints;
028 import java.awt.GridBagLayout;
029 import java.awt.Insets;
030 import java.awt.event.ActionEvent;
031 import java.awt.event.ItemEvent;
032 import java.awt.event.ItemListener;
033
034 import javax.swing.AbstractAction;
035 import javax.swing.BorderFactory;
036 import javax.swing.BoxLayout;
037 import javax.swing.Icon;
038 import javax.swing.ImageIcon;
039 import javax.swing.JButton;
040 import javax.swing.JColorChooser;
041 import javax.swing.JComponent;
042 import javax.swing.JLabel;
043 import javax.swing.JOptionPane;
044 import javax.swing.JPanel;
045 import javax.swing.JToggleButton;
046 import javax.swing.border.Border;
047 import javax.swing.border.MatteBorder;
048
049 import csheets.ext.style.StyleExtension;
050
051 /**
052 * A component which allows the user to select a border.
053 * @author Einar Pehrson
054 */
055 @SuppressWarnings("serial")
056 public class BorderChooser extends JComponent {
057
058 /** The toggle button for the top border segment */
059 private JToggleButton topButton = new JToggleButton(new ImageIcon(
060 StyleExtension.class.getResource("res/img/border_top.gif")));
061
062 /** The toggle button for the left border segment */
063 private JToggleButton leftButton = new JToggleButton(new ImageIcon(
064 StyleExtension.class.getResource("res/img/border_left.gif")));
065
066 /** The toggle button for the right border segment */
067 private JToggleButton rightButton = new JToggleButton(new ImageIcon(
068 StyleExtension.class.getResource("res/img/border_right.gif")));
069
070 /** The toggle button for the bottom border segment */
071 private JToggleButton bottomButton = new JToggleButton(new ImageIcon(
072 StyleExtension.class.getResource("res/img/border_bottom.gif")));
073
074 /** The preview label */
075 private JLabel previewLabel = new JLabel("");
076
077 /** The currently selected border color */
078 private Color color = Color.black;
079
080 /**
081 * Creates a new border selection panel.
082 */
083 public BorderChooser () {
084 this(null);
085 }
086
087 /**
088 * Creates a new border selection panel with the given initial border
089 * selected.
090 * @param initialBorder the border to select initially
091 */
092 public BorderChooser(Border initialBorder) {
093 // Configures preview label
094 previewLabel.setPreferredSize(new Dimension(100, 80));
095 previewLabel.setBorder(
096 BorderFactory.createCompoundBorder(
097 BorderFactory.createTitledBorder("Preview"),
098 BorderFactory.createEmptyBorder(5, 5, 5, 5)
099 ));
100
101 // Registers listener
102 PreviewLabelUpdater updater = new PreviewLabelUpdater();
103 topButton.addItemListener(updater);
104 leftButton.addItemListener(updater);
105 rightButton.addItemListener(updater);
106 bottomButton.addItemListener(updater);
107
108 // Lays out button panel
109 JPanel buttonPanel = new JPanel(new GridBagLayout());
110 GridBagConstraints gc = new GridBagConstraints();
111 gc.gridwidth = gc.gridheight = 2;
112 gc.gridy = 1;
113 buttonPanel.add(leftButton, gc);
114 gc.gridx = 2;
115 gc.gridy = 0;
116 buttonPanel.add(topButton, gc);
117 gc.gridy = 2;
118 buttonPanel.add(bottomButton, gc);
119 gc.gridx = 4;
120 gc.gridy = 1;
121 buttonPanel.add(rightButton, gc);
122 buttonPanel.setBorder(BorderFactory.createTitledBorder("Border"));
123
124 // Creates color panel
125 JPanel colorPanel = new JPanel();
126 colorPanel.setLayout(new BoxLayout(colorPanel, BoxLayout.X_AXIS));
127 JButton colorButton = new JButton(new ColorAction());
128 colorButton.setAlignmentY(0.5f);
129 colorPanel.add(colorButton);
130 colorPanel.setBorder(BorderFactory.createTitledBorder("Color"));
131
132 // Configures layout and adds components
133 setLayout(new BorderLayout(5, 5));
134 add(buttonPanel, BorderLayout.CENTER);
135 add(colorPanel, BorderLayout.EAST);
136 add(previewLabel, BorderLayout.SOUTH);
137
138 // Sets the initial border
139 setSelectedBorder(initialBorder);
140 }
141
142 /**
143 * Lets the user select a border from a chooser in a standard dialog.
144 * @param parent the parent component of the dialog
145 * @param title the title of the dialog
146 * @param initialBorder the border to select initially
147 * @return the selected border or, if the user did not press OK, null
148 */
149 public static Border showDialog(Component parent, String title,
150 Border initialBorder) {
151 BorderChooser chooser = new BorderChooser(initialBorder);
152 int returnValue = JOptionPane.showConfirmDialog(
153 parent,
154 chooser,
155 title,
156 JOptionPane.OK_CANCEL_OPTION,
157 JOptionPane.PLAIN_MESSAGE,
158 (Icon)null);
159 if (returnValue == JOptionPane.OK_OPTION)
160 return chooser.getSelectedBorder();
161 else
162 return null;
163 }
164
165 /**
166 * Returns the currently selected border in the dialog.
167 * @return the currently selected border
168 */
169 public Border getSelectedBorder() {
170 return BorderFactory.createMatteBorder(
171 topButton.isSelected() ? 1 : 0,
172 leftButton.isSelected() ? 1 : 0,
173 bottomButton.isSelected() ? 1 : 0,
174 rightButton.isSelected() ? 1 : 0,
175 color);
176 }
177
178 /**
179 * Sets the currently selected border in the dialog.
180 * @param border the border to select
181 */
182 public void setSelectedBorder(Border border) {
183 if (border instanceof MatteBorder) {
184 MatteBorder matteBorder = (MatteBorder)border;
185 color = matteBorder.getMatteColor();
186 Insets insets = matteBorder.getBorderInsets();
187 topButton.setSelected(insets.top > 0);
188 leftButton.setSelected(insets.left > 0);
189 bottomButton.setSelected(insets.bottom > 0);
190 rightButton.setSelected(insets.right > 0);
191 }
192 }
193
194 /**
195 * Updates the border of the preview label.
196 */
197 private void updatePreviewBorder() {
198 previewLabel.setBorder(
199 BorderFactory.createCompoundBorder(
200 BorderFactory.createTitledBorder("Preview"),
201 BorderFactory.createCompoundBorder(
202 BorderFactory.createEmptyBorder(5, 5, 5, 5),
203 getSelectedBorder())));
204 }
205
206 /**
207 * A controller that listens to selection events on the buttons.
208 */
209 private class PreviewLabelUpdater implements ItemListener {
210
211 /**
212 * Creates a new preview label updater.
213 */
214 public PreviewLabelUpdater() {}
215
216 /**
217 * Updates the preview label.
218 * @param e the event that was fired
219 */
220 public void itemStateChanged(ItemEvent e) {
221 updatePreviewBorder();
222 }
223 }
224
225 /**
226 * An action for letting the user select a new border color from a chooser.
227 */
228 private class ColorAction extends AbstractAction {
229
230 public ColorAction() {
231 putValue(SMALL_ICON, new ImageIcon(
232 StyleExtension.class.getResource("res/img/color_bg.gif")));
233 }
234
235 public void actionPerformed(ActionEvent e) {
236 Color c = JColorChooser.showDialog(null, "Choose Border Color",
237 color);
238 if (c != null) {
239 color = c;
240 updatePreviewBorder();
241 }
242 }
243 }
244 }