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.ribbon;
33
import java.awt.color.ColorSpace;
34
import java.awt.image.ColorConvertOp;
35
import java.beans.PropertyChangeEvent;
36
import java.beans.PropertyChangeListener;
39
import javax.swing.plaf.ComponentUI;
41
import org.pushingpixels.flamingo.api.common.HorizontalAlignment;
42
import org.pushingpixels.flamingo.api.common.icon.FilteredResizableIcon;
43
import org.pushingpixels.flamingo.api.common.icon.ResizableIcon;
44
import org.pushingpixels.flamingo.api.ribbon.JRibbonComponent;
45
import org.pushingpixels.flamingo.api.ribbon.RibbonElementPriority;
47
public class BasicRibbonComponentUI extends RibbonComponentUI {
49
* The associated ribbon component.
51
protected JRibbonComponent ribbonComponent;
53
protected JLabel captionLabel;
55
protected PropertyChangeListener propertyChangeListener;
57
protected ResizableIcon disabledIcon;
62
* @see javax.swing.plaf.ComponentUI#createUI(javax.swing.JComponent)
64
public static ComponentUI createUI(JComponent c) {
65
return new BasicRibbonComponentUI();
71
* @see javax.swing.plaf.ComponentUI#installUI(javax.swing.JComponent)
74
public void installUI(JComponent c) {
75
this.ribbonComponent = (JRibbonComponent) c;
79
c.setLayout(createLayoutManager());
85
* @see javax.swing.plaf.ComponentUI#uninstallUI(javax.swing.JComponent)
88
public void uninstallUI(JComponent c) {
92
uninstallComponents();
96
* Installs default parameters on the associated ribbon component.
98
protected void installDefaults() {
99
if (!this.ribbonComponent.isSimpleWrapper()) {
100
ResizableIcon icon = this.ribbonComponent.getIcon();
102
icon.setDimension(new Dimension(16, 16));
103
this.disabledIcon = createDisabledIcon();
107
this.ribbonComponent.getMainComponent().setOpaque(false);
108
this.ribbonComponent.setOpaque(false);
112
* Installs subcomponents on the associated ribbon component.
114
protected void installComponents() {
115
this.captionLabel = new JLabel(this.ribbonComponent.getCaption());
116
this.captionLabel.setEnabled(this.ribbonComponent.isEnabled());
117
this.ribbonComponent.add(this.captionLabel);
119
JComponent mainComponent = this.ribbonComponent.getMainComponent();
120
this.ribbonComponent.add(mainComponent);
124
* Installs listeners on the associated ribbon component.
126
protected void installListeners() {
127
this.propertyChangeListener = new PropertyChangeListener() {
129
public void propertyChange(PropertyChangeEvent evt) {
130
if ("enabled".equals(evt.getPropertyName())) {
131
boolean isEnabled = (Boolean) evt.getNewValue();
132
ribbonComponent.getMainComponent().setEnabled(isEnabled);
133
if (!ribbonComponent.isSimpleWrapper()) {
134
captionLabel.setEnabled(isEnabled);
136
ribbonComponent.repaint();
138
if ("caption".equals(evt.getPropertyName())) {
139
captionLabel.setText((String) evt.getNewValue());
141
if ("displayPriority".equals(evt.getPropertyName())) {
142
ribbonComponent.revalidate();
143
ribbonComponent.doLayout();
148
.addPropertyChangeListener(this.propertyChangeListener);
153
* Uninstalls default parameters from the associated ribbon component.
155
protected void uninstallDefaults() {
159
* Uninstalls components from the associated ribbon component.
161
protected void uninstallComponents() {
162
JComponent mainComponent = this.ribbonComponent.getMainComponent();
163
this.ribbonComponent.remove(mainComponent);
165
this.ribbonComponent.remove(this.captionLabel);
166
this.captionLabel = null;
170
* Uninstalls listeners from the associated ribbon component.
172
protected void uninstallListeners() {
174
.removePropertyChangeListener(this.propertyChangeListener);
175
this.propertyChangeListener = null;
179
public Point getKeyTipAnchorCenterPoint() {
180
if (this.ribbonComponent.isSimpleWrapper()) {
182
this.ribbonComponent.getMainComponent().getX() + 10,
183
this.ribbonComponent.getHeight());
185
return new Point(this.captionLabel.getX(), this.ribbonComponent
190
protected LayoutManager createLayoutManager() {
191
return new ExtComponentLayout();
194
protected class ExtComponentLayout implements LayoutManager {
196
public void addLayoutComponent(String name, Component comp) {
200
public void removeLayoutComponent(Component comp) {
204
public Dimension minimumLayoutSize(Container parent) {
205
Insets ins = ribbonComponent.getInsets();
206
JComponent mainComponent = ribbonComponent.getMainComponent();
207
Dimension minMain = mainComponent.getMinimumSize();
209
int width = ins.left;
210
int height = minMain.height;
211
if (isIconVisible(ribbonComponent.getDisplayPriority())) {
212
ResizableIcon icon = ribbonComponent.getIcon();
214
width += (icon.getIconWidth() + getLayoutGap());
215
height = Math.max(height, icon.getIconHeight());
218
if (isCaptionVisible(ribbonComponent.getDisplayPriority())) {
219
Dimension minCaption = captionLabel.getMinimumSize();
220
width += (minCaption.width + getLayoutGap());
221
height = Math.max(height, minCaption.height);
223
width += minMain.width;
225
height += (ins.top + ins.bottom);
227
return new Dimension(width, height);
231
public Dimension preferredLayoutSize(Container parent) {
232
return getPreferredSize(ribbonComponent.getDisplayPriority());
236
public void layoutContainer(Container parent) {
237
JRibbonComponent ribbonComp = (JRibbonComponent) parent;
238
Insets ins = ribbonComp.getInsets();
239
int gap = getLayoutGap();
240
int availableHeight = ribbonComp.getHeight() - ins.top - ins.bottom;
241
int availableWidth = ribbonComp.getWidth() - ins.left - ins.right;
243
HorizontalAlignment horizAlignment = ribbonComp
244
.getHorizontalAlignment();
245
JComponent mainComp = ribbonComp.getMainComponent();
246
Dimension prefMainDim = mainComp.getPreferredSize();
247
int prefMainWidth = prefMainDim.width;
248
int finalHeight = Math.min(prefMainDim.height, availableHeight);
249
boolean ltr = ribbonComp.getComponentOrientation().isLeftToRight();
251
if (ribbonComp.isSimpleWrapper()) {
252
int finalMainWidth = Math.min(availableWidth, prefMainWidth);
253
int offset = availableWidth - prefMainWidth;
254
int topMain = ins.top + (availableHeight - finalHeight) / 2;
255
int x = ltr ? ins.left : ribbonComp.getWidth() - ins.right;
256
switch (horizAlignment) {
259
mainComp.setBounds(x, topMain, finalMainWidth,
262
mainComp.setBounds(x - finalMainWidth, topMain,
263
finalMainWidth, finalHeight);
268
mainComp.setBounds(x + offset, topMain, finalMainWidth,
271
mainComp.setBounds(x - finalMainWidth - offset,
272
topMain, finalMainWidth, finalHeight);
277
mainComp.setBounds(x + offset / 2, topMain,
278
finalMainWidth, finalHeight);
280
mainComp.setBounds(x - finalMainWidth - offset / 2,
281
topMain, finalMainWidth, finalHeight);
286
mainComp.setBounds(x, topMain, availableWidth,
289
mainComp.setBounds(x - availableWidth, topMain,
290
availableWidth, finalHeight);
296
int x = ltr ? ins.left : ribbonComp.getWidth() - ins.right;
297
if (isIconVisible(ribbonComponent.getDisplayPriority())) {
298
if (ribbonComp.getIcon() != null) {
299
// icon is painted separately
300
int iconW = ribbonComp.getIcon().getIconWidth();
301
x = ltr ? x + iconW + gap : x - iconW - gap;
305
if (isCaptionVisible(ribbonComponent.getDisplayPriority())) {
306
captionLabel.setVisible(true);
307
Dimension prefCaptionDim = captionLabel.getPreferredSize();
313
+ (availableHeight - prefCaptionDim.height)
314
/ 2, prefCaptionDim.width,
315
prefCaptionDim.height);
316
x += (prefCaptionDim.width + gap);
320
x - prefCaptionDim.width,
322
+ (availableHeight - prefCaptionDim.height)
323
/ 2, prefCaptionDim.width,
324
prefCaptionDim.height);
325
x -= (prefCaptionDim.width + gap);
328
captionLabel.setVisible(false);
331
int topMain = ins.top + (availableHeight - finalHeight) / 2;
332
int finalMainWidth = ltr ? Math.min(ribbonComp.getWidth()
333
- ins.right - x, prefMainWidth) : Math.min(
334
x - ins.left, prefMainWidth);
335
int offset = ltr ? ribbonComp.getWidth() - ins.right - x
336
- prefMainWidth : x - prefMainWidth - ins.left;
338
switch (horizAlignment) {
341
mainComp.setBounds(x, topMain, finalMainWidth,
344
mainComp.setBounds(x - finalMainWidth, topMain,
345
finalMainWidth, finalHeight);
350
mainComp.setBounds(x + offset, topMain, finalMainWidth,
353
mainComp.setBounds(x - finalMainWidth - offset,
354
topMain, finalMainWidth, finalHeight);
359
mainComp.setBounds(x + offset / 2, topMain,
360
finalMainWidth, finalHeight);
362
mainComp.setBounds(x - finalMainWidth - offset / 2,
363
topMain, finalMainWidth, finalHeight);
368
mainComp.setBounds(x, topMain, ribbonComp.getWidth()
369
- ins.right - x, finalHeight);
371
mainComp.setBounds(ins.left, topMain, x - ins.left,
382
public void paint(Graphics g, JComponent c) {
383
JRibbonComponent ribbonComp = (JRibbonComponent) c;
384
if (isIconVisible(this.ribbonComponent.getDisplayPriority())) {
385
Insets ins = ribbonComp.getInsets();
386
ResizableIcon icon = ribbonComp.isEnabled() ? ribbonComp.getIcon()
389
int availableHeight = ribbonComp.getHeight() - ins.top
391
int iconY = Math.max(0, ins.top
392
+ (availableHeight - icon.getIconHeight()) / 2);
393
if (ribbonComp.getComponentOrientation().isLeftToRight()) {
394
paintIcon(g, ribbonComp, icon, ins.left, iconY);
396
paintIcon(g, ribbonComp, icon, ribbonComp.getWidth()
397
- ins.right - icon.getIconWidth(), iconY);
403
protected void paintIcon(Graphics g, JRibbonComponent ribbonComp,
404
Icon icon, int x, int y) {
405
icon.paintIcon(ribbonComp, g, x, y);
408
protected int getLayoutGap() {
412
protected ResizableIcon createDisabledIcon() {
413
return new FilteredResizableIcon(this.ribbonComponent.getIcon(),
414
new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY),
418
protected boolean isIconVisible(RibbonElementPriority displayPriority) {
419
if (this.ribbonComponent.isSimpleWrapper())
421
return (displayPriority == RibbonElementPriority.TOP)
422
|| (displayPriority == RibbonElementPriority.MEDIUM);
425
protected boolean isCaptionVisible(RibbonElementPriority displayPriority) {
426
if (this.ribbonComponent.isSimpleWrapper())
428
return (displayPriority == RibbonElementPriority.TOP);
432
public Dimension getPreferredSize(RibbonElementPriority priority) {
433
Insets ins = ribbonComponent.getInsets();
434
JComponent mainComponent = ribbonComponent.getMainComponent();
435
Dimension prefMain = mainComponent.getPreferredSize();
437
int width = ins.left;
438
int height = prefMain.height;
439
if (isIconVisible(priority)) {
440
ResizableIcon icon = ribbonComponent.getIcon();
442
width += (icon.getIconWidth() + getLayoutGap());
443
height = Math.max(height, icon.getIconHeight());
446
if (isCaptionVisible(priority)) {
447
Dimension prefCaption = captionLabel.getPreferredSize();
448
width += (prefCaption.width + getLayoutGap());
449
height = Math.max(height, prefCaption.height);
451
width += prefMain.width;
453
height += (ins.top + ins.bottom);
455
return new Dimension(width, height);