org.pushingpixels.substance.flamingo.ribbon.ui.SubstanceRibbonTaskToggleButtonUI Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of substance-flamingo Show documentation
Show all versions of substance-flamingo Show documentation
A fork of @kirilcool's substance project
The newest version!
/*
* Copyright (c) 2005-2010 Flamingo / Substance 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.substance.flamingo.ribbon.ui;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Map;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.border.Border;
import javax.swing.plaf.ComponentUI;
import org.pushingpixels.flamingo.api.common.AbstractCommandButton;
import org.pushingpixels.flamingo.api.ribbon.RibbonContextualTaskGroup;
import org.pushingpixels.flamingo.internal.ui.ribbon.BasicRibbonTaskToggleButtonUI;
import org.pushingpixels.flamingo.internal.ui.ribbon.JRibbonTaskToggleButton;
import org.pushingpixels.substance.api.*;
import org.pushingpixels.substance.api.shaper.SubstanceButtonShaper;
import org.pushingpixels.substance.flamingo.ribbon.RibbonBackgroundDelegate;
import org.pushingpixels.substance.flamingo.utils.CommandButtonVisualStateTracker;
import org.pushingpixels.substance.internal.animation.StateTransitionTracker;
import org.pushingpixels.substance.internal.animation.TransitionAwareUI;
import org.pushingpixels.substance.internal.painter.DecorationPainterUtils;
import org.pushingpixels.substance.internal.utils.*;
/**
* UI for {@link JRibbonTaskToggleButton} components in Substance look
* and feel.
*
* @author Kirill Grouchnikov
*/
public class SubstanceRibbonTaskToggleButtonUI extends
BasicRibbonTaskToggleButtonUI implements TransitionAwareUI {
/**
* Tracker for visual state transitions.
*/
protected CommandButtonVisualStateTracker substanceVisualStateTracker;
/**
* Property change listener on the button.
*/
private PropertyChangeListener substancePropertyChangeListener;
/*
* (non-Javadoc)
*
* @see javax.swing.plaf.ComponentUI#createUI(javax.swing.JComponent)
*/
public static ComponentUI createUI(JComponent comp) {
return new SubstanceRibbonTaskToggleButtonUI();
}
/**
* Painting delegate.
*/
private RibbonBackgroundDelegate delegate;
/**
* Simple constructor.
*/
public SubstanceRibbonTaskToggleButtonUI() {
this.delegate = new RibbonBackgroundDelegate();
}
@Override
protected void installDefaults() {
super.installDefaults();
this.commandButton.setOpaque(false);
this.commandButton.setBorder(new Border() {
@Override
public Insets getBorderInsets(Component c) {
return new Insets(0, 12, 0, 12);
}
@Override
public boolean isBorderOpaque() {
return false;
}
@Override
public void paintBorder(Component c, Graphics g, int x, int y,
int width, int height) {
}
});
SubstanceLookAndFeel.setDecorationType(this.commandButton,
DecorationAreaType.GENERAL);
this.commandButton.putClientProperty(
SubstanceLookAndFeel.COLORIZATION_FACTOR,
RibbonContextualTaskGroup.HUE_ALPHA);
}
@Override
protected void uninstallComponents() {
DecorationPainterUtils.clearDecorationType(this.commandButton);
super.uninstallDefaults();
}
@Override
protected void installListeners() {
super.installListeners();
this.substanceVisualStateTracker = new CommandButtonVisualStateTracker();
this.substanceVisualStateTracker.installListeners(this.commandButton);
this.substancePropertyChangeListener = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("contextualGroupHueColor".equals(evt.getPropertyName())) {
Color newValue = (Color) evt.getNewValue();
commandButton.setBackground(newValue);
}
}
};
this.commandButton
.addPropertyChangeListener(this.substancePropertyChangeListener);
}
@Override
protected void uninstallListeners() {
this.substanceVisualStateTracker.uninstallListeners(this.commandButton);
this.substanceVisualStateTracker = null;
this.commandButton
.removePropertyChangeListener(this.substancePropertyChangeListener);
this.substancePropertyChangeListener = null;
super.uninstallListeners();
}
/*
* (non-Javadoc)
*
* @see javax.swing.plaf.basic.BasicToggleButtonUI#paint(java.awt.Graphics,
* javax.swing.JComponent)
*/
@Override
public void paint(Graphics g, JComponent c) {
this.layoutInfo = this.layoutManager.getLayoutInfo(this.commandButton,
g);
this.delegate.updateTaskToggleButtonBackground(g,
(JRibbonTaskToggleButton) this.commandButton);
this.paintText(g);
}
/*
* (non-Javadoc)
*
* @see
* org.jvnet.flamingo.ribbon.ui.BasicToggleTabButtonUI#update(java.awt.Graphics
* , javax.swing.JComponent)
*/
@Override
public void update(Graphics g, JComponent c) {
this.paint(g, c);
}
/*
* (non-Javadoc)
*
* @see
* org.jvnet.flamingo.ribbon.ui.BasicRibbonTaskToggleButtonUI#paintText(
* java.awt.Graphics)
*/
@Override
protected void paintText(Graphics g) {
FontMetrics fm = g.getFontMetrics();
String toPaint = this.commandButton.getText();
// compute the insets
int fullInsets = this.commandButton.getInsets().left;
int pw = this.getPreferredSize(this.commandButton).width;
int mw = this.getMinimumSize(this.commandButton).width;
int w = this.commandButton.getWidth();
int h = this.commandButton.getHeight();
int insets = fullInsets - (pw - w) * (fullInsets - 2) / (pw - mw);
// and the text rectangle
Rectangle textRect = new Rectangle(insets,
1 + (h - fm.getHeight()) / 2, w - 2 * insets, fm.getHeight());
// show the first characters that fit into the available text rectangle
while (true) {
if (toPaint.length() == 0)
break;
int strWidth = fm.stringWidth(toPaint);
if (strWidth <= textRect.width)
break;
toPaint = toPaint.substring(0, toPaint.length() - 1);
}
int finalStrWidth = fm.stringWidth(toPaint);
if (finalStrWidth < textRect.width) {
int delta = textRect.width - finalStrWidth;
textRect.x += delta / 2;
textRect.width -= delta;
}
StateTransitionTracker.ModelStateInfo modelStateInfo = this.substanceVisualStateTracker
.getActionStateTransitionTracker().getModelStateInfo();
ComponentState currState = modelStateInfo.getCurrModelState();
float buttonAlpha = SubstanceColorSchemeUtilities.getAlpha(
this.commandButton, currState);
Color fgColor = getForegroundColor(this.commandButton, modelStateInfo);
if (buttonAlpha < 1.0f) {
Color bgFillColor = SubstanceColorUtilities
.getBackgroundFillColor(this.commandButton);
fgColor = SubstanceColorUtilities.getInterpolatedColor(fgColor,
bgFillColor, buttonAlpha);
}
SubstanceTextUtilities.paintText(g, this.commandButton, textRect,
toPaint, -1, this.commandButton.getFont(), fgColor, null);
}
private static Color getForegroundColor(AbstractCommandButton button,
StateTransitionTracker.ModelStateInfo modelStateInfo) {
ComponentState currState = modelStateInfo.getCurrModelState();
Map activeStates = modelStateInfo
.getStateContributionMap();
SubstanceColorScheme colorScheme = SubstanceColorSchemeUtilities
.getColorScheme(
button.isFlat() && currState == ComponentState.ENABLED ? button
.getParent() : button,
ColorSchemeAssociationKind.TAB, currState);
if (currState.isDisabled() || (activeStates == null)
|| (activeStates.size() == 1)) {
return colorScheme.getForegroundColor();
}
float aggrRed = 0;
float aggrGreen = 0;
float aggrBlue = 0;
for (Map.Entry activeEntry : activeStates
.entrySet()) {
ComponentState activeState = activeEntry.getKey();
float alpha = activeEntry.getValue().getContribution();
SubstanceColorScheme activeColorScheme = SubstanceColorSchemeUtilities
.getColorScheme(
button.isFlat()
&& activeState == ComponentState.ENABLED ? button
.getParent() : button,
ColorSchemeAssociationKind.TAB, activeState);
Color activeForeground = activeColorScheme.getForegroundColor();
aggrRed += alpha * activeForeground.getRed();
aggrGreen += alpha * activeForeground.getGreen();
aggrBlue += alpha * activeForeground.getBlue();
}
return new Color((int) aggrRed, (int) aggrGreen, (int) aggrBlue);
}
/*
* (non-Javadoc)
*
* @see
* javax.swing.plaf.ComponentUI#getPreferredSize(javax.swing.JComponent)
*/
@Override
public Dimension getPreferredSize(JComponent c) {
AbstractCommandButton button = (AbstractCommandButton) c;
SubstanceButtonShaper shaper = SubstanceCoreUtilities
.getButtonShaper(button);
Dimension superPref = super.getPreferredSize(button);
if (superPref == null)
return null;
if (shaper == null)
return superPref;
JButton dummy = new JButton(button.getText(), button.getIcon());
return shaper.getPreferredSize(dummy, superPref);
}
@Override
public StateTransitionTracker getTransitionTracker() {
return this.substanceVisualStateTracker
.getActionStateTransitionTracker();
}
@Override
public boolean isInside(MouseEvent me) {
return true;
}
}