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

« back to all changes in this revision

Viewing changes to substance-flamingo/src/main/java/org/pushingpixels/substance/flamingo/ribbon/ui/SubstanceRibbonFrameTitlePane.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 / Substance 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.substance.flamingo.ribbon.ui;
 
31
 
 
32
import java.awt.*;
 
33
import java.awt.geom.Arc2D;
 
34
import java.awt.geom.GeneralPath;
 
35
import java.util.HashMap;
 
36
import java.util.Map;
 
37
 
 
38
import javax.swing.*;
 
39
import javax.swing.border.EmptyBorder;
 
40
import javax.swing.event.ChangeEvent;
 
41
import javax.swing.event.ChangeListener;
 
42
 
 
43
import org.pushingpixels.flamingo.api.ribbon.*;
 
44
import org.pushingpixels.flamingo.internal.ui.ribbon.BasicRibbonUI;
 
45
import org.pushingpixels.flamingo.internal.ui.ribbon.RibbonUI;
 
46
import org.pushingpixels.flamingo.internal.ui.ribbon.appmenu.JRibbonApplicationMenuButton;
 
47
import org.pushingpixels.flamingo.internal.utils.FlamingoUtilities;
 
48
import org.pushingpixels.lafwidget.LafWidgetUtilities;
 
49
import org.pushingpixels.lafwidget.utils.RenderingUtils;
 
50
import org.pushingpixels.substance.api.*;
 
51
import org.pushingpixels.substance.api.painter.border.SubstanceBorderPainter;
 
52
import org.pushingpixels.substance.api.painter.fill.MatteFillPainter;
 
53
import org.pushingpixels.substance.internal.painter.DecorationPainterUtils;
 
54
import org.pushingpixels.substance.internal.painter.SeparatorPainterUtils;
 
55
import org.pushingpixels.substance.internal.ui.SubstanceRootPaneUI;
 
56
import org.pushingpixels.substance.internal.utils.*;
 
57
 
 
58
/**
 
59
 * Custom title pane for {@link JRibbonFrame} running under Substance
 
60
 * look-and-feel.
 
61
 *
 
62
 * @author Kirill Grouchnikov
 
63
 */
 
64
public class SubstanceRibbonFrameTitlePane extends SubstanceTitlePane {
 
65
        /**
 
66
         * Custom component to paint the header of a single contextual task group.
 
67
         *
 
68
         * @author Kirill Grouchnikov
 
69
         */
 
70
        private class SubstanceContextualGroupComponent extends JComponent {
 
71
                /**
 
72
                 * The associated contextual task group.
 
73
                 */
 
74
                RibbonContextualTaskGroup taskGroup;
 
75
 
 
76
                /**
 
77
                 * Creates the new task group header component.
 
78
                 *
 
79
                 * @param taskGroup
 
80
                 *            The associated contextual task group.
 
81
                 */
 
82
                public SubstanceContextualGroupComponent(
 
83
                                RibbonContextualTaskGroup taskGroup) {
 
84
                        this.taskGroup = taskGroup;
 
85
                        this.setOpaque(false);
 
86
                }
 
87
 
 
88
                /*
 
89
                 * (non-Javadoc)
 
90
                 *
 
91
                 * @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
 
92
                 */
 
93
                @Override
 
94
                protected void paintComponent(Graphics g) {
 
95
                        int width = this.getWidth();
 
96
                        int height = this.getHeight();
 
97
                        Color hueColor = this.taskGroup.getHueColor();
 
98
 
 
99
                        Graphics2D g2d = (Graphics2D) g.create();
 
100
                        Paint paint = new GradientPaint(0, 0, SubstanceColorUtilities
 
101
                                        .getAlphaColor(hueColor, 0), 0, height,
 
102
                                        SubstanceColorUtilities.getAlphaColor(hueColor,
 
103
                                                        (int) (255 * RibbonContextualTaskGroup.HUE_ALPHA)));
 
104
                        g2d = (Graphics2D) g.create();
 
105
                        // translucent gradient paint
 
106
                        g2d.setPaint(paint);
 
107
                        g2d.fillRect(0, 0, width, height);
 
108
                        // and a solid line at the bottom
 
109
                        g2d.setColor(hueColor);
 
110
                        g2d.drawLine(1, height - 1, width, height - 1);
 
111
 
 
112
                        JRibbon ribbon = getRibbon();
 
113
 
 
114
                        SubstanceColorScheme scheme = SubstanceCoreUtilities.getSkin(
 
115
                                        rootPane).getEnabledColorScheme(
 
116
                                        DecorationAreaType.PRIMARY_TITLE_PANE);
 
117
 
 
118
                        // task group title
 
119
                        FontMetrics fm = this.getFontMetrics(ribbon.getFont());
 
120
                        int yOffset = (height - fm.getHeight()) / 2;
 
121
                        RenderingUtils.installDesktopHints(g2d, this);
 
122
 
 
123
                        int offset = SubstanceSizeUtils.getAdjustedSize(SubstanceSizeUtils
 
124
                                        .getComponentFontSize(this), 5, 2, 1, false);
 
125
                        if (getComponentOrientation().isLeftToRight()) {
 
126
                                SubstanceTextUtilities.paintText(g2d, this, new Rectangle(
 
127
                                                offset, yOffset, width, height - yOffset),
 
128
                                                this.taskGroup.getTitle(), -1, ribbon.getFont(),
 
129
                                                SubstanceColorUtilities.getForegroundColor(scheme),
 
130
                                                null);
 
131
                        } else {
 
132
                                SubstanceTextUtilities.paintText(g2d, this, new Rectangle(width
 
133
                                                - offset
 
134
                                                - g2d.getFontMetrics().stringWidth(
 
135
                                                                this.taskGroup.getTitle()), yOffset, width,
 
136
                                                height - yOffset), this.taskGroup.getTitle(), -1,
 
137
                                                ribbon.getFont(), SubstanceColorUtilities
 
138
                                                                .getForegroundColor(scheme), null);
 
139
                        }
 
140
 
 
141
                        // left separator
 
142
                        SeparatorPainterUtils.paintSeparator(ribbon, g2d, 2, height,
 
143
                                        SwingConstants.VERTICAL, false, height / 3, 0, true);
 
144
 
 
145
                        // right separator
 
146
                        g2d.translate(width - 1, 0);
 
147
                        SeparatorPainterUtils.paintSeparator(ribbon, g2d, 2, height,
 
148
                                        SwingConstants.VERTICAL, false, height / 3, 0, true);
 
149
 
 
150
                        g2d.dispose();
 
151
                }
 
152
        }
 
153
 
 
154
        /**
 
155
         * The taskbar panel that holds the {@link JRibbon#getTaskbarComponents()}.
 
156
         *
 
157
         * @author Kirill Grouchnikov
 
158
         */
 
159
        private class TaskbarPanel extends JPanel {
 
160
                /**
 
161
                 * Creates the new taskbar panel.
 
162
                 */
 
163
                public TaskbarPanel() {
 
164
                        super(new TaskbarLayout());
 
165
                        this.setOpaque(false);
 
166
                        int insets = SubstanceSizeUtils.getAdjustedSize(SubstanceSizeUtils
 
167
                                        .getComponentFontSize(this), 2, 3, 1, false);
 
168
                        this.setBorder(new EmptyBorder(insets, insets, insets, insets));
 
169
                }
 
170
 
 
171
                /*
 
172
                 * (non-Javadoc)
 
173
                 *
 
174
                 * @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
 
175
                 */
 
176
                @Override
 
177
                protected void paintComponent(Graphics g) {
 
178
                }
 
179
 
 
180
                /**
 
181
                 * Returns the outline of this taskbar panel.
 
182
                 *
 
183
                 * @param insets
 
184
                 *            Insets.
 
185
                 * @return The outline of this taskbar panel.
 
186
                 */
 
187
                protected Shape getOutline(double insets) {
 
188
                        double width = this.getWidth() - 2 * insets - 1;
 
189
                        double height = this.getHeight() - 2 * insets - 1;
 
190
                        float radius = (float) height;
 
191
 
 
192
                        if (getComponentCount() == 0) {
 
193
                                return null;
 
194
                        } else {
 
195
                                GeneralPath outline = new GeneralPath();
 
196
                                JRibbonApplicationMenuButton menuButton = FlamingoUtilities
 
197
                                                .getApplicationMenuButton(SwingUtilities
 
198
                                                                .getWindowAncestor(this));
 
199
 
 
200
                                boolean ltr = getComponentOrientation().isLeftToRight();
 
201
 
 
202
                                double alpha = Math.asin((radius - insets / 2)
 
203
                                                / (radius + insets / 2));
 
204
 
 
205
                                if (ltr) {
 
206
                                        // top right
 
207
                                        outline.moveTo(insets + width - height / 2, insets);
 
208
 
 
209
                                        // right arc
 
210
                                        outline
 
211
                                                        .append(new Arc2D.Double(insets + width - height,
 
212
                                                                        insets, height, height, 90, -180,
 
213
                                                                        Arc2D.OPEN), true);
 
214
                                        // bottom left
 
215
                                        outline.lineTo(insets, insets + height);
 
216
                                        if (menuButton != null) {
 
217
                                                double arcSpan = 90;
 
218
                                                if (insets != 0) {
 
219
                                                        arcSpan = 180.0 * alpha / Math.PI;
 
220
                                                }
 
221
                                                outline.append(new Arc2D.Double(insets - 2 * height,
 
222
                                                                insets, 2 * height, 2 * height, 0, arcSpan,
 
223
                                                                Arc2D.OPEN), true);
 
224
                                        } else {
 
225
                                                outline.lineTo(insets, insets);
 
226
                                        }
 
227
                                } else {
 
228
                                        // top left corner
 
229
                                        outline.moveTo(insets + height / 2, 0);
 
230
                                        // left arc
 
231
                                        outline.append(new Arc2D.Double(insets, 0, height, height,
 
232
                                                        90, 180, Arc2D.OPEN), true);
 
233
                                        // bottom right corner
 
234
                                        outline.lineTo(width - 1, insets + height);
 
235
                                        if (menuButton != null) {
 
236
                                                double arcSpan = -90;
 
237
                                                if (insets != 0) {
 
238
                                                        arcSpan = -180.0 * alpha / Math.PI;
 
239
                                                }
 
240
                                                outline.append(new Arc2D.Double(width - 1, 0,
 
241
                                                                2 * height, 2 * height, 180, arcSpan,
 
242
                                                                Arc2D.OPEN), true);
 
243
                                        } else {
 
244
                                                outline.lineTo(width - 1, 0);
 
245
                                        }
 
246
                                }
 
247
                                outline.closePath();
 
248
 
 
249
                                return outline;
 
250
                        }
 
251
                }
 
252
 
 
253
                /*
 
254
                 * (non-Javadoc)
 
255
                 *
 
256
                 * @see javax.swing.JComponent#getPreferredSize()
 
257
                 */
 
258
                @Override
 
259
                public Dimension getPreferredSize() {
 
260
                        Dimension result = super.getPreferredSize();
 
261
                        return new Dimension(result.width + result.height / 2,
 
262
                                        result.height);
 
263
                }
 
264
        }
 
265
 
 
266
        /**
 
267
         * Maps the currently visible contextual task groups to the respective child
 
268
         * components of this title pane.
 
269
         */
 
270
        protected Map<RibbonContextualTaskGroup, SubstanceContextualGroupComponent> taskComponentMap;
 
271
 
 
272
        /**
 
273
         * Listener to sync {@link #taskComponentMap}.
 
274
         */
 
275
        protected ChangeListener ribbonFrameChangeListener;
 
276
 
 
277
        /**
 
278
         * Panel for the taskbar components.
 
279
         */
 
280
        protected TaskbarPanel taskbarPanel;
 
281
 
 
282
        /**
 
283
         * Creates a new title pane for {@link JRibbonFrame}.
 
284
         *
 
285
         * @param root
 
286
         *            Root pane.
 
287
         * @param ui
 
288
         *            UI delegate.
 
289
         */
 
290
        public SubstanceRibbonFrameTitlePane(JRootPane root, SubstanceRootPaneUI ui) {
 
291
                super(root, ui);
 
292
                this.taskComponentMap = new HashMap<RibbonContextualTaskGroup, SubstanceContextualGroupComponent>();
 
293
                this.taskbarPanel = new TaskbarPanel();
 
294
                this.markExtraComponent(this.taskbarPanel, ExtraComponentKind.LEADING);
 
295
                this.add(this.taskbarPanel);
 
296
        }
 
297
 
 
298
        /*
 
299
         * (non-Javadoc)
 
300
         *
 
301
         * @see org.jvnet.substance.utils.SubstanceTitlePane#createLayout()
 
302
         */
 
303
        @Override
 
304
        protected LayoutManager createLayout() {
 
305
                return new RibbonFrameTitlePaneLayout();
 
306
        }
 
307
 
 
308
        /*
 
309
         * (non-Javadoc)
 
310
         *
 
311
         * @see org.jvnet.substance.utils.SubstanceTitlePane#addNotify()
 
312
         */
 
313
        @Override
 
314
        public void addNotify() {
 
315
                super.addNotify();
 
316
 
 
317
                JRibbon ribbon = this.getRibbon();
 
318
                ribbon.putClientProperty(BasicRibbonUI.IS_USING_TITLE_PANE,
 
319
                                Boolean.TRUE);
 
320
 
 
321
                this.syncRibbonState();
 
322
 
 
323
                this.ribbonFrameChangeListener = new ChangeListener() {
 
324
                        @Override
 
325
                        public void stateChanged(ChangeEvent e) {
 
326
                                syncRibbonState();
 
327
                        }
 
328
                };
 
329
                ribbon.addChangeListener(this.ribbonFrameChangeListener);
 
330
        }
 
331
 
 
332
        /*
 
333
         * (non-Javadoc)
 
334
         *
 
335
         * @see org.jvnet.substance.utils.SubstanceTitlePane#removeNotify()
 
336
         */
 
337
        @Override
 
338
        public void removeNotify() {
 
339
                JRibbon ribbon = this.getRibbon();
 
340
                ribbon.putClientProperty(BasicRibbonUI.IS_USING_TITLE_PANE, null);
 
341
 
 
342
                for (SubstanceContextualGroupComponent groupComp : this.taskComponentMap
 
343
                                .values()) {
 
344
                        this.remove(groupComp);
 
345
                }
 
346
 
 
347
                ribbon.removeChangeListener(this.ribbonFrameChangeListener);
 
348
                this.ribbonFrameChangeListener = null;
 
349
 
 
350
                super.removeNotify();
 
351
        }
 
352
 
 
353
        /**
 
354
         * Synchronizes the child components for ribbon state (visible contextual
 
355
         * task groups and taskbar components).
 
356
         */
 
357
        protected void syncRibbonState() {
 
358
                // Contextual task groups
 
359
                for (SubstanceContextualGroupComponent groupComp : this.taskComponentMap
 
360
                                .values()) {
 
361
                        this.remove(groupComp);
 
362
                }
 
363
                this.taskComponentMap.clear();
 
364
                JRibbon ribbon = this.getRibbon();
 
365
                for (int i = 0; i < ribbon.getContextualTaskGroupCount(); i++) {
 
366
                        RibbonContextualTaskGroup group = ribbon.getContextualTaskGroup(i);
 
367
                        if (!ribbon.isVisible(group))
 
368
                                continue;
 
369
                        SubstanceContextualGroupComponent taskGroupComponent = new SubstanceContextualGroupComponent(
 
370
                                        group);
 
371
                        taskGroupComponent.applyComponentOrientation(this.getRibbon()
 
372
                                        .getComponentOrientation());
 
373
                        this.add(taskGroupComponent);
 
374
                        this.taskComponentMap.put(group, taskGroupComponent);
 
375
                        this.markExtraComponent(taskGroupComponent,
 
376
                                        ExtraComponentKind.MIDDLING);
 
377
                }
 
378
                // Taskbar components
 
379
                this.taskbarPanel.removeAll();
 
380
                this.taskbarPanel.setPreferredSize(null);
 
381
                for (Component taskbarComp : ribbon.getTaskbarComponents()) {
 
382
                        this.taskbarPanel.add(taskbarComp);
 
383
                }
 
384
        }
 
385
 
 
386
        /**
 
387
         * Custom layout manager for the title panes of {@link JRibbonFrame} under
 
388
         * decorated mode.
 
389
         *
 
390
         * @author Kirill Grouchnikov
 
391
         */
 
392
        protected class RibbonFrameTitlePaneLayout extends TitlePaneLayout {
 
393
                /*
 
394
                 * (non-Javadoc)
 
395
                 *
 
396
                 * @seeorg.jvnet.substance.utils.SubstanceTitlePane.TitlePaneLayout#
 
397
                 * layoutContainer(java.awt.Container)
 
398
                 */
 
399
                @Override
 
400
                public void layoutContainer(Container c) {
 
401
                        super.layoutContainer(c);
 
402
 
 
403
                        JRibbon ribbon = getRibbon();
 
404
                        boolean ltr = ribbon.getComponentOrientation().isLeftToRight();
 
405
                        RibbonUI ribbonUI = ribbon.getUI();
 
406
 
 
407
                        if (ltr) {
 
408
                                // headers of contextual task groups
 
409
                                for (Map.Entry<RibbonContextualTaskGroup, SubstanceContextualGroupComponent> entry : taskComponentMap
 
410
                                                .entrySet()) {
 
411
                                        Rectangle taskGroupBounds = ribbonUI
 
412
                                                        .getContextualTaskGroupBounds(entry.getKey());
 
413
                                        // make sure that the header bounds do not overlap with the
 
414
                                        // min / max / close buttons
 
415
                                        int minTrailingX = c.getWidth();
 
416
 
 
417
                                        for (int i = 0; i < c.getComponentCount(); i++) {
 
418
                                                Component child = c.getComponent(i);
 
419
                                                if (!child.isVisible())
 
420
                                                        continue;
 
421
                                                if (child instanceof JComponent) {
 
422
                                                        ExtraComponentKind kind = (ExtraComponentKind) ((JComponent) child)
 
423
                                                                        .getClientProperty(EXTRA_COMPONENT_KIND);
 
424
                                                        if (kind == ExtraComponentKind.LEADING)
 
425
                                                                continue;
 
426
                                                        if (child instanceof SubstanceContextualGroupComponent)
 
427
                                                                continue;
 
428
 
 
429
                                                        minTrailingX = Math.min(child.getX(), minTrailingX);
 
430
                                                }
 
431
                                        }
 
432
 
 
433
                                        int width = taskGroupBounds.width;
 
434
                                        if (taskGroupBounds.x + width > (minTrailingX - 5)) {
 
435
                                                width = minTrailingX - 5 - taskGroupBounds.x;
 
436
                                        }
 
437
                                        entry.getValue().setBounds(
 
438
                                                        new Rectangle(taskGroupBounds.x, 0, width, c
 
439
                                                                        .getHeight()));
 
440
                                        // hide headers when the task toggle buttons
 
441
                                        // are wrapped with visible scroller buttons
 
442
                                        entry.getValue().setVisible(
 
443
                                                        !ribbonUI.isShowingScrollsForTaskToggleButtons());
 
444
                                }
 
445
 
 
446
                                // taskbar panel
 
447
                                taskbarPanel.setVisible(true);
 
448
                                Dimension pref = taskbarPanel.getPreferredSize();
 
449
                                if (taskbarPanel.getComponentCount() == 0) {
 
450
                                        // fix for issue 38 on Flamingo - if there are no
 
451
                                        // taskbar components, don't push the title to the right
 
452
                                        pref.width = 0;
 
453
                                }
 
454
 
 
455
                                SubstanceRibbonRootPaneUI rootPaneUI = (SubstanceRibbonRootPaneUI) getRootPane()
 
456
                                                .getUI();
 
457
                                JRibbonApplicationMenuButton menuButton = rootPaneUI.applicationMenuButton;
 
458
 
 
459
                                if (menuButton != null) {
 
460
                                        if (menuButton.isVisible()) {
 
461
                                                int maxLeadingX = menuButton.getX()
 
462
                                                                + menuButton.getWidth() + 2
 
463
                                                                * getTaskBarLayoutGap(taskbarPanel);
 
464
                                                if (taskbarPanel.isVisible()) {
 
465
                                                        taskbarPanel.setBounds(maxLeadingX, 0, pref.width,
 
466
                                                                        c.getHeight());
 
467
                                                }
 
468
                                                menuBar.setVisible(false);
 
469
                                        } else {
 
470
                                                if (taskbarPanel.isVisible()) {
 
471
                                                        if (pref.width == 0) {
 
472
                                                                taskbarPanel.setBounds(menuBar.getX()
 
473
                                                                                + menuBar.getWidth(), 0, pref.width, c
 
474
                                                                                .getHeight());
 
475
                                                        } else {
 
476
                                                                taskbarPanel.setBounds(menuBar.getX()
 
477
                                                                                + menuBar.getWidth() + 5, 0,
 
478
                                                                                pref.width, c.getHeight());
 
479
                                                        }
 
480
                                                }
 
481
                                                menuBar.setVisible(true);
 
482
                                        }
 
483
                                } else {
 
484
                                        menuBar.setVisible(true);
 
485
                                }
 
486
                        } else {
 
487
                                // headers of contextual task groups
 
488
                                for (Map.Entry<RibbonContextualTaskGroup, SubstanceContextualGroupComponent> entry : taskComponentMap
 
489
                                                .entrySet()) {
 
490
                                        Rectangle taskGroupBounds = ribbonUI
 
491
                                                        .getContextualTaskGroupBounds(entry.getKey());
 
492
                                        // make sure that the header bounds do not overlap with the
 
493
                                        // min / max / close buttons
 
494
                                        int maxTrailingX = 0;
 
495
 
 
496
                                        for (int i = 0; i < c.getComponentCount(); i++) {
 
497
                                                Component child = c.getComponent(i);
 
498
                                                if (!child.isVisible())
 
499
                                                        continue;
 
500
                                                if (child instanceof JComponent) {
 
501
                                                        ExtraComponentKind kind = (ExtraComponentKind) ((JComponent) child)
 
502
                                                                        .getClientProperty(EXTRA_COMPONENT_KIND);
 
503
                                                        if (kind == ExtraComponentKind.LEADING)
 
504
                                                                continue;
 
505
                                                        if (child instanceof SubstanceContextualGroupComponent)
 
506
                                                                continue;
 
507
 
 
508
                                                        maxTrailingX = Math.max(child.getX()
 
509
                                                                        + child.getWidth(), maxTrailingX);
 
510
                                                }
 
511
                                        }
 
512
 
 
513
                                        int width = taskGroupBounds.width;
 
514
                                        int x = taskGroupBounds.x;
 
515
                                        if (taskGroupBounds.x < (maxTrailingX + 5)) {
 
516
                                                int diff = maxTrailingX + 5 - taskGroupBounds.x;
 
517
                                                x += diff;
 
518
                                                width -= diff;
 
519
                                        }
 
520
                                        entry.getValue().setBounds(
 
521
                                                        new Rectangle(x, 0, width, c.getHeight()));
 
522
                                        // hide headers when the task toggle buttons
 
523
                                        // are wrapped with visible scroller buttons
 
524
                                        entry.getValue().setVisible(
 
525
                                                        !ribbonUI.isShowingScrollsForTaskToggleButtons());
 
526
                                }
 
527
 
 
528
                                // taskbar panel
 
529
                                taskbarPanel.setVisible(true);
 
530
                                Dimension pref = taskbarPanel.getPreferredSize();
 
531
                                if (taskbarPanel.getComponentCount() == 0) {
 
532
                                        // fix for issue 38 on Flamingo - if there are no
 
533
                                        // taskbar components, don't push the title to the left
 
534
                                        pref.width = 0;
 
535
                                }
 
536
 
 
537
                                SubstanceRibbonRootPaneUI rootPaneUI = (SubstanceRibbonRootPaneUI) getRootPane()
 
538
                                                .getUI();
 
539
                                JRibbonApplicationMenuButton menuButton = rootPaneUI.applicationMenuButton;
 
540
 
 
541
                                if (menuButton != null) {
 
542
                                        if (menuButton.isVisible()) {
 
543
                                                int maxLeadingX = menuButton.getX() - 2
 
544
                                                                * getTaskBarLayoutGap(taskbarPanel);
 
545
                                                if (taskbarPanel.isVisible()) {
 
546
                                                        taskbarPanel.setBounds(maxLeadingX - pref.width, 0,
 
547
                                                                        pref.width, c.getHeight());
 
548
                                                }
 
549
                                                menuBar.setVisible(false);
 
550
                                        } else {
 
551
                                                if (taskbarPanel.isVisible()) {
 
552
                                                        if (pref.width == 0) {
 
553
                                                                taskbarPanel.setBounds(menuBar.getX(), 0,
 
554
                                                                                pref.width, c.getHeight());
 
555
                                                        } else {
 
556
                                                                taskbarPanel.setBounds(menuBar.getX() - 5
 
557
                                                                                - pref.width, 0, pref.width, c
 
558
                                                                                .getHeight());
 
559
                                                        }
 
560
                                                }
 
561
                                                menuBar.setVisible(true);
 
562
                                        }
 
563
                                } else {
 
564
                                        menuBar.setVisible(true);
 
565
                                }
 
566
                        }
 
567
                }
 
568
        }
 
569
 
 
570
        /**
 
571
         * Layout for the task bar.
 
572
         *
 
573
         * @author Kirill Grouchnikov
 
574
         */
 
575
        private class TaskbarLayout implements LayoutManager {
 
576
                /*
 
577
                 * (non-Javadoc)
 
578
                 *
 
579
                 * @see java.awt.LayoutManager#addLayoutComponent(java.lang.String,
 
580
                 * java.awt.Component)
 
581
                 */
 
582
                @Override
 
583
        public void addLayoutComponent(String name, Component c) {
 
584
                }
 
585
 
 
586
                /*
 
587
                 * (non-Javadoc)
 
588
                 *
 
589
                 * @see java.awt.LayoutManager#removeLayoutComponent(java.awt.Component)
 
590
                 */
 
591
                @Override
 
592
        public void removeLayoutComponent(Component c) {
 
593
                }
 
594
 
 
595
                /*
 
596
                 * (non-Javadoc)
 
597
                 *
 
598
                 * @see java.awt.LayoutManager#preferredLayoutSize(java.awt.Container)
 
599
                 */
 
600
                @Override
 
601
        public Dimension preferredLayoutSize(Container c) {
 
602
                        Insets ins = c.getInsets();
 
603
                        int pw = 0;
 
604
                        int gap = getTaskBarLayoutGap(c);
 
605
                        for (Component regComp : getRibbon().getTaskbarComponents()) {
 
606
                // Do not add layout space for non-visible components
 
607
                if (regComp.isVisible()){
 
608
                                    pw += regComp.getPreferredSize().width;
 
609
                                    pw += gap;
 
610
                }
 
611
                        }
 
612
                        return new Dimension(pw + ins.left + ins.right, c.getParent()
 
613
                                        .getHeight());
 
614
                }
 
615
 
 
616
                /*
 
617
                 * (non-Javadoc)
 
618
                 *
 
619
                 * @see java.awt.LayoutManager#minimumLayoutSize(java.awt.Container)
 
620
                 */
 
621
                @Override
 
622
        public Dimension minimumLayoutSize(Container c) {
 
623
                        return this.preferredLayoutSize(c);
 
624
                }
 
625
 
 
626
                /*
 
627
                 * (non-Javadoc)
 
628
                 *
 
629
                 * @see java.awt.LayoutManager#layoutContainer(java.awt.Container)
 
630
                 */
 
631
                @Override
 
632
        public void layoutContainer(Container c) {
 
633
                        Insets ins = c.getInsets();
 
634
                        int gap = getTaskBarLayoutGap(c);
 
635
                        boolean ltr = getComponentOrientation().isLeftToRight();
 
636
                        int x = ltr ? ins.left : c.getWidth() - ins.right;
 
637
                        for (Component regComp : getRibbon().getTaskbarComponents()) {
 
638
                // Do not add layout space for non-visible components
 
639
                if (regComp.isVisible()){
 
640
                    int pw = regComp.getPreferredSize().width;
 
641
                    if (ltr) {
 
642
                        regComp.setBounds(x, ins.top, pw, c.getHeight() - ins.top
 
643
                                - ins.bottom);
 
644
                        x += (pw + gap);
 
645
                    } else {
 
646
                        regComp.setBounds(x - pw, ins.top, pw, c.getHeight()
 
647
                                - ins.top - ins.bottom);
 
648
                        x -= (pw + gap);
 
649
                    }
 
650
                }
 
651
                        }
 
652
                }
 
653
        }
 
654
 
 
655
        /**
 
656
         * Retrieves the {@link JRibbon} component of the associated
 
657
         * {@link JRibbonFrame}.
 
658
         *
 
659
         * @return {@link JRibbon} component of the associated {@link JRibbonFrame}.
 
660
         */
 
661
        private JRibbon getRibbon() {
 
662
                JRibbonFrame ribbonFrame = (JRibbonFrame) SwingUtilities
 
663
                                .getWindowAncestor(this);
 
664
                JRibbon ribbon = ribbonFrame.getRibbon();
 
665
                return ribbon;
 
666
        }
 
667
 
 
668
        /**
 
669
         * Returns the layout gap of the taskbar panel.
 
670
         * 
 
671
         * @param c
 
672
         *            Container.
 
673
         * @return Layout gap of the taskbar panel.
 
674
         */
 
675
        private int getTaskBarLayoutGap(Container c) {
 
676
                return SubstanceSizeUtils.getAdjustedSize(SubstanceSizeUtils
 
677
                                .getComponentFontSize(c), 1, 6, 1, false);
 
678
        }
 
679
 
 
680
        /*
 
681
         * (non-Javadoc)
 
682
         * 
 
683
         * @see
 
684
         * org.jvnet.substance.utils.SubstanceTitlePane#paintComponent(java.awt.
 
685
         * Graphics)
 
686
         */
 
687
        @Override
 
688
        public void paintComponent(Graphics g) {
 
689
                super.paintComponent(g);
 
690
 
 
691
                Graphics2D g2d = (Graphics2D) g.create();
 
692
                if (taskbarPanel.getWidth() != 0) {
 
693
                        g2d.translate(taskbarPanel.getX(), taskbarPanel.getY());
 
694
                        // paint the outline of the taskbar panel to complete
 
695
                        // the correct appearance in the area behind the application
 
696
                        // menu button
 
697
                        // g2d.clipRect(0, 0, 20, 100);
 
698
                        paintTaskBarPanelOutline(g2d, this.taskbarPanel);
 
699
                        g2d.translate(-taskbarPanel.getX(), -taskbarPanel.getY());
 
700
                }
 
701
 
 
702
                if (SubstanceLookAndFeel.getCurrentSkin(this).getOverlayPainters(
 
703
                                DecorationAreaType.PRIMARY_TITLE_PANE).isEmpty()) {
 
704
                        // g2d.translate(0, this.getHeight() - 1);
 
705
                        SubstanceColorScheme compScheme = SubstanceColorSchemeUtilities
 
706
                                        .getColorScheme(this, ColorSchemeAssociationKind.SEPARATOR,
 
707
                                                        ComponentState.ENABLED);
 
708
                        Color sepColor = compScheme.isDark() ? SeparatorPainterUtils
 
709
                                        .getSeparatorShadowColor(compScheme)
 
710
                                        : SeparatorPainterUtils.getSeparatorDarkColor(compScheme);
 
711
                        g2d.setColor(sepColor);
 
712
                        g2d.drawLine(0, this.getHeight() - 1, this.getWidth(), this
 
713
                                        .getHeight() - 1);
 
714
                        // SeparatorPainterUtils.paintSeparator(this, g2d, this.getWidth(),
 
715
                        // 0,
 
716
                        // JSeparator.HORIZONTAL, false, 0);
 
717
                }
 
718
                g2d.dispose();
 
719
        }
 
720
 
 
721
        /**
 
722
         * Paints the outline of the taskbar panel.
 
723
         * 
 
724
         * @param g
 
725
         *            Graphics context.
 
726
         * @param taskbarPanel
 
727
         *            Taskbar panel.
 
728
         */
 
729
        protected static void paintTaskBarPanelOutline(Graphics g,
 
730
                        TaskbarPanel taskbarPanel) {
 
731
                int borderDelta = (int) Math.floor(SubstanceSizeUtils
 
732
                                .getBorderStrokeWidth(SubstanceSizeUtils
 
733
                                                .getComponentFontSize(taskbarPanel)) / 2.0);
 
734
                int borderThickness = (int) SubstanceSizeUtils
 
735
                                .getBorderStrokeWidth(SubstanceSizeUtils
 
736
                                                .getComponentFontSize(taskbarPanel));
 
737
 
 
738
                Shape contour = taskbarPanel.getOutline(borderDelta);
 
739
                Shape contourInner = taskbarPanel.getOutline(borderDelta
 
740
                                + borderThickness);
 
741
 
 
742
                SubstanceColorScheme colorScheme = SubstanceColorSchemeUtilities
 
743
                                .getColorScheme(taskbarPanel, ComponentState.ENABLED);
 
744
                SubstanceColorScheme borderScheme = SubstanceColorSchemeUtilities
 
745
                                .getColorScheme(taskbarPanel,
 
746
                                                ColorSchemeAssociationKind.BORDER,
 
747
                                                ComponentState.ENABLED);
 
748
                SubstanceBorderPainter borderPainter = SubstanceCoreUtilities
 
749
                                .getBorderPainter(taskbarPanel);
 
750
 
 
751
                Graphics2D g2d = (Graphics2D) g.create();
 
752
                g2d.setComposite(AlphaComposite.SrcOver.derive(0.6f));
 
753
                if (contour != null) {
 
754
                        Shape clip = g2d.getClip();
 
755
                        g2d.clip(contour);
 
756
                        DecorationPainterUtils.paintDecorationBackground(g2d, taskbarPanel,
 
757
                                        true);
 
758
                        g2d.setComposite(LafWidgetUtilities.getAlphaComposite(taskbarPanel,
 
759
                                        0.3f, g));
 
760
                        MatteFillPainter.INSTANCE.paintContourBackground(g2d, taskbarPanel,
 
761
                                        taskbarPanel.getWidth(), taskbarPanel.getHeight(), contour
 
762
                                                        .getBounds(), false, colorScheme, false);
 
763
                        g2d.setComposite(LafWidgetUtilities.getAlphaComposite(taskbarPanel,
 
764
                                        1.0f, g));
 
765
                        g2d.setClip(clip);
 
766
 
 
767
                }
 
768
                borderPainter.paintBorder(g2d, taskbarPanel, taskbarPanel.getWidth(),
 
769
                                taskbarPanel.getHeight(), contour, contourInner, borderScheme);
 
770
                g2d.dispose();
 
771
        }
 
772
}