001    /**
002     * Copyright (c) 2008-2009, Piet Blok
003     * All rights reserved.
004     *
005     * Redistribution and use in source and binary forms, with or without
006     * modification, are permitted provided that the following conditions
007     * are met:
008     *
009     *   * Redistributions of source code must retain the above copyright
010     *     notice, this list of conditions and the following disclaimer.
011     *   * Redistributions in binary form must reproduce the above
012     *     copyright notice, this list of conditions and the following
013     *     disclaimer in the documentation and/or other materials provided
014     *     with the distribution.
015     *   * Neither the name of the copyright holder nor the names of the
016     *     contributors may be used to endorse or promote products derived
017     *     from this software without specific prior written permission.
018     *
019     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
020     * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
021     * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
022     * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
023     * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
024     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
025     * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
026     * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
027     * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
028     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
029     * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
030     */
031    
032    package org.pbjar.jxlayer.demo;
033    
034    import java.awt.BorderLayout;
035    import java.awt.GridLayout;
036    import java.awt.event.ActionEvent;
037    import java.beans.PropertyChangeEvent;
038    import java.beans.PropertyChangeListener;
039    import java.text.NumberFormat;
040    
041    import javax.swing.AbstractAction;
042    import javax.swing.Action;
043    import javax.swing.JCheckBox;
044    import javax.swing.JPanel;
045    import javax.swing.JToolBar;
046    
047    import org.jdesktop.jxlayer.JXLayer;
048    import org.pbjar.jxlayer.plaf.ext.MouseEventUI;
049    import org.pbjar.jxlayer.plaf.ext.TransformUI;
050    import org.pbjar.jxlayer.plaf.ext.transform.DefaultTransformModel;
051    
052    /**
053     * A component that contains {@link WheelButton}s for the preferred scale and
054     * transformation options.
055     * 
056     * @author Piet Blok
057     */
058    public class TransformWheelButtons extends JPanel {
059    
060        private static final long serialVersionUID = 1L;
061    
062        private static final String tooltip = "<html><body backgroundcolor='white'>"
063                + "<h2>How to use these controls</h2>"
064                + "<p><ul>"
065                + "<li>You can use the mouse wheel<br/>"
066                + "on the whole area of a control<br/>"
067                + "to increase or decrease its value.</li>"
068                + "<li>Pressing on the current value<br/>"
069                + "will reset it to its default value.</li>"
070                + "<li>Pressing on the up arrow will<br/>"
071                + "increase the value.</li>"
072                + "<li>Pressing on the down arrow will<br/>"
073                + "decrease the value.</li>"
074                + "</ul></p>"
075                + "<p align = 'center'><b>You can disable this tool tip by unchecking the<br/>"
076                + " \"Tip\" check box </b></p>" + "</body></html>";
077    
078    
079        private final DefaultTransformModel model;
080    
081        /**
082         * Sole constructor.
083         * 
084         * @param layer
085         *            affected layer
086         * @param clientListener
087         *            an additional listener that will be notified when any change
088         *            occurs on any of the wheels, or {@code null}
089         */
090        public TransformWheelButtons(JXLayer<?> layer,
091                PropertyChangeListener clientListener) {
092            super(new BorderLayout());
093    //      this.port = layer.getView();
094            model = (DefaultTransformModel) ((TransformUI) layer.getUI())
095                    .getModel();
096            layer.addPropertyChangeListener(clientListener);
097            JPanel buttonPanel = new JPanel(new GridLayout(1, 0));
098            createSliders(buttonPanel);
099            final JXLayer<JPanel> buttonLayer = new JXLayer<JPanel>(buttonPanel,
100                    new MouseEventUI<JPanel>());
101            buttonLayer.getGlassPane().setToolTipText(tooltip);
102            this.add(buttonLayer, BorderLayout.CENTER);
103            JToolBar toolBar = new JToolBar();
104            this.add(toolBar, BorderLayout.PAGE_END);
105            createActions(toolBar);
106            for (int index = 0; index < buttonPanel.getComponentCount(); index++) {
107                buttonPanel.getComponent(index).addPropertyChangeListener(
108                        WheelButton.KEY_CURRENT, clientListener);
109            }
110            tipDisplayButton = new JCheckBox(new AbstractAction("Tip") {
111    
112                private static final long serialVersionUID = 1L;
113    
114                {
115                    String tip = buttonLayer.getGlassPane().getToolTipText();
116                    this.putValue(Action.SELECTED_KEY, tip != null
117                            && tip.length() > 0);
118                }
119    
120                @Override
121                public void actionPerformed(ActionEvent e) {
122                    buttonLayer.getGlassPane().setToolTipText(
123                            (Boolean) this.getValue(Action.SELECTED_KEY) ? tooltip
124                                    : "");
125                }
126            });
127        }
128        
129        private final JCheckBox tipDisplayButton;
130    
131        private void createActions(JToolBar toolBar) {
132            final Action preserve = new AbstractAction("Preserve aspect ratio") {
133    
134                private static final long serialVersionUID = 1L;
135    
136                {
137                    this.putValue(Action.SELECTED_KEY, model
138                            .isPreserveAspectRatio());
139                }
140    
141                @Override
142                public void actionPerformed(ActionEvent e) {
143                    model.setPreserveAspectRatio((Boolean) this
144                            .getValue(Action.SELECTED_KEY));
145                }
146            };
147    
148            final Action scalePreferred = new AbstractAction("Scale to preferred") {
149    
150                private static final long serialVersionUID = 1L;
151    
152                {
153                    this.putValue(Action.SELECTED_KEY, model
154                            .isScaleToPreferredSize());
155                    preserve.setEnabled(!(Boolean) this
156                            .getValue(Action.SELECTED_KEY));
157                }
158    
159                @Override
160                public void actionPerformed(ActionEvent e) {
161                    model.setScaleToPreferredSize((Boolean) this
162                            .getValue(Action.SELECTED_KEY));
163                    preserve.setEnabled(!(Boolean) this
164                            .getValue(Action.SELECTED_KEY));
165                }
166            };
167            final Action mirror = new AbstractAction("Mirror") {
168    
169                private static final long serialVersionUID = 1L;
170    
171                {
172                    this.putValue(Action.SELECTED_KEY, model.isMirror());
173                }
174    
175                @Override
176                public void actionPerformed(ActionEvent e) {
177                    model.setMirror((Boolean) this.getValue(Action.SELECTED_KEY));
178                }
179            };
180    
181            for (Action action : new Action[] { preserve, scalePreferred, mirror }) {
182                toolBar.add(new JCheckBox(action));
183            }
184        }
185    
186        private void createSliders(JPanel buttonPanel) {
187            NumberFormat numberFormat = NumberFormat.getNumberInstance();
188            // Scale.
189            buttonPanel.add(new WheelButton("Scale", model.getScale(),
190                    WheelButton.IncrementType.Factor, Math.sqrt(2), numberFormat,
191                    new PropertyChangeListener() {
192    
193                        @Override
194                        public void propertyChange(PropertyChangeEvent evt) {
195                            model.setScale((Double) evt.getNewValue());
196                        }
197                    }));
198            // Radians rotation
199            buttonPanel.add(new WheelButton("Rotate", model.getRotation(),
200                    WheelButton.IncrementType.Fixed, Math.PI / 90, numberFormat,
201                    new PropertyChangeListener() {
202    
203                        @Override
204                        public void propertyChange(PropertyChangeEvent evt) {
205                            model.setRotation((Double) evt.getNewValue());
206                        }
207                    }));
208            // Quadrant rotation
209            buttonPanel.add(new WheelButton("Quadrant",
210                    model.getQuadrantRotation(), WheelButton.IncrementType.Fixed,
211                    1, numberFormat, new PropertyChangeListener() {
212    
213                        @Override
214                        public void propertyChange(PropertyChangeEvent evt) {
215                            model.setQuadrantRotation(((Double) evt.getNewValue())
216                                    .intValue());
217                        }
218                    }));
219            // Shear X
220            buttonPanel.add(new WheelButton("Shear X", model.getShearX(),
221                    WheelButton.IncrementType.Fixed, .02, numberFormat,
222                    new PropertyChangeListener() {
223    
224                        @Override
225                        public void propertyChange(PropertyChangeEvent evt) {
226                            model.setShearX((Double) evt.getNewValue());
227                        }
228                    }));
229            // Shear Y
230            buttonPanel.add(new WheelButton("Shear Y", model.getShearY(),
231                    WheelButton.IncrementType.Fixed, .02, numberFormat,
232                    new PropertyChangeListener() {
233    
234                        @Override
235                        public void propertyChange(PropertyChangeEvent evt) {
236                            model.setShearY((Double) evt.getNewValue());
237                        }
238                    }));
239        }
240    
241        public JCheckBox getTipDisplayButton() {
242            return tipDisplayButton;
243        }
244    
245    }