2
* Copyright (c) 2005-2010 Flamingo Kirill Grouchnikov. All Rights Reserved.
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions are met:
7
* o Redistributions of source code must retain the above copyright notice,
8
* this list of conditions and the following disclaimer.
10
* o Redistributions in binary form must reproduce the above copyright notice,
11
* this list of conditions and the following disclaimer in the documentation
12
* and/or other materials provided with the distribution.
14
* o Neither the name of Flamingo Kirill Grouchnikov nor the names of
15
* its contributors may be used to endorse or promote products derived
16
* from this software without specific prior written permission.
18
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
package org.pushingpixels.flamingo.internal.ui.common;
33
import java.beans.PropertyChangeEvent;
35
import javax.swing.JSeparator;
36
import javax.swing.SwingConstants;
38
import org.pushingpixels.flamingo.api.common.*;
39
import org.pushingpixels.flamingo.api.common.JCommandButton.CommandButtonKind;
40
import org.pushingpixels.flamingo.api.common.icon.ResizableIcon;
41
import org.pushingpixels.flamingo.internal.utils.FlamingoUtilities;
43
public class CommandButtonLayoutManagerSmall implements
44
CommandButtonLayoutManager {
47
public int getPreferredIconSize() {
52
public Dimension getPreferredSize(AbstractCommandButton commandButton) {
53
Insets borderInsets = commandButton.getInsets();
54
// int bx = borderInsets.left + borderInsets.right;
55
int by = borderInsets.top + borderInsets.bottom;
56
FontMetrics fm = commandButton.getFontMetrics(commandButton.getFont());
58
int layoutHGap = FlamingoUtilities.getHLayoutGap(commandButton);
60
boolean hasIcon = (commandButton.getIcon() != null);
61
boolean hasPopupIcon = FlamingoUtilities.hasPopupAction(commandButton);
63
int prefIconSize = hasIcon ? this.getPreferredIconSize() : 0;
65
// start with the left insets
66
int width = borderInsets.left;
69
// padding before the icon
72
width += prefIconSize;
73
// padding after the icon
78
// padding before the popup icon
79
width += 2 * layoutHGap;
81
width += 1 + fm.getHeight() / 2;
82
// padding after the popup icon
83
width += 2 * layoutHGap;
86
if (commandButton instanceof JCommandButton) {
87
JCommandButton jcb = (JCommandButton) commandButton;
88
CommandButtonKind buttonKind = jcb.getCommandButtonKind();
89
if (hasIcon && buttonKind.hasAction() && buttonKind.hasPopup()) {
90
// space for a vertical separator
91
width += new JSeparator(JSeparator.VERTICAL).getPreferredSize().width;
96
width += borderInsets.right;
98
// and remove the padding before the first and after the last elements
99
width -= 2 * layoutHGap;
101
return new Dimension(width, by
102
+ Math.max(prefIconSize, fm.getAscent() + fm.getDescent()));
106
public void propertyChange(PropertyChangeEvent evt) {
110
public Point getKeyTipAnchorCenterPoint(AbstractCommandButton commandButton) {
111
Insets ins = commandButton.getInsets();
112
int height = commandButton.getHeight();
113
ResizableIcon buttonIcon = commandButton.getIcon();
114
if (buttonIcon != null) {
115
// bottom-right corner of the icon area
116
return new Point(ins.left + buttonIcon.getIconWidth(),
117
(height + buttonIcon.getIconHeight()) / 2);
119
// bottom-left corner of the button
120
return new Point(ins.left, 3 * height / 4);
125
public CommandButtonLayoutInfo getLayoutInfo(
126
AbstractCommandButton commandButton, Graphics g) {
127
CommandButtonLayoutInfo result = new CommandButtonLayoutInfo();
129
result.actionClickArea = new Rectangle(0, 0, 0, 0);
130
result.popupClickArea = new Rectangle(0, 0, 0, 0);
132
Insets ins = commandButton.getInsets();
134
result.iconRect = new Rectangle();
135
result.popupActionRect = new Rectangle();
137
int width = commandButton.getWidth();
138
int height = commandButton.getHeight();
140
int prefWidth = this.getPreferredSize(commandButton).width;
142
if (commandButton.getHorizontalAlignment() == SwingConstants.CENTER) {
143
if (width > prefWidth) {
144
shiftX = (width - prefWidth) / 2;
148
ResizableIcon buttonIcon = commandButton.getIcon();
150
boolean hasIcon = (buttonIcon != null);
151
boolean hasPopupIcon = FlamingoUtilities.hasPopupAction(commandButton);
153
boolean ltr = commandButton.getComponentOrientation().isLeftToRight();
155
FontMetrics fm = g.getFontMetrics();
156
int labelHeight = fm.getAscent() + fm.getDescent();
158
JCommandButton.CommandButtonKind buttonKind = (commandButton instanceof JCommandButton) ? ((JCommandButton) commandButton)
159
.getCommandButtonKind()
160
: JCommandButton.CommandButtonKind.ACTION_ONLY;
161
int layoutHGap = FlamingoUtilities.getHLayoutGap(commandButton);
164
int x = ins.left + shiftX - layoutHGap;
170
int iconHeight = buttonIcon.getIconHeight();
171
int iconWidth = buttonIcon.getIconWidth();
173
result.iconRect.x = x;
174
result.iconRect.y = (height - iconHeight) / 2;
175
result.iconRect.width = iconWidth;
176
result.iconRect.height = iconHeight;
178
x += (iconWidth + layoutHGap);
184
result.popupActionRect.x = x;
185
result.popupActionRect.y = (height - labelHeight) / 2 - 1;
186
result.popupActionRect.width = 1 + labelHeight / 2;
187
result.popupActionRect.height = labelHeight + 2;
188
x += result.popupActionRect.width;
193
int xBorderBetweenActionAndPopup = 0;
194
int verticalSeparatorWidth = new JSeparator(JSeparator.VERTICAL)
195
.getPreferredSize().width;
196
// compute the action and popup click areas
197
switch (buttonKind) {
199
result.actionClickArea.x = 0;
200
result.actionClickArea.y = 0;
201
result.actionClickArea.width = width;
202
result.actionClickArea.height = height;
203
result.isTextInActionArea = true;
206
result.popupClickArea.x = 0;
207
result.popupClickArea.y = 0;
208
result.popupClickArea.width = width;
209
result.popupClickArea.height = height;
210
result.isTextInActionArea = false;
212
case ACTION_AND_POPUP_MAIN_ACTION:
213
case ACTION_AND_POPUP_MAIN_POPUP:
214
// 1. break after icon if button has icon
215
// 2. no break (all popup) if button has no icon
217
// shift popup action rectangle to the right
218
// to accomodate the vertical separator
219
result.popupActionRect.x += verticalSeparatorWidth;
221
xBorderBetweenActionAndPopup = result.iconRect.x
222
+ result.iconRect.width + layoutHGap;
224
result.actionClickArea.x = 0;
225
result.actionClickArea.y = 0;
226
result.actionClickArea.width = xBorderBetweenActionAndPopup;
227
result.actionClickArea.height = height;
229
result.popupClickArea.x = xBorderBetweenActionAndPopup;
230
result.popupClickArea.y = 0;
231
result.popupClickArea.width = width
232
- xBorderBetweenActionAndPopup;
233
result.popupClickArea.height = height;
235
result.separatorOrientation = CommandButtonSeparatorOrientation.VERTICAL;
236
result.separatorArea = new Rectangle();
237
result.separatorArea.x = xBorderBetweenActionAndPopup;
238
result.separatorArea.y = 0;
239
result.separatorArea.width = verticalSeparatorWidth;
240
result.separatorArea.height = height;
242
result.isTextInActionArea = true;
244
result.popupClickArea.x = 0;
245
result.popupClickArea.y = 0;
246
result.popupClickArea.width = width;
247
result.popupClickArea.height = height;
249
result.isTextInActionArea = true;
254
int x = width - ins.right - shiftX + layoutHGap;
260
int iconHeight = buttonIcon.getIconHeight();
261
int iconWidth = buttonIcon.getIconWidth();
263
result.iconRect.x = x - iconWidth;
264
result.iconRect.y = (height - iconHeight) / 2;
265
result.iconRect.width = iconWidth;
266
result.iconRect.height = iconHeight;
268
x -= (iconWidth + layoutHGap);
274
result.popupActionRect.width = 1 + labelHeight / 2;
275
result.popupActionRect.x = x - result.popupActionRect.width;
276
result.popupActionRect.y = (height - labelHeight) / 2 - 1;
277
result.popupActionRect.height = labelHeight + 2;
278
x -= result.popupActionRect.width;
283
int xBorderBetweenActionAndPopup = 0;
284
int verticalSeparatorWidth = new JSeparator(JSeparator.VERTICAL)
285
.getPreferredSize().width;
286
// compute the action and popup click areas
287
switch (buttonKind) {
289
result.actionClickArea.x = 0;
290
result.actionClickArea.y = 0;
291
result.actionClickArea.width = width;
292
result.actionClickArea.height = height;
293
result.isTextInActionArea = true;
296
result.popupClickArea.x = 0;
297
result.popupClickArea.y = 0;
298
result.popupClickArea.width = width;
299
result.popupClickArea.height = height;
300
result.isTextInActionArea = false;
302
case ACTION_AND_POPUP_MAIN_ACTION:
303
case ACTION_AND_POPUP_MAIN_POPUP:
304
// 1. break after icon if button has icon
305
// 2. no break (all popup) if button has no icon
307
// shift popup action rectangle to the left
308
// to accomodate the vertical separator
309
result.popupActionRect.x -= verticalSeparatorWidth;
311
xBorderBetweenActionAndPopup = result.iconRect.x
314
result.actionClickArea.x = xBorderBetweenActionAndPopup;
315
result.actionClickArea.y = 0;
316
result.actionClickArea.width = width
317
- xBorderBetweenActionAndPopup;
318
result.actionClickArea.height = height;
320
result.popupClickArea.x = 0;
321
result.popupClickArea.y = 0;
322
result.popupClickArea.width = xBorderBetweenActionAndPopup;
323
result.popupClickArea.height = height;
325
result.separatorOrientation = CommandButtonSeparatorOrientation.VERTICAL;
326
result.separatorArea = new Rectangle();
327
result.separatorArea.x = xBorderBetweenActionAndPopup;
328
result.separatorArea.y = 0;
329
result.separatorArea.width = verticalSeparatorWidth;
330
result.separatorArea.height = height;
332
result.isTextInActionArea = true;
334
result.popupClickArea.x = 0;
335
result.popupClickArea.y = 0;
336
result.popupClickArea.width = width;
337
result.popupClickArea.height = height;
339
result.isTextInActionArea = true;