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 }