org.pushingpixels.flamingo.internal.ui.ribbon.BasicBandControlPanelUI Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of flamengo Show documentation
Show all versions of flamengo Show documentation
Flamingo Swing component suite
The newest version!
/*
* Copyright (c) 2005-2010 Flamingo Kirill Grouchnikov. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* o Neither the name of Flamingo Kirill Grouchnikov nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.pushingpixels.flamingo.internal.ui.ribbon;
import java.awt.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.ComponentUI;
import org.pushingpixels.flamingo.api.common.AbstractCommandButton;
import org.pushingpixels.flamingo.api.common.CommandButtonDisplayState;
import org.pushingpixels.flamingo.api.ribbon.*;
import org.pushingpixels.flamingo.api.ribbon.resize.IconRibbonBandResizePolicy;
import org.pushingpixels.flamingo.api.ribbon.resize.RibbonBandResizePolicy;
import org.pushingpixels.flamingo.internal.ui.ribbon.BasicRibbonBandUI.CollapsedButtonPopupPanel;
/**
* Basic UI for control panel of ribbon band {@link JBandControlPanel}.
*
* @author Kirill Grouchnikov
*/
public class BasicBandControlPanelUI extends AbstractBandControlPanelUI {
private JSeparator[] groupSeparators;
private JLabel[] groupLabels;
protected ChangeListener changeListener;
/*
* (non-Javadoc)
*
* @see javax.swing.plaf.ComponentUI#createUI(javax.swing.JComponent)
*/
public static ComponentUI createUI(JComponent c) {
return new BasicBandControlPanelUI();
}
/**
* Invoked by installUI
to create a layout manager object to
* manage the {@link JBandControlPanel}.
*
* @return a layout manager object
*/
@Override
protected LayoutManager createLayoutManager() {
return new ControlPanelLayout();
}
@Override
protected void installListeners() {
super.installListeners();
this.changeListener = new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
syncGroupHeaders();
controlPanel.revalidate();
}
};
((JBandControlPanel) this.controlPanel)
.addChangeListener(this.changeListener);
}
@Override
protected void uninstallListeners() {
((JBandControlPanel) this.controlPanel)
.removeChangeListener(this.changeListener);
this.changeListener = null;
super.uninstallListeners();
}
@Override
protected void installComponents() {
super.installComponents();
this.syncGroupHeaders();
}
@Override
protected void uninstallComponents() {
if (this.groupSeparators != null) {
for (JSeparator groupSeparator : this.groupSeparators) {
this.controlPanel.remove(groupSeparator);
}
}
if (this.groupLabels != null) {
for (JLabel groupLabel : this.groupLabels) {
if (groupLabel != null)
this.controlPanel.remove(groupLabel);
}
}
super.uninstallComponents();
}
protected void syncGroupHeaders() {
if (this.groupSeparators != null) {
for (JSeparator groupSeparator : this.groupSeparators) {
this.controlPanel.remove(groupSeparator);
}
}
if (this.groupLabels != null) {
for (JLabel groupLabel : this.groupLabels) {
if (groupLabel != null)
this.controlPanel.remove(groupLabel);
}
}
int groupCount = ((JBandControlPanel) this.controlPanel)
.getControlPanelGroupCount();
if (groupCount > 1) {
this.groupSeparators = new JSeparator[groupCount - 1];
for (int i = 0; i < groupCount - 1; i++) {
this.groupSeparators[i] = new JSeparator(JSeparator.VERTICAL);
this.controlPanel.add(this.groupSeparators[i]);
}
}
if (groupCount > 0) {
this.groupLabels = new JLabel[groupCount];
for (int i = 0; i < groupCount; i++) {
String title = ((JBandControlPanel) this.controlPanel)
.getControlPanelGroupTitle(i);
if (title != null) {
this.groupLabels[i] = new JLabel(title);
this.controlPanel.add(this.groupLabels[i]);
}
}
}
}
/**
* Layout for the control panel of ribbon band.
*
* @author Kirill Grouchnikov
*/
private class ControlPanelLayout implements LayoutManager {
/*
* (non-Javadoc)
*
* @see java.awt.LayoutManager#addLayoutComponent(java.lang.String,
* java.awt.Component)
*/
public void addLayoutComponent(String name, Component c) {
}
/*
* (non-Javadoc)
*
* @see java.awt.LayoutManager#removeLayoutComponent(java.awt.Component)
*/
public void removeLayoutComponent(Component c) {
}
/*
* (non-Javadoc)
*
* @see java.awt.LayoutManager#preferredLayoutSize(java.awt.Container)
*/
public Dimension preferredLayoutSize(Container c) {
// The height of ribbon band control panel is
// computed based on the preferred height of a command
// button in BIG state.
int buttonHeight = dummy.getPreferredSize().height;
int vGap = getLayoutGap() * 3 / 4;
int minusGaps = buttonHeight - 2 * vGap;
switch (minusGaps % 3) {
case 1:
buttonHeight += 2;
break;
case 2:
buttonHeight++;
break;
}
Insets ins = c.getInsets();
// System.out.println("Control panel pref = "
// + (buttonHeight + ins.top + ins.bottom));
return new Dimension(c.getWidth(), buttonHeight + ins.top
+ ins.bottom);
}
/*
* (non-Javadoc)
*
* @see java.awt.LayoutManager#minimumLayoutSize(java.awt.Container)
*/
public Dimension minimumLayoutSize(Container c) {
return this.preferredLayoutSize(c);
}
/*
* (non-Javadoc)
*
* @see java.awt.LayoutManager#layoutContainer(java.awt.Container)
*/
public void layoutContainer(Container c) {
// System.out.println("Control panel real = " + c.getHeight());
AbstractRibbonBand ribbonBand = ((JBandControlPanel) c)
.getRibbonBand();
RibbonBandResizePolicy currentResizePolicy = ribbonBand
.getCurrentResizePolicy();
if (currentResizePolicy == null)
return;
boolean ltr = c.getComponentOrientation().isLeftToRight();
// need place for border
Insets ins = c.getInsets();
int gap = getLayoutGap();
int x = ltr ? ins.left + gap / 2 : c.getWidth() - ins.right - gap
/ 2;
int availableHeight = c.getHeight() - ins.top - ins.bottom;
if (SwingUtilities.getAncestorOfClass(
CollapsedButtonPopupPanel.class, c) != null) {
// install the most permissive resize policy on the popup
// panel of a collapsed ribbon band
List resizePolicies = ribbonBand
.getResizePolicies();
resizePolicies.get(0).install(availableHeight, gap);
} else {
if (currentResizePolicy instanceof IconRibbonBandResizePolicy) {
return;
}
// Installs the resize policy - this updates the display
// priority of all the galleries and buttons
currentResizePolicy.install(availableHeight, gap);
}
int controlPanelGroupIndex = 0;
for (JBandControlPanel.ControlPanelGroup controlPanelGroup : ((JBandControlPanel) controlPanel)
.getControlPanelGroups()) {
// handle the group separators
if (controlPanelGroupIndex > 0) {
int prefW = groupSeparators[controlPanelGroupIndex - 1]
.getPreferredSize().width;
int sepX = ltr ? x - gap + (gap - prefW) / 2 : x + gap / 2
- (gap - prefW) / 2;
groupSeparators[controlPanelGroupIndex - 1].setBounds(sepX,
ins.top, prefW, availableHeight);
}
boolean hasLeadingComponent = false;
boolean isCoreContent = controlPanelGroup.isCoreContent();
if (isCoreContent) {
// how much vertical space is available in each row?
int singleRowHeight = availableHeight / 3;
boolean hasTitle = (controlPanelGroup.getGroupTitle() != null);
int maxWidthInCurrColumn = 0;
if (hasTitle) {
JLabel titleLabel = groupLabels[controlPanelGroupIndex];
int pw = titleLabel.getPreferredSize().width;
int titleLabelHeight = Math.min(singleRowHeight - gap
/ 4, titleLabel.getPreferredSize().height);
int yNudge = singleRowHeight - titleLabelHeight;
int baseline = (titleLabelHeight > 0) ? titleLabel
.getBaseline(pw, titleLabelHeight) : 0;
if (ltr) {
titleLabel.setBounds(x + gap, ins.top + yNudge
- titleLabelHeight + baseline, pw,
titleLabelHeight);
} else {
titleLabel.setBounds(x - gap - pw, ins.top + yNudge
- titleLabelHeight + baseline, pw,
titleLabelHeight);
}
maxWidthInCurrColumn = gap + pw;
}
List ribbonComps = controlPanelGroup
.getRibbonComps();
Map ribbonCompRowSpans = controlPanelGroup
.getRibbonCompsRowSpans();
List currColumn = new ArrayList();
// if a group has a title, then the core components in that
// group will take two rows instead of three
int startingRow = hasTitle ? 1 : 0;
int rowIndex = startingRow;
for (int i = 0; i < ribbonComps.size(); i++) {
JRibbonComponent coreComp = ribbonComps.get(i);
int prefWidth = coreComp.getPreferredSize().width;
int rowSpan = ribbonCompRowSpans.get(coreComp);
// do we need to start a new column?
int nextRowIndex = rowIndex + rowSpan;
if (nextRowIndex > 3) {
if (ltr) {
if (hasLeadingComponent)
x += gap;
x += maxWidthInCurrColumn;
} else {
if (hasLeadingComponent)
x -= gap;
x -= maxWidthInCurrColumn;
}
hasLeadingComponent = true;
maxWidthInCurrColumn = 0;
rowIndex = startingRow;
currColumn.clear();
}
// how much vertical space does a component get?
int compHeight = Math.min(rowSpan * singleRowHeight
- gap / 4, coreComp.getPreferredSize().height);
int yNudge = rowSpan * singleRowHeight - compHeight;
int y = rowIndex * singleRowHeight + ins.top;
if (ltr) {
coreComp.setBounds(x, y + yNudge, prefWidth,
compHeight);
} else {
coreComp.setBounds(x - prefWidth, y + yNudge,
prefWidth, compHeight);
}
maxWidthInCurrColumn = Math.max(maxWidthInCurrColumn,
prefWidth);
currColumn.add(coreComp);
coreComp.putClientProperty(
AbstractBandControlPanelUI.TOP_ROW, Boolean
.valueOf(rowIndex == 0));
coreComp.putClientProperty(
AbstractBandControlPanelUI.MID_ROW, Boolean
.valueOf((rowIndex > 0)
&& (rowIndex < 2)));
coreComp.putClientProperty(
AbstractBandControlPanelUI.BOTTOM_ROW, Boolean
.valueOf(rowIndex == 2));
// scan the components in this column and make them to
// have the same width as the widest component in this
// column
for (JRibbonComponent comp : currColumn) {
Rectangle bounds = comp.getBounds();
if (ltr) {
comp.setBounds(bounds.x, bounds.y,
maxWidthInCurrColumn, bounds.height);
} else {
comp.setBounds(bounds.x + bounds.width
- maxWidthInCurrColumn, bounds.y,
maxWidthInCurrColumn, bounds.height);
}
comp.doLayout();
}
// System.out
// .println(rowSpan + ":" + coreComp.getBounds());
rowIndex += rowSpan;
}
if ((rowIndex > 0) && (rowIndex <= 3)) {
if (ltr) {
if (hasLeadingComponent)
x += gap;
x += maxWidthInCurrColumn;
} else {
if (hasLeadingComponent)
x -= gap;
x -= maxWidthInCurrColumn;
}
hasLeadingComponent = true;
}
} else {
// The galleries
for (RibbonElementPriority elementPriority : RibbonElementPriority
.values()) {
for (JRibbonGallery gallery : controlPanelGroup
.getRibbonGalleries(elementPriority)) {
int pw = gallery.getPreferredWidth(gallery
.getDisplayPriority(), availableHeight);
if (ltr) {
gallery.setBounds(x, ins.top, pw,
availableHeight);
if (hasLeadingComponent)
x += gap;
x += pw;
} else {
gallery.setBounds(x - pw, ins.top, pw,
availableHeight);
if (hasLeadingComponent)
x -= gap;
x -= pw;
}
hasLeadingComponent = true;
}
}
Map> buttonMap = new HashMap>();
for (RibbonElementPriority elementPriority : RibbonElementPriority
.values()) {
for (AbstractCommandButton commandButton : controlPanelGroup
.getRibbonButtons(elementPriority)) {
CommandButtonDisplayState state = commandButton
.getDisplayState();
if (buttonMap.get(state) == null) {
buttonMap.put(state,
new ArrayList());
}
buttonMap.get(state).add(commandButton);
}
}
List bigs = buttonMap
.get(CommandButtonDisplayState.BIG);
if (bigs != null) {
for (AbstractCommandButton bigButton : bigs) {
// Big buttons
int bigButtonWidth = bigButton.getPreferredSize().width;
if (hasLeadingComponent) {
if (ltr) {
x += gap;
} else {
x -= gap;
}
}
if (ltr) {
bigButton.setBounds(x, ins.top, bigButtonWidth,
availableHeight);
} else {
bigButton.setBounds(x - bigButtonWidth,
ins.top, bigButtonWidth,
availableHeight);
}
bigButton.putClientProperty(TOP_ROW, Boolean.FALSE);
bigButton.putClientProperty(MID_ROW, Boolean.FALSE);
bigButton.putClientProperty(BOTTOM_ROW,
Boolean.FALSE);
if (ltr) {
x += bigButtonWidth;
} else {
x -= bigButtonWidth;
}
hasLeadingComponent = true;
}
}
// Medium buttons
int vGap = gap * 3 / 4;
int medSmallButtonHeight = (availableHeight - 2 * vGap) / 3;
int index3 = 0;
int maxWidth3 = 0;
List mediums = buttonMap
.get(CommandButtonDisplayState.MEDIUM);
if (mediums != null) {
for (AbstractCommandButton mediumButton : mediums) {
int medWidth = mediumButton.getPreferredSize().width;
maxWidth3 = Math.max(maxWidth3, medWidth);
if (hasLeadingComponent && (index3 == 0)) {
if (ltr) {
x += gap;
} else {
x -= gap;
}
}
int buttonTop = (medSmallButtonHeight + vGap)
* index3;
int buttonBottom = (medSmallButtonHeight + vGap)
* (index3 + 1) - vGap;
if (ltr) {
mediumButton.setBounds(x, ins.top + buttonTop,
medWidth, buttonBottom - buttonTop);
} else {
mediumButton.setBounds(x - medWidth, ins.top
+ buttonTop, medWidth, buttonBottom
- buttonTop);
}
mediumButton.putClientProperty(TOP_ROW, Boolean
.valueOf(index3 == 0));
mediumButton.putClientProperty(MID_ROW, Boolean
.valueOf(index3 == 1));
mediumButton.putClientProperty(BOTTOM_ROW, Boolean
.valueOf(index3 == 2));
index3++;
if (index3 == 3) {
// last button in threesome
index3 = 0;
if (ltr) {
x += maxWidth3;
} else {
x -= maxWidth3;
}
hasLeadingComponent = true;
maxWidth3 = 0;
}
}
}
// at this point, maxWidth3 may be non-null. We can safely
// add it, since in this case there will be no buttons
// left in lowButtons
if (maxWidth3 > 0) {
if (ltr) {
x += maxWidth3;
} else {
x -= maxWidth3;
}
hasLeadingComponent = true;
}
index3 = 0;
maxWidth3 = 0;
List smalls = buttonMap
.get(CommandButtonDisplayState.SMALL);
if (smalls != null) {
for (AbstractCommandButton smallButton : smalls) {
int lowWidth = smallButton.getPreferredSize().width;
maxWidth3 = Math.max(maxWidth3, lowWidth);
if (hasLeadingComponent && (index3 == 0)) {
if (ltr) {
x += gap;
} else {
x -= gap;
}
}
int buttonTop = (medSmallButtonHeight + vGap)
* index3;
int buttonBottom = (medSmallButtonHeight + vGap)
* (index3 + 1) - vGap;
if (ltr) {
smallButton.setBounds(x, ins.top + buttonTop,
lowWidth, buttonBottom - buttonTop);
} else {
smallButton.setBounds(x - lowWidth, ins.top
+ buttonTop, lowWidth, buttonBottom
- buttonTop);
}
smallButton.putClientProperty(TOP_ROW, Boolean
.valueOf(index3 == 0));
smallButton.putClientProperty(MID_ROW, Boolean
.valueOf(index3 == 1));
smallButton.putClientProperty(BOTTOM_ROW, Boolean
.valueOf(index3 == 2));
index3++;
if (index3 == 3) {
// last button in threesome
index3 = 0;
if (ltr) {
x += maxWidth3;
} else {
x -= maxWidth3;
}
hasLeadingComponent = true;
maxWidth3 = 0;
}
}
}
if ((index3 < 3) && (maxWidth3 > 0)) {
if (ltr) {
x += maxWidth3;
} else {
x -= maxWidth3;
}
hasLeadingComponent = true;
}
}
// space for the separator
if (ltr) {
x += gap * 3 / 2;
} else {
x -= gap * 3 / 2;
}
controlPanelGroupIndex++;
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy