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    }