~ubuntu-branches/debian/stretch/insubstantial/stretch

« back to all changes in this revision

Viewing changes to flamingo/src/main/java/org/pushingpixels/flamingo/internal/ui/common/CommandButtonLayoutManagerBig.java

  • Committer: Package Import Robot
  • Author(s): Felix Natter
  • Date: 2016-01-18 20:58:45 UTC
  • Revision ID: package-import@ubuntu.com-20160118205845-crbmrkda61qsi5qa
Tags: upstream-7.3+dfsg2
ImportĀ upstreamĀ versionĀ 7.3+dfsg2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2005-2010 Flamingo Kirill Grouchnikov. All Rights Reserved.
 
3
 *
 
4
 * Redistribution and use in source and binary forms, with or without 
 
5
 * modification, are permitted provided that the following conditions are met:
 
6
 * 
 
7
 *  o Redistributions of source code must retain the above copyright notice, 
 
8
 *    this list of conditions and the following disclaimer. 
 
9
 *     
 
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. 
 
13
 *     
 
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. 
 
17
 *     
 
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. 
 
29
 */
 
30
package org.pushingpixels.flamingo.internal.ui.common;
 
31
 
 
32
import java.awt.*;
 
33
import java.awt.image.BufferedImage;
 
34
import java.beans.PropertyChangeEvent;
 
35
import java.util.ArrayList;
 
36
import java.util.StringTokenizer;
 
37
 
 
38
import javax.swing.JSeparator;
 
39
 
 
40
import org.pushingpixels.flamingo.api.common.*;
 
41
import org.pushingpixels.flamingo.api.common.JCommandButton.CommandButtonKind;
 
42
import org.pushingpixels.flamingo.api.common.icon.ResizableIcon;
 
43
import org.pushingpixels.flamingo.internal.utils.FlamingoUtilities;
 
44
 
 
45
public class CommandButtonLayoutManagerBig implements
 
46
                CommandButtonLayoutManager {
 
47
        protected AbstractCommandButton commandButton;
 
48
 
 
49
        /**
 
50
         * The first part of (possibly) two-lined split of {@link #commandButton}'s
 
51
         * title.
 
52
         */
 
53
        protected String titlePart1;
 
54
 
 
55
        /**
 
56
         * The second part of (possibly) two-lined split of {@link #commandButton}'s
 
57
         * title.
 
58
         */
 
59
        protected String titlePart2;
 
60
 
 
61
        public CommandButtonLayoutManagerBig(AbstractCommandButton commandButton) {
 
62
                this.commandButton = commandButton;
 
63
                this.updateTitleStrings();
 
64
        }
 
65
 
 
66
        @Override
 
67
        public int getPreferredIconSize() {
 
68
                return 32;
 
69
        }
 
70
 
 
71
        @Override
 
72
        public Dimension getPreferredSize(AbstractCommandButton commandButton) {
 
73
                Insets borderInsets = (commandButton == null) ? new Insets(0, 0, 0, 0)
 
74
                                : commandButton.getInsets();
 
75
                int bx = borderInsets.left + borderInsets.right;
 
76
                FontMetrics fm = commandButton.getFontMetrics(commandButton.getFont());
 
77
                JSeparator jsep = new JSeparator(JSeparator.HORIZONTAL);
 
78
                int layoutHGap = FlamingoUtilities.getHLayoutGap(commandButton);
 
79
                int layoutVGap = FlamingoUtilities.getVLayoutGap(commandButton);
 
80
 
 
81
                boolean hasIcon = (commandButton.getIcon() != null);
 
82
                boolean hasText = (this.titlePart1 != null);
 
83
                boolean hasPopupIcon = FlamingoUtilities.hasPopupAction(commandButton);
 
84
 
 
85
                int title1Width = (this.titlePart1 == null) ? 0 : fm
 
86
                                .stringWidth(this.titlePart1);
 
87
                int title2Width = (this.titlePart2 == null) ? 0 : fm
 
88
                                .stringWidth(this.titlePart2);
 
89
 
 
90
                int prefIconSize = hasIcon ? this.getPreferredIconSize() : 0;
 
91
 
 
92
                int width = Math.max(prefIconSize, Math.max(title1Width, title2Width
 
93
                                + 4
 
94
                                * layoutHGap
 
95
                                + jsep.getPreferredSize().height
 
96
                                + (FlamingoUtilities.hasPopupAction(commandButton) ? 1 + fm
 
97
                                                .getHeight() / 2 : 0)));
 
98
 
 
99
                // start height with the top inset
 
100
                int height = borderInsets.top;
 
101
                // icon?
 
102
                if (hasIcon) {
 
103
                        // padding above the icon
 
104
                        height += layoutVGap;
 
105
                        // icon height
 
106
                        height += prefIconSize;
 
107
                        // padding below the icon
 
108
                        height += layoutVGap;
 
109
                }
 
110
                // text?
 
111
                if (hasText) {
 
112
                        // padding above the text
 
113
                        height += layoutVGap;
 
114
                        // text height - two lines
 
115
                        height += 2 * (fm.getAscent() + fm.getDescent());
 
116
                        // padding below the text
 
117
                        height += layoutVGap;
 
118
                }
 
119
                // popup icon (no text)?
 
120
                if (!hasText && hasPopupIcon) {
 
121
                        // padding above the popup icon
 
122
                        height += layoutVGap;
 
123
                        // popup icon height - one line of text
 
124
                        height += fm.getHeight();
 
125
                        // padding below the popup icon
 
126
                        height += layoutVGap;
 
127
                }
 
128
 
 
129
                // separator?
 
130
                if (commandButton instanceof JCommandButton) {
 
131
                        JCommandButton jcb = (JCommandButton) commandButton;
 
132
                        CommandButtonKind buttonKind = jcb.getCommandButtonKind();
 
133
                        if (hasIcon && buttonKind.hasAction() && buttonKind.hasPopup()) {
 
134
                                // space for a horizontal separator
 
135
                                height += new JSeparator(JSeparator.HORIZONTAL)
 
136
                                                .getPreferredSize().height;
 
137
                        }
 
138
                }
 
139
 
 
140
                // bottom insets
 
141
                height += borderInsets.bottom;
 
142
 
 
143
                // and remove the padding above the first and below the last elements
 
144
                height -= 2 * layoutVGap;
 
145
 
 
146
                return new Dimension(bx + width, height);
 
147
        }
 
148
 
 
149
        @Override
 
150
        public void propertyChange(PropertyChangeEvent evt) {
 
151
                if ("text".equals(evt.getPropertyName())
 
152
                                || "font".equals(evt.getPropertyName())) {
 
153
                        this.updateTitleStrings();
 
154
                }
 
155
        }
 
156
 
 
157
        /**
 
158
         * Updates the title strings for {@link CommandButtonDisplayState#BIG} and
 
159
         * other relevant states.
 
160
         */
 
161
        protected void updateTitleStrings() {
 
162
                // Break the title in two parts (the second part may be empty),
 
163
                // finding the "inflection" point. The inflection point is a space
 
164
                // character that breaks the title in two parts, such that the maximal
 
165
                // length of the first part and the second part + action label icon
 
166
                // is minimal between all possible space characters
 
167
                BufferedImage tempImage = new BufferedImage(30, 30,
 
168
                                BufferedImage.TYPE_INT_ARGB);
 
169
                Graphics2D g = (Graphics2D) tempImage.getGraphics();
 
170
                g.setFont(FlamingoUtilities.getFont(this.commandButton, "Ribbon.font",
 
171
                                "Button.font", "Panel.font"));
 
172
                FontMetrics fm = g.getFontMetrics();
 
173
 
 
174
                String title = (this.commandButton == null) ? null : this.commandButton
 
175
                                .getText();
 
176
                if (title != null) {
 
177
                        StringTokenizer tokenizer = new StringTokenizer(title, " _-", true);
 
178
                        if (tokenizer.countTokens() <= 1) {
 
179
                                // single word
 
180
                                this.titlePart1 = title;
 
181
                                this.titlePart2 = null;
 
182
                        } else {
 
183
                                int currMaxLength = (int) fm.getStringBounds(
 
184
                                                this.commandButton.getText(), g).getWidth();
 
185
                                int actionIconWidth = FlamingoUtilities
 
186
                                                .hasPopupAction(this.commandButton) ? 0 : 2
 
187
                                                * FlamingoUtilities.getHLayoutGap(commandButton)
 
188
                                                + (fm.getAscent() + fm.getDescent()) / 2;
 
189
 
 
190
                                String currLeading = "";
 
191
                                while (tokenizer.hasMoreTokens()) {
 
192
                                        currLeading += tokenizer.nextToken();
 
193
                                        String part1 = currLeading;
 
194
                                        String part2 = title.substring(currLeading.length());
 
195
 
 
196
                                        int len1 = (int) fm.getStringBounds(part1, g).getWidth();
 
197
                                        int len2 = (int) fm.getStringBounds(part2, g).getWidth()
 
198
                                                        + actionIconWidth;
 
199
                                        int len = Math.max(len1, len2);
 
200
 
 
201
                                        if (currMaxLength > len) {
 
202
                                                currMaxLength = len;
 
203
                                                this.titlePart1 = part1;
 
204
                                                this.titlePart2 = part2;
 
205
                                        }
 
206
                                }
 
207
                        }
 
208
                } else {
 
209
                        this.titlePart1 = null;
 
210
                        this.titlePart2 = null;
 
211
                }
 
212
        }
 
213
 
 
214
        @Override
 
215
        public Point getKeyTipAnchorCenterPoint(AbstractCommandButton commandButton) {
 
216
                // center of the bottom edge
 
217
                return new Point(commandButton.getWidth() / 2, commandButton
 
218
                                .getHeight());
 
219
        }
 
220
 
 
221
        @Override
 
222
        public CommandButtonLayoutInfo getLayoutInfo(
 
223
                        AbstractCommandButton commandButton, Graphics g) {
 
224
                CommandButtonLayoutInfo result = new CommandButtonLayoutInfo();
 
225
 
 
226
                result.actionClickArea = new Rectangle(0, 0, 0, 0);
 
227
                result.popupClickArea = new Rectangle(0, 0, 0, 0);
 
228
 
 
229
                Insets ins = commandButton.getInsets();
 
230
 
 
231
                result.iconRect = new Rectangle();
 
232
                result.popupActionRect = new Rectangle();
 
233
 
 
234
                int width = commandButton.getWidth();
 
235
                int height = commandButton.getHeight();
 
236
 
 
237
                int x = ins.left;
 
238
 
 
239
                boolean ltr = commandButton.getComponentOrientation().isLeftToRight();
 
240
 
 
241
                FontMetrics fm = g.getFontMetrics();
 
242
                int labelHeight = fm.getAscent() + fm.getDescent();
 
243
 
 
244
                JCommandButton.CommandButtonKind buttonKind = (commandButton instanceof JCommandButton) ? ((JCommandButton) commandButton)
 
245
                                .getCommandButtonKind()
 
246
                                : JCommandButton.CommandButtonKind.ACTION_ONLY;
 
247
 
 
248
                ResizableIcon buttonIcon = commandButton.getIcon();
 
249
 
 
250
                boolean hasIcon = (commandButton.getIcon() != null);
 
251
                boolean hasText = (this.titlePart1 != null);
 
252
                boolean hasPopupIcon = FlamingoUtilities.hasPopupAction(commandButton);
 
253
 
 
254
                int layoutHGap = FlamingoUtilities.getHLayoutGap(commandButton);
 
255
                int layoutVGap = FlamingoUtilities.getVLayoutGap(commandButton);
 
256
 
 
257
                int prefHeight = this.getPreferredSize(commandButton).height;
 
258
                int shiftY = 0;
 
259
                if (height > prefHeight) {
 
260
                        shiftY = (height - prefHeight) / 2;
 
261
                }
 
262
 
 
263
                int y = ins.top + shiftY - layoutVGap;
 
264
 
 
265
                // icon
 
266
                if (hasIcon) {
 
267
                        y += layoutVGap;
 
268
 
 
269
                        int iconHeight = buttonIcon.getIconHeight();
 
270
                        int iconWidth = buttonIcon.getIconWidth();
 
271
 
 
272
                        result.iconRect.x = (width - iconWidth) / 2;
 
273
                        result.iconRect.y = y;
 
274
                        result.iconRect.width = iconWidth;
 
275
                        result.iconRect.height = iconHeight;
 
276
 
 
277
                        y += (iconHeight + layoutVGap);
 
278
                }
 
279
 
 
280
                // separator?
 
281
                if (commandButton instanceof JCommandButton) {
 
282
                        // horizontal separator is always after the icon
 
283
                        if (hasIcon && buttonKind.hasAction() && buttonKind.hasPopup()) {
 
284
                                result.separatorOrientation = CommandButtonLayoutManager.CommandButtonSeparatorOrientation.HORIZONTAL;
 
285
 
 
286
                                result.separatorArea = new Rectangle(0, 0, 0, 0);
 
287
                                result.separatorArea.x = 0;
 
288
                                result.separatorArea.y = y;
 
289
                                result.separatorArea.width = width;
 
290
                                result.separatorArea.height = new JSeparator(
 
291
                                                JSeparator.HORIZONTAL).getPreferredSize().height;
 
292
 
 
293
                                y += result.separatorArea.height;
 
294
                        }
 
295
                }
 
296
 
 
297
                int lastTextLineWidth = 0;
 
298
                // text
 
299
                if (hasText) {
 
300
                        y += layoutVGap;
 
301
                        lastTextLineWidth = (this.titlePart1 != null) ? (int) fm
 
302
                                        .getStringBounds(this.titlePart1, g).getWidth() : 0;
 
303
 
 
304
                        TextLayoutInfo line1LayoutInfo = new TextLayoutInfo();
 
305
                        line1LayoutInfo.text = this.titlePart1;
 
306
                        line1LayoutInfo.textRect = new Rectangle();
 
307
 
 
308
                        line1LayoutInfo.textRect.x = ins.left
 
309
                                        + (width - lastTextLineWidth - ins.left - ins.right) / 2;
 
310
                        line1LayoutInfo.textRect.y = y;
 
311
                        line1LayoutInfo.textRect.width = lastTextLineWidth;
 
312
                        line1LayoutInfo.textRect.height = labelHeight;
 
313
 
 
314
                        if (this.titlePart1 != null) {
 
315
                                y += labelHeight;
 
316
                        }
 
317
 
 
318
                        lastTextLineWidth = (this.titlePart2 != null) ? (int) fm
 
319
                                        .getStringBounds(this.titlePart2, g).getWidth() : 0;
 
320
 
 
321
                        int extraWidth = hasPopupIcon ? 4 * layoutHGap + labelHeight / 2
 
322
                                        : 0;
 
323
 
 
324
                        if (ltr) {
 
325
                                x = ins.left
 
326
                                                + (width - lastTextLineWidth - extraWidth - ins.left - ins.right)
 
327
                                                / 2;
 
328
                        }
 
329
                        if (!ltr) {
 
330
                                x = width
 
331
                                                - ins.right
 
332
                                                - lastTextLineWidth
 
333
                                                - +(width - lastTextLineWidth - extraWidth - ins.left - ins.right)
 
334
                                                / 2;
 
335
                        }
 
336
 
 
337
                        TextLayoutInfo line2LayoutInfo = new TextLayoutInfo();
 
338
                        line2LayoutInfo.text = this.titlePart2;
 
339
                        line2LayoutInfo.textRect = new Rectangle();
 
340
 
 
341
                        line2LayoutInfo.textRect.x = x;
 
342
                        line2LayoutInfo.textRect.y = y;
 
343
                        line2LayoutInfo.textRect.width = lastTextLineWidth;
 
344
                        line2LayoutInfo.textRect.height = labelHeight;
 
345
 
 
346
                        result.textLayoutInfoList = new ArrayList<TextLayoutInfo>();
 
347
                        result.textLayoutInfoList.add(line1LayoutInfo);
 
348
                        result.textLayoutInfoList.add(line2LayoutInfo);
 
349
                }
 
350
 
 
351
                if (hasPopupIcon) {
 
352
                        if (lastTextLineWidth > 0) {
 
353
                                if (ltr) {
 
354
                                        x += 2 * layoutHGap;
 
355
                                        x += lastTextLineWidth;
 
356
                                } else {
 
357
                                        x -= 2 * layoutHGap;
 
358
                                        x -= labelHeight / 2;
 
359
                                }
 
360
                        } else {
 
361
                                x = (width - 1 - labelHeight / 2) / 2;
 
362
                        }
 
363
 
 
364
                        result.popupActionRect.x = x;
 
365
                        result.popupActionRect.y = y - 1;
 
366
                        result.popupActionRect.width = 1 + labelHeight / 2;
 
367
                        result.popupActionRect.height = labelHeight + 2;
 
368
                }
 
369
 
 
370
                switch (buttonKind) {
 
371
                case ACTION_ONLY:
 
372
                        result.actionClickArea.x = 0;
 
373
                        result.actionClickArea.y = 0;
 
374
                        result.actionClickArea.width = width;
 
375
                        result.actionClickArea.height = height;
 
376
                        result.isTextInActionArea = true;
 
377
                        break;
 
378
                case POPUP_ONLY:
 
379
                        result.popupClickArea.x = 0;
 
380
                        result.popupClickArea.y = 0;
 
381
                        result.popupClickArea.width = width;
 
382
                        result.popupClickArea.height = height;
 
383
                        result.isTextInActionArea = false;
 
384
                        break;
 
385
                case ACTION_AND_POPUP_MAIN_ACTION:
 
386
                case ACTION_AND_POPUP_MAIN_POPUP:
 
387
                        // 1. break after icon if button has icon
 
388
                        // 2. no break (all popup) if button has no icon
 
389
                        if (hasIcon) {
 
390
                                int yBorderBetweenActionAndPopupAreas = result.iconRect.y
 
391
                                                + result.iconRect.height + layoutVGap;
 
392
 
 
393
                                result.actionClickArea.x = 0;
 
394
                                result.actionClickArea.y = 0;
 
395
                                result.actionClickArea.width = width;
 
396
                                result.actionClickArea.height = yBorderBetweenActionAndPopupAreas;
 
397
 
 
398
                                result.popupClickArea.x = 0;
 
399
                                result.popupClickArea.y = yBorderBetweenActionAndPopupAreas;
 
400
                                result.popupClickArea.width = width;
 
401
                                result.popupClickArea.height = height
 
402
                                                - yBorderBetweenActionAndPopupAreas;
 
403
 
 
404
                                result.isTextInActionArea = false;
 
405
                        } else {
 
406
                                result.popupClickArea.x = 0;
 
407
                                result.popupClickArea.y = 0;
 
408
                                result.popupClickArea.width = width;
 
409
                                result.popupClickArea.height = height;
 
410
 
 
411
                                result.isTextInActionArea = false;
 
412
                        }
 
413
                }
 
414
 
 
415
                return result;
 
416
        }
 
417
}