mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-10 20:37:30 -04:00
Animations on buttons and comboboxes
This commit is contained in:
parent
d8086b7337
commit
61afad30c8
@ -17,7 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.jackhuang.hmcl.util.ui;
|
package org.jackhuang.hmcl.util.ui;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import javax.swing.JFileChooser;
|
import javax.swing.JFileChooser;
|
||||||
import javax.swing.LookAndFeel;
|
import javax.swing.LookAndFeel;
|
||||||
|
@ -17,14 +17,13 @@ import java.awt.Dimension;
|
|||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import java.awt.Rectangle;
|
|
||||||
|
|
||||||
import javax.swing.AbstractButton;
|
import javax.swing.AbstractButton;
|
||||||
import javax.swing.ButtonModel;
|
import javax.swing.ButtonModel;
|
||||||
|
import javax.swing.JButton;
|
||||||
import javax.swing.JCheckBox;
|
import javax.swing.JCheckBox;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JRadioButton;
|
import javax.swing.JRadioButton;
|
||||||
import javax.swing.JToggleButton;
|
|
||||||
import javax.swing.JToolBar;
|
import javax.swing.JToolBar;
|
||||||
import javax.swing.LookAndFeel;
|
import javax.swing.LookAndFeel;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
@ -36,9 +35,13 @@ import javax.swing.plaf.InsetsUIResource;
|
|||||||
import javax.swing.plaf.UIResource;
|
import javax.swing.plaf.UIResource;
|
||||||
import javax.swing.plaf.basic.BasicButtonUI;
|
import javax.swing.plaf.basic.BasicButtonUI;
|
||||||
import javax.swing.text.JTextComponent;
|
import javax.swing.text.JTextComponent;
|
||||||
import org.jackhuang.hmcl.laf.BEUtils;
|
import org.jackhuang.hmcl.laf.utils.AnimationController;
|
||||||
|
|
||||||
import org.jackhuang.hmcl.laf.utils.Icon9Factory;
|
import org.jackhuang.hmcl.laf.utils.Icon9Factory;
|
||||||
|
import org.jackhuang.hmcl.laf.utils.Skin;
|
||||||
|
import org.jackhuang.hmcl.laf.utils.TMSchema;
|
||||||
|
import org.jackhuang.hmcl.laf.utils.TMSchema.Part;
|
||||||
|
import org.jackhuang.hmcl.laf.utils.TMSchema.State;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JButton的UI实现类.
|
* JButton的UI实现类.
|
||||||
@ -47,7 +50,7 @@ import org.jackhuang.hmcl.laf.utils.Icon9Factory;
|
|||||||
* @version 1.0
|
* @version 1.0
|
||||||
* @see com.sun.java.swing.plaf.windows.WindowsButtonUI
|
* @see com.sun.java.swing.plaf.windows.WindowsButtonUI
|
||||||
*/
|
*/
|
||||||
public class BEButtonUI extends BasicButtonUI {
|
public class BEButtonUI extends BasicButtonUI implements Skin {
|
||||||
|
|
||||||
private static final Icon9Factory ICON_9 = new Icon9Factory("button");
|
private static final Icon9Factory ICON_9 = new Icon9Factory("button");
|
||||||
|
|
||||||
@ -130,29 +133,6 @@ public class BEButtonUI extends BasicButtonUI {
|
|||||||
return focusColor;
|
return focusColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ********************************
|
|
||||||
// Paint Methods
|
|
||||||
// ********************************
|
|
||||||
@Override
|
|
||||||
protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, Rectangle textRect, Rectangle iconRect) {
|
|
||||||
// focus painted same color as text on Basic??
|
|
||||||
int width = b.getWidth();
|
|
||||||
int height = b.getHeight();
|
|
||||||
g.setColor(getFocusColor());
|
|
||||||
|
|
||||||
//** modified by jb2011:绘制虚线方法改成可以设置虚线步进的方法,步进设为2则更好看一点
|
|
||||||
// BasicGraphicsUtils.drawDashedRect(g, dashedRectGapX, dashedRectGapY,
|
|
||||||
// width - dashedRectGapWidth, height - dashedRectGapHeight);
|
|
||||||
// 绘制虚线框
|
|
||||||
BEUtils.drawDashedRect(g, dashedRectGapX, dashedRectGapY,
|
|
||||||
width - dashedRectGapWidth, height - dashedRectGapHeight);
|
|
||||||
// 绘制虚线框的半透明白色立体阴影(半透明的用处在于若隐若现的效果比纯白要来的柔和的多)
|
|
||||||
g.setColor(new Color(255, 255, 255, 50));
|
|
||||||
// 立体阴影就是向右下偏移一个像素实现的
|
|
||||||
BEUtils.drawDashedRect(g, dashedRectGapX + 1, dashedRectGapY + 1,
|
|
||||||
width - dashedRectGapWidth, height - dashedRectGapHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ********************************
|
// ********************************
|
||||||
// Layout Methods
|
// Layout Methods
|
||||||
// ********************************
|
// ********************************
|
||||||
@ -223,7 +203,7 @@ public class BEButtonUI extends BasicButtonUI {
|
|||||||
dh -= (insets.top + insets.bottom);
|
dh -= (insets.top + insets.bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (toolbar)
|
/*if (toolbar)
|
||||||
//此状态下JToggleButton和JButton使用各自的背景实现,2012-10-16前无论是不是JToggleButton都是使用该种实是不太合理的
|
//此状态下JToggleButton和JButton使用各自的背景实现,2012-10-16前无论是不是JToggleButton都是使用该种实是不太合理的
|
||||||
if (model.isRollover() || model.isPressed())
|
if (model.isRollover() || model.isPressed())
|
||||||
if (c instanceof JToggleButton)
|
if (c instanceof JToggleButton)
|
||||||
@ -248,8 +228,103 @@ public class BEButtonUI extends BasicButtonUI {
|
|||||||
else
|
else
|
||||||
key = "normal";
|
key = "normal";
|
||||||
ICON_9.get(key).draw((Graphics2D) g, dx, dy, dw, dh);
|
ICON_9.get(key).draw((Graphics2D) g, dx, dy, dw, dh);
|
||||||
|
}*/
|
||||||
|
AnimationController.paintSkin(c, INSTANCE, g, dx, dy, dw, dh, getXPButtonState(b));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Part getPart(JComponent c) {
|
||||||
|
return getXPButtonType((AbstractButton) c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Part getXPButtonType(AbstractButton b) {
|
||||||
|
if (b instanceof JCheckBox)
|
||||||
|
return Part.BP_CHECKBOX;
|
||||||
|
if (b instanceof JRadioButton)
|
||||||
|
return Part.BP_RADIOBUTTON;
|
||||||
|
boolean toolbar = (b.getParent() instanceof JToolBar);
|
||||||
|
return toolbar ? Part.TP_BUTTON : Part.BP_PUSHBUTTON;
|
||||||
|
}
|
||||||
|
|
||||||
|
static State getXPButtonState(AbstractButton b) {
|
||||||
|
Part part = getXPButtonType(b);
|
||||||
|
ButtonModel model = b.getModel();
|
||||||
|
State state = State.NORMAL;
|
||||||
|
switch (part) {
|
||||||
|
case BP_RADIOBUTTON:
|
||||||
|
case BP_CHECKBOX:
|
||||||
|
if (!model.isEnabled())
|
||||||
|
state = (model.isSelected()) ? State.CHECKEDDISABLED
|
||||||
|
: State.UNCHECKEDDISABLED;
|
||||||
|
else if (model.isPressed() && model.isArmed())
|
||||||
|
state = (model.isSelected()) ? State.CHECKEDPRESSED
|
||||||
|
: State.UNCHECKEDPRESSED;
|
||||||
|
else if (model.isRollover())
|
||||||
|
state = (model.isSelected()) ? State.CHECKEDHOT
|
||||||
|
: State.UNCHECKEDHOT;
|
||||||
|
else
|
||||||
|
state = (model.isSelected()) ? State.CHECKEDNORMAL
|
||||||
|
: State.UNCHECKEDNORMAL;
|
||||||
|
break;
|
||||||
|
case BP_PUSHBUTTON:
|
||||||
|
case TP_BUTTON:
|
||||||
|
boolean toolbar = (b.getParent() instanceof JToolBar);
|
||||||
|
if (toolbar) {
|
||||||
|
if (model.isArmed() && model.isPressed())
|
||||||
|
state = State.PRESSED;
|
||||||
|
else if (!model.isEnabled())
|
||||||
|
state = State.DISABLED;
|
||||||
|
else if (model.isSelected() && model.isRollover())
|
||||||
|
state = State.HOTCHECKED;
|
||||||
|
else if (model.isSelected())
|
||||||
|
state = State.CHECKED;
|
||||||
|
else if (model.isRollover())
|
||||||
|
state = State.HOT;
|
||||||
|
else if (b.hasFocus())
|
||||||
|
state = State.HOT;
|
||||||
|
} else
|
||||||
|
if ((model.isArmed() && model.isPressed())
|
||||||
|
|| model.isSelected())
|
||||||
|
state = State.PRESSED;
|
||||||
|
else if (!model.isEnabled())
|
||||||
|
state = State.DISABLED;
|
||||||
|
else if (model.isRollover() || model.isPressed())
|
||||||
|
state = State.HOT;
|
||||||
|
else if (b instanceof JButton
|
||||||
|
&& ((JButton) b).isDefaultButton())
|
||||||
|
state = State.DEFAULTED;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
state = State.NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paintSkinRaw(Graphics g, int dx, int dy, int dw, int dh, TMSchema.State state) {
|
||||||
|
String key;
|
||||||
|
switch (state) {
|
||||||
|
case SELECTED:
|
||||||
|
key = "selected";
|
||||||
|
break;
|
||||||
|
case PRESSED:
|
||||||
|
key = "pressed";
|
||||||
|
break;
|
||||||
|
case DISABLED:
|
||||||
|
key = "disabled";
|
||||||
|
break;
|
||||||
|
case HOT:
|
||||||
|
key = "rollover";
|
||||||
|
break;
|
||||||
|
case NORMAL:
|
||||||
|
key = "normal";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ICON_9.get(key).draw((Graphics2D) g, dx, dy, dw, dh);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,7 +37,11 @@ import javax.swing.plaf.basic.BasicComboBoxEditor;
|
|||||||
import javax.swing.plaf.basic.BasicComboBoxUI;
|
import javax.swing.plaf.basic.BasicComboBoxUI;
|
||||||
import javax.swing.plaf.basic.BasicComboPopup;
|
import javax.swing.plaf.basic.BasicComboPopup;
|
||||||
import javax.swing.plaf.basic.ComboPopup;
|
import javax.swing.plaf.basic.ComboPopup;
|
||||||
|
import org.jackhuang.hmcl.laf.utils.AnimationController;
|
||||||
import org.jackhuang.hmcl.laf.utils.Icon9Factory;
|
import org.jackhuang.hmcl.laf.utils.Icon9Factory;
|
||||||
|
import org.jackhuang.hmcl.laf.utils.Skin;
|
||||||
|
import org.jackhuang.hmcl.laf.utils.TMSchema;
|
||||||
|
import org.jackhuang.hmcl.laf.utils.TMSchema.State;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JComboBox的UI实现类.
|
* JComboBox的UI实现类.
|
||||||
@ -47,7 +51,7 @@ import org.jackhuang.hmcl.laf.utils.Icon9Factory;
|
|||||||
* @see com.sun.java.swing.plaf.windows.WindowsComboBoxUI
|
* @see com.sun.java.swing.plaf.windows.WindowsComboBoxUI
|
||||||
*/
|
*/
|
||||||
public class BEComboBoxUI extends BasicComboBoxUI
|
public class BEComboBoxUI extends BasicComboBoxUI
|
||||||
implements org.jackhuang.hmcl.laf.BeautyEyeLNFHelper.__UseParentPaintSurported, MouseListener {
|
implements org.jackhuang.hmcl.laf.BeautyEyeLNFHelper.__UseParentPaintSurported, MouseListener, Skin {
|
||||||
|
|
||||||
private static final Icon9Factory ICON_9 = new Icon9Factory("combo");
|
private static final Icon9Factory ICON_9 = new Icon9Factory("combo");
|
||||||
private static final Dimension BTN_SIZE = new Dimension(17, 20);
|
private static final Dimension BTN_SIZE = new Dimension(17, 20);
|
||||||
@ -164,10 +168,50 @@ public class BEComboBoxUI extends BasicComboBoxUI
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void paintCurrentValueBackground(Graphics g, Rectangle bounds, boolean hasFocus) {
|
public void paintCurrentValueBackground(Graphics g, Rectangle bounds, boolean hasFocus) {
|
||||||
ICON_9.getWithComboState("", comboBox.isEnabled(), mouseDown, mouseInside)
|
AnimationController.paintSkin(comboBox, this, g, bounds.x, bounds.y, bounds.width, bounds.height, getXPComboBoxState(comboBox));
|
||||||
.draw((Graphics2D) g, bounds.x, bounds.y, bounds.width, bounds.height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TMSchema.Part getPart(JComponent c) {
|
||||||
|
return TMSchema.Part.CP_COMBOBOX;
|
||||||
|
}
|
||||||
|
|
||||||
|
State getXPComboBoxState(JComponent c) {
|
||||||
|
State state = State.NORMAL;
|
||||||
|
if (!c.isEnabled()) {
|
||||||
|
state = State.DISABLED;
|
||||||
|
} else if (isPopupVisible(comboBox)) {
|
||||||
|
state = State.PRESSED;
|
||||||
|
} else if (mouseInside) {
|
||||||
|
state = State.HOT;
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paintSkinRaw(Graphics g, int x, int y, int w, int h, TMSchema.State state) {
|
||||||
|
String key;
|
||||||
|
switch (state) {
|
||||||
|
case PRESSED:
|
||||||
|
key = "pressed";
|
||||||
|
break;
|
||||||
|
case DISABLED:
|
||||||
|
key = "disabled";
|
||||||
|
break;
|
||||||
|
case HOT:
|
||||||
|
key = "rollover";
|
||||||
|
break;
|
||||||
|
case NORMAL:
|
||||||
|
key = "normal";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ICON_9.get(key).draw((Graphics2D) g, x, y, w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//* copy from BasicComboBoxUI and modified by jb2011
|
//* copy from BasicComboBoxUI and modified by jb2011
|
||||||
/**
|
/**
|
||||||
* Creates the default renderer that will be used in a non-editiable combo
|
* Creates the default renderer that will be used in a non-editiable combo
|
||||||
|
@ -149,10 +149,8 @@ public class TranslucentPopupFactory extends PopupFactory {
|
|||||||
Component c = getComponent();
|
Component c = getComponent();
|
||||||
Window window = SwingUtilities.getWindowAncestor(c);
|
Window window = SwingUtilities.getWindowAncestor(c);
|
||||||
|
|
||||||
if (c instanceof JWindow) {
|
if (c instanceof JWindow)
|
||||||
((Window) c).dispose();
|
((Window) c).dispose();
|
||||||
c = null;
|
|
||||||
}
|
|
||||||
// If our parent is a DefaultFrame, we need to dispose it, too.
|
// If our parent is a DefaultFrame, we need to dispose it, too.
|
||||||
if (window instanceof DefaultFrame)
|
if (window instanceof DefaultFrame)
|
||||||
window.dispose();
|
window.dispose();
|
||||||
|
@ -0,0 +1,383 @@
|
|||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher.
|
||||||
|
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||||
|
*/
|
||||||
|
package org.jackhuang.hmcl.laf.utils;
|
||||||
|
|
||||||
|
import java.awt.AlphaComposite;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.beans.PropertyChangeEvent;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
import javax.swing.Timer;
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
import org.jackhuang.hmcl.laf.BeautyEyeLookAndFeel;
|
||||||
|
|
||||||
|
import org.jackhuang.hmcl.laf.utils.TMSchema.State;
|
||||||
|
import static org.jackhuang.hmcl.laf.utils.TMSchema.State.*;
|
||||||
|
import org.jackhuang.hmcl.laf.utils.TMSchema.Part;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class to help mimic Vista theme animations. The only kind of
|
||||||
|
* animation it handles for now is 'transition' animation (this seems
|
||||||
|
* to be the only animation which Vista theme can do). This is when
|
||||||
|
* one picture fadein over another one in some period of time.
|
||||||
|
* According to
|
||||||
|
* https://connect.microsoft.com/feedback/ViewFeedback.aspx?FeedbackID=86852&SiteID=4
|
||||||
|
* The animations are all linear.
|
||||||
|
*
|
||||||
|
* This class has a number of responsibilities.
|
||||||
|
* <ul>
|
||||||
|
* <li> It trigger rapaint for the UI components involved in the animation
|
||||||
|
* <li> It tracks the animation state for every UI component involved in the
|
||||||
|
* animation and paints {@code Skin} in new {@code State} over the
|
||||||
|
* {@code Skin} in last {@code State} using
|
||||||
|
* {@code AlphaComposite.SrcOver.derive(alpha)} where {code alpha}
|
||||||
|
* depends on the state of animation
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @author Igor Kushnirskiy
|
||||||
|
*/
|
||||||
|
public class AnimationController implements ActionListener, PropertyChangeListener {
|
||||||
|
|
||||||
|
private static AnimationController INSTANCE = new AnimationController();
|
||||||
|
private static final String ANIMATION_CONTROLLER_KEY = "BeautyEye.AnimationController";
|
||||||
|
private final Map<JComponent, Map<Part, AnimationState>> animationStateMap
|
||||||
|
= new WeakHashMap<>();
|
||||||
|
|
||||||
|
//this timer is used to cause repaint on animated components
|
||||||
|
//30 repaints per second should give smooth animation affect
|
||||||
|
private final Timer timer = new Timer(1000 / 30, this);
|
||||||
|
|
||||||
|
private static synchronized AnimationController getAnimationController(JComponent c) {
|
||||||
|
if (c.getClientProperty(ANIMATION_CONTROLLER_KEY) == null)
|
||||||
|
c.putClientProperty(ANIMATION_CONTROLLER_KEY, new AnimationController());
|
||||||
|
return (AnimationController) c.getClientProperty(ANIMATION_CONTROLLER_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private AnimationController() {
|
||||||
|
timer.setRepeats(true);
|
||||||
|
timer.setCoalesce(true);
|
||||||
|
//we need to dispose the controller on l&f change
|
||||||
|
UIManager.addPropertyChangeListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void triggerAnimation(JComponent c,
|
||||||
|
Part part, State newState) {
|
||||||
|
if (c instanceof javax.swing.JTabbedPane
|
||||||
|
|| part == Part.TP_BUTTON)
|
||||||
|
//idk: we can not handle tabs animation because
|
||||||
|
//the same (component,part) is used to handle all the tabs
|
||||||
|
//and we can not track the states
|
||||||
|
//Vista theme might have transition duration for toolbar buttons
|
||||||
|
//but native application does not seem to animate them
|
||||||
|
return;
|
||||||
|
AnimationController controller
|
||||||
|
= AnimationController.getAnimationController(c);
|
||||||
|
State oldState = controller.getState(c, part);
|
||||||
|
if (oldState != newState) {
|
||||||
|
controller.putState(c, part, newState);
|
||||||
|
if (newState == State.DEFAULTED)
|
||||||
|
// it seems for DEFAULTED button state Vista does animation from
|
||||||
|
// HOT
|
||||||
|
oldState = State.HOT;
|
||||||
|
if (oldState != null) {
|
||||||
|
long duration;
|
||||||
|
//if (newState == State.DEFAULTED) {
|
||||||
|
//Only button might have DEFAULTED state
|
||||||
|
//idk: do not know how to get the value from Vista
|
||||||
|
//one second seems plausible value
|
||||||
|
duration = 500;
|
||||||
|
/*} else {
|
||||||
|
XPStyle xp = XPStyle.getXP();
|
||||||
|
duration = (xp != null)
|
||||||
|
? xp.getThemeTransitionDuration(
|
||||||
|
c, part,
|
||||||
|
normalizeState(oldState),
|
||||||
|
normalizeState(newState),
|
||||||
|
Prop.TRANSITIONDURATIONS)
|
||||||
|
: 1000;
|
||||||
|
}*/
|
||||||
|
controller.startAnimation(c, part, oldState, newState, duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// for scrollbar up, down, left and right button pictures are
|
||||||
|
// defined by states. It seems that theme has duration defined
|
||||||
|
// only for up button states thus we doing this translation here.
|
||||||
|
private static State normalizeState(State state) {
|
||||||
|
State rv;
|
||||||
|
switch (state) {
|
||||||
|
case DOWNPRESSED:
|
||||||
|
case LEFTPRESSED:
|
||||||
|
case RIGHTPRESSED:
|
||||||
|
rv = UPPRESSED;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DOWNDISABLED:
|
||||||
|
case LEFTDISABLED:
|
||||||
|
case RIGHTDISABLED:
|
||||||
|
rv = UPDISABLED;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DOWNHOT:
|
||||||
|
case LEFTHOT:
|
||||||
|
case RIGHTHOT:
|
||||||
|
rv = UPHOT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DOWNNORMAL:
|
||||||
|
case LEFTNORMAL:
|
||||||
|
case RIGHTNORMAL:
|
||||||
|
rv = UPNORMAL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
rv = state;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized State getState(JComponent component, Part part) {
|
||||||
|
State rv = null;
|
||||||
|
Object tmpObject
|
||||||
|
= component.getClientProperty(PartUIClientPropertyKey.getKey(part));
|
||||||
|
if (tmpObject instanceof State)
|
||||||
|
rv = (State) tmpObject;
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void putState(JComponent component, Part part,
|
||||||
|
State state) {
|
||||||
|
component.putClientProperty(PartUIClientPropertyKey.getKey(part),
|
||||||
|
state);
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void startAnimation(JComponent component,
|
||||||
|
Part part,
|
||||||
|
State startState,
|
||||||
|
State endState,
|
||||||
|
long millis) {
|
||||||
|
boolean isForwardAndReverse = false;
|
||||||
|
if (endState == State.DEFAULTED)
|
||||||
|
isForwardAndReverse = true;
|
||||||
|
Map<Part, AnimationState> map = animationStateMap.get(component);
|
||||||
|
if (millis <= 0) {
|
||||||
|
if (map != null) {
|
||||||
|
map.remove(part);
|
||||||
|
if (map.isEmpty())
|
||||||
|
animationStateMap.remove(component);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (map == null) {
|
||||||
|
map = new EnumMap<>(Part.class);
|
||||||
|
animationStateMap.put(component, map);
|
||||||
|
}
|
||||||
|
map.put(part,
|
||||||
|
new AnimationState(startState, millis, isForwardAndReverse));
|
||||||
|
if (!timer.isRunning())
|
||||||
|
timer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void paintSkin(JComponent component, Skin skin,
|
||||||
|
Graphics g, int dx, int dy, int dw, int dh, State state) {
|
||||||
|
triggerAnimation(component, skin.getPart(component), state);
|
||||||
|
AnimationController controller = getAnimationController(component);
|
||||||
|
synchronized (controller) {
|
||||||
|
AnimationState animationState = null;
|
||||||
|
Map<Part, AnimationState> map
|
||||||
|
= controller.animationStateMap.get(component);
|
||||||
|
if (map != null)
|
||||||
|
animationState = map.get(skin.getPart(component));
|
||||||
|
if (animationState != null)
|
||||||
|
animationState.paintSkin(skin, g, dx, dy, dw, dh, state);
|
||||||
|
else
|
||||||
|
skin.paintSkinRaw(g, dx, dy, dw, dh, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void propertyChange(PropertyChangeEvent e) {
|
||||||
|
if ("lookAndFeel".equals(e.getPropertyName())
|
||||||
|
&& !(e.getNewValue() instanceof BeautyEyeLookAndFeel))
|
||||||
|
dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void actionPerformed(ActionEvent e) {
|
||||||
|
java.util.List<JComponent> componentsToRemove = null;
|
||||||
|
java.util.List<Part> partsToRemove = null;
|
||||||
|
for (JComponent component : animationStateMap.keySet()) {
|
||||||
|
component.repaint();
|
||||||
|
if (partsToRemove != null)
|
||||||
|
partsToRemove.clear();
|
||||||
|
Map<Part, AnimationState> map = animationStateMap.get(component);
|
||||||
|
if (!component.isShowing()
|
||||||
|
|| map == null
|
||||||
|
|| map.isEmpty()) {
|
||||||
|
if (componentsToRemove == null)
|
||||||
|
componentsToRemove = new ArrayList<>();
|
||||||
|
componentsToRemove.add(component);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (Part part : map.keySet())
|
||||||
|
if (map.get(part).isDone()) {
|
||||||
|
if (partsToRemove == null)
|
||||||
|
partsToRemove = new ArrayList<>();
|
||||||
|
partsToRemove.add(part);
|
||||||
|
}
|
||||||
|
if (partsToRemove != null)
|
||||||
|
if (partsToRemove.size() == map.size()) {
|
||||||
|
//animation is done for the component
|
||||||
|
if (componentsToRemove == null)
|
||||||
|
componentsToRemove = new ArrayList<>();
|
||||||
|
componentsToRemove.add(component);
|
||||||
|
} else
|
||||||
|
for (Part part : partsToRemove)
|
||||||
|
map.remove(part);
|
||||||
|
}
|
||||||
|
if (componentsToRemove != null)
|
||||||
|
for (JComponent component : componentsToRemove)
|
||||||
|
animationStateMap.remove(component);
|
||||||
|
if (animationStateMap.isEmpty())
|
||||||
|
timer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void dispose() {
|
||||||
|
timer.stop();
|
||||||
|
UIManager.removePropertyChangeListener(this);
|
||||||
|
INSTANCE = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class AnimationState {
|
||||||
|
|
||||||
|
private final State startState;
|
||||||
|
|
||||||
|
//animation duration in nanoseconds
|
||||||
|
private final long duration;
|
||||||
|
|
||||||
|
//animatin start time in nanoseconds
|
||||||
|
private long startTime;
|
||||||
|
|
||||||
|
//direction the alpha value is changing
|
||||||
|
//forward - from 0 to 1
|
||||||
|
//!forward - from 1 to 0
|
||||||
|
private boolean isForward = true;
|
||||||
|
|
||||||
|
//if isForwardAndReverse the animation continually goes
|
||||||
|
//forward and reverse. alpha value is changing from 0 to 1 then
|
||||||
|
//from 1 to 0 and so forth
|
||||||
|
private final boolean isForwardAndReverse;
|
||||||
|
|
||||||
|
private float progress;
|
||||||
|
|
||||||
|
AnimationState(final State startState,
|
||||||
|
final long milliseconds,
|
||||||
|
boolean isForwardAndReverse) {
|
||||||
|
assert startState != null && milliseconds > 0;
|
||||||
|
assert SwingUtilities.isEventDispatchThread();
|
||||||
|
|
||||||
|
this.startState = startState;
|
||||||
|
this.duration = milliseconds * 1000000;
|
||||||
|
this.startTime = System.nanoTime();
|
||||||
|
this.isForwardAndReverse = isForwardAndReverse;
|
||||||
|
progress = 0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateProgress() {
|
||||||
|
assert SwingUtilities.isEventDispatchThread();
|
||||||
|
|
||||||
|
if (isDone())
|
||||||
|
return;
|
||||||
|
long currentTime = System.nanoTime();
|
||||||
|
|
||||||
|
progress = ((float) (currentTime - startTime))
|
||||||
|
/ duration;
|
||||||
|
progress = Math.max(progress, 0); //in case time was reset
|
||||||
|
if (progress >= 1) {
|
||||||
|
progress = 1;
|
||||||
|
if (isForwardAndReverse) {
|
||||||
|
startTime = currentTime;
|
||||||
|
progress = 0;
|
||||||
|
isForward = !isForward;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void paintSkin(Skin skin, Graphics _g,
|
||||||
|
int dx, int dy, int dw, int dh, State state) {
|
||||||
|
assert SwingUtilities.isEventDispatchThread();
|
||||||
|
|
||||||
|
updateProgress();
|
||||||
|
if (!isDone()) {
|
||||||
|
Graphics2D g = (Graphics2D) _g.create();
|
||||||
|
skin.paintSkinRaw(g, dx, dy, dw, dh, startState);
|
||||||
|
float alpha;
|
||||||
|
if (isForward)
|
||||||
|
alpha = progress;
|
||||||
|
else
|
||||||
|
alpha = 1 - progress;
|
||||||
|
g.setComposite(AlphaComposite.SrcOver.derive(alpha));
|
||||||
|
skin.paintSkinRaw(g, dx, dy, dw, dh, state);
|
||||||
|
g.dispose();
|
||||||
|
} else
|
||||||
|
skin.paintSkinRaw(_g, dx, dy, dw, dh, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isDone() {
|
||||||
|
assert SwingUtilities.isEventDispatchThread();
|
||||||
|
|
||||||
|
return progress >= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class PartUIClientPropertyKey {
|
||||||
|
|
||||||
|
private static final Map<Part, PartUIClientPropertyKey> MAP
|
||||||
|
= new EnumMap<>(Part.class);
|
||||||
|
|
||||||
|
static synchronized PartUIClientPropertyKey getKey(Part part) {
|
||||||
|
PartUIClientPropertyKey rv = MAP.get(part);
|
||||||
|
if (rv == null) {
|
||||||
|
rv = new PartUIClientPropertyKey(part);
|
||||||
|
MAP.put(part, rv);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Part part;
|
||||||
|
|
||||||
|
private PartUIClientPropertyKey(Part part) {
|
||||||
|
this.part = part;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return part.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
31
HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/Skin.java
Normal file
31
HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/Skin.java
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher.
|
||||||
|
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||||
|
*/
|
||||||
|
package org.jackhuang.hmcl.laf.utils;
|
||||||
|
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author huang
|
||||||
|
*/
|
||||||
|
public interface Skin {
|
||||||
|
void paintSkinRaw(Graphics g, int x, int y, int w, int h, TMSchema.State state);
|
||||||
|
|
||||||
|
TMSchema.Part getPart(JComponent c);
|
||||||
|
}
|
580
HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/TMSchema.java
Normal file
580
HMCLaF/src/main/java/org/jackhuang/hmcl/laf/utils/TMSchema.java
Normal file
@ -0,0 +1,580 @@
|
|||||||
|
/*
|
||||||
|
* Hello Minecraft! Launcher.
|
||||||
|
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||||
|
*/
|
||||||
|
package org.jackhuang.hmcl.laf.utils;
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* <p>These classes are designed to be used while the
|
||||||
|
* corresponding <code>LookAndFeel</code> class has been installed
|
||||||
|
* (<code>UIManager.setLookAndFeel(new <i>XXX</i>LookAndFeel())</code>).
|
||||||
|
* Using them while a different <code>LookAndFeel</code> is installed
|
||||||
|
* may produce unexpected results, including exceptions.
|
||||||
|
* Additionally, changing the <code>LookAndFeel</code>
|
||||||
|
* maintained by the <code>UIManager</code> without updating the
|
||||||
|
* corresponding <code>ComponentUI</code> of any
|
||||||
|
* <code>JComponent</code>s may also produce unexpected results,
|
||||||
|
* such as the wrong colors showing up, and is generally not
|
||||||
|
* encouraged.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements Windows Parts and their States and Properties for the Windows Look and Feel.
|
||||||
|
*
|
||||||
|
* See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/userex/topics/partsandstates.asp
|
||||||
|
* See tmschema.h (or vssym32.h & vsstyle.h for MS Vista)
|
||||||
|
*
|
||||||
|
* @author Leif Samuelsson
|
||||||
|
*/
|
||||||
|
public class TMSchema {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An enumeration of the various Windows controls (also known as
|
||||||
|
* components, or top-level parts)
|
||||||
|
*/
|
||||||
|
public static enum Control {
|
||||||
|
BUTTON,
|
||||||
|
COMBOBOX,
|
||||||
|
EDIT,
|
||||||
|
HEADER,
|
||||||
|
LISTBOX,
|
||||||
|
LISTVIEW,
|
||||||
|
MENU,
|
||||||
|
PROGRESS,
|
||||||
|
REBAR,
|
||||||
|
SCROLLBAR,
|
||||||
|
SPIN,
|
||||||
|
TAB,
|
||||||
|
TOOLBAR,
|
||||||
|
TRACKBAR,
|
||||||
|
TREEVIEW,
|
||||||
|
WINDOW
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An enumeration of the Windows compoent parts
|
||||||
|
*/
|
||||||
|
public static enum Part {
|
||||||
|
MENU (Control.MENU, 0), // Special case, not in native
|
||||||
|
MP_BARBACKGROUND (Control.MENU, 7),
|
||||||
|
MP_BARITEM (Control.MENU, 8),
|
||||||
|
MP_POPUPBACKGROUND (Control.MENU, 9),
|
||||||
|
MP_POPUPBORDERS (Control.MENU, 10),
|
||||||
|
MP_POPUPCHECK (Control.MENU, 11),
|
||||||
|
MP_POPUPCHECKBACKGROUND (Control.MENU, 12),
|
||||||
|
MP_POPUPGUTTER (Control.MENU, 13),
|
||||||
|
MP_POPUPITEM (Control.MENU, 14),
|
||||||
|
MP_POPUPSEPARATOR (Control.MENU, 15),
|
||||||
|
MP_POPUPSUBMENU (Control.MENU, 16),
|
||||||
|
|
||||||
|
BP_PUSHBUTTON (Control.BUTTON, 1),
|
||||||
|
BP_RADIOBUTTON(Control.BUTTON, 2),
|
||||||
|
BP_CHECKBOX (Control.BUTTON, 3),
|
||||||
|
BP_GROUPBOX (Control.BUTTON, 4),
|
||||||
|
|
||||||
|
CP_COMBOBOX (Control.COMBOBOX, 0),
|
||||||
|
CP_DROPDOWNBUTTON(Control.COMBOBOX, 1),
|
||||||
|
CP_BACKGROUND (Control.COMBOBOX, 2),
|
||||||
|
CP_TRANSPARENTBACKGROUND (Control.COMBOBOX, 3),
|
||||||
|
CP_BORDER (Control.COMBOBOX, 4),
|
||||||
|
CP_READONLY (Control.COMBOBOX, 5),
|
||||||
|
CP_DROPDOWNBUTTONRIGHT (Control.COMBOBOX, 6),
|
||||||
|
CP_DROPDOWNBUTTONLEFT (Control.COMBOBOX, 7),
|
||||||
|
CP_CUEBANNER (Control.COMBOBOX, 8),
|
||||||
|
|
||||||
|
|
||||||
|
EP_EDIT (Control.EDIT, 0),
|
||||||
|
EP_EDITTEXT(Control.EDIT, 1),
|
||||||
|
|
||||||
|
HP_HEADERITEM(Control.HEADER, 1),
|
||||||
|
HP_HEADERSORTARROW(Control.HEADER, 4),
|
||||||
|
|
||||||
|
LBP_LISTBOX(Control.LISTBOX, 0),
|
||||||
|
|
||||||
|
LVP_LISTVIEW(Control.LISTVIEW, 0),
|
||||||
|
|
||||||
|
PP_PROGRESS (Control.PROGRESS, 0),
|
||||||
|
PP_BAR (Control.PROGRESS, 1),
|
||||||
|
PP_BARVERT (Control.PROGRESS, 2),
|
||||||
|
PP_CHUNK (Control.PROGRESS, 3),
|
||||||
|
PP_CHUNKVERT(Control.PROGRESS, 4),
|
||||||
|
|
||||||
|
RP_GRIPPER (Control.REBAR, 1),
|
||||||
|
RP_GRIPPERVERT(Control.REBAR, 2),
|
||||||
|
|
||||||
|
SBP_SCROLLBAR (Control.SCROLLBAR, 0),
|
||||||
|
SBP_ARROWBTN (Control.SCROLLBAR, 1),
|
||||||
|
SBP_THUMBBTNHORZ (Control.SCROLLBAR, 2),
|
||||||
|
SBP_THUMBBTNVERT (Control.SCROLLBAR, 3),
|
||||||
|
SBP_LOWERTRACKHORZ(Control.SCROLLBAR, 4),
|
||||||
|
SBP_UPPERTRACKHORZ(Control.SCROLLBAR, 5),
|
||||||
|
SBP_LOWERTRACKVERT(Control.SCROLLBAR, 6),
|
||||||
|
SBP_UPPERTRACKVERT(Control.SCROLLBAR, 7),
|
||||||
|
SBP_GRIPPERHORZ (Control.SCROLLBAR, 8),
|
||||||
|
SBP_GRIPPERVERT (Control.SCROLLBAR, 9),
|
||||||
|
SBP_SIZEBOX (Control.SCROLLBAR, 10),
|
||||||
|
|
||||||
|
SPNP_UP (Control.SPIN, 1),
|
||||||
|
SPNP_DOWN(Control.SPIN, 2),
|
||||||
|
|
||||||
|
TABP_TABITEM (Control.TAB, 1),
|
||||||
|
TABP_TABITEMLEFTEDGE (Control.TAB, 2),
|
||||||
|
TABP_TABITEMRIGHTEDGE(Control.TAB, 3),
|
||||||
|
TABP_PANE (Control.TAB, 9),
|
||||||
|
|
||||||
|
TP_TOOLBAR (Control.TOOLBAR, 0),
|
||||||
|
TP_BUTTON (Control.TOOLBAR, 1),
|
||||||
|
TP_SEPARATOR (Control.TOOLBAR, 5),
|
||||||
|
TP_SEPARATORVERT (Control.TOOLBAR, 6),
|
||||||
|
|
||||||
|
TKP_TRACK (Control.TRACKBAR, 1),
|
||||||
|
TKP_TRACKVERT (Control.TRACKBAR, 2),
|
||||||
|
TKP_THUMB (Control.TRACKBAR, 3),
|
||||||
|
TKP_THUMBBOTTOM(Control.TRACKBAR, 4),
|
||||||
|
TKP_THUMBTOP (Control.TRACKBAR, 5),
|
||||||
|
TKP_THUMBVERT (Control.TRACKBAR, 6),
|
||||||
|
TKP_THUMBLEFT (Control.TRACKBAR, 7),
|
||||||
|
TKP_THUMBRIGHT (Control.TRACKBAR, 8),
|
||||||
|
TKP_TICS (Control.TRACKBAR, 9),
|
||||||
|
TKP_TICSVERT (Control.TRACKBAR, 10),
|
||||||
|
|
||||||
|
TVP_TREEVIEW(Control.TREEVIEW, 0),
|
||||||
|
TVP_GLYPH (Control.TREEVIEW, 2),
|
||||||
|
|
||||||
|
WP_WINDOW (Control.WINDOW, 0),
|
||||||
|
WP_CAPTION (Control.WINDOW, 1),
|
||||||
|
WP_MINCAPTION (Control.WINDOW, 3),
|
||||||
|
WP_MAXCAPTION (Control.WINDOW, 5),
|
||||||
|
WP_FRAMELEFT (Control.WINDOW, 7),
|
||||||
|
WP_FRAMERIGHT (Control.WINDOW, 8),
|
||||||
|
WP_FRAMEBOTTOM (Control.WINDOW, 9),
|
||||||
|
WP_SYSBUTTON (Control.WINDOW, 13),
|
||||||
|
WP_MDISYSBUTTON (Control.WINDOW, 14),
|
||||||
|
WP_MINBUTTON (Control.WINDOW, 15),
|
||||||
|
WP_MDIMINBUTTON (Control.WINDOW, 16),
|
||||||
|
WP_MAXBUTTON (Control.WINDOW, 17),
|
||||||
|
WP_CLOSEBUTTON (Control.WINDOW, 18),
|
||||||
|
WP_MDICLOSEBUTTON (Control.WINDOW, 20),
|
||||||
|
WP_RESTOREBUTTON (Control.WINDOW, 21),
|
||||||
|
WP_MDIRESTOREBUTTON(Control.WINDOW, 22);
|
||||||
|
|
||||||
|
private final Control control;
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
private Part(Control control, int value) {
|
||||||
|
this.control = control;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getControlName(Component component) {
|
||||||
|
String str = "";
|
||||||
|
if (component instanceof JComponent) {
|
||||||
|
JComponent c = (JComponent)component;
|
||||||
|
String subAppName = (String)c.getClientProperty("XPStyle.subAppName");
|
||||||
|
if (subAppName != null) {
|
||||||
|
str = subAppName + "::";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return str + control.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return control.toString()+"."+name();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An enumeration of the possible component states
|
||||||
|
*/
|
||||||
|
public static enum State {
|
||||||
|
ACTIVE,
|
||||||
|
ASSIST,
|
||||||
|
BITMAP,
|
||||||
|
CHECKED,
|
||||||
|
CHECKEDDISABLED,
|
||||||
|
CHECKEDHOT,
|
||||||
|
CHECKEDNORMAL,
|
||||||
|
CHECKEDPRESSED,
|
||||||
|
CHECKMARKNORMAL,
|
||||||
|
CHECKMARKDISABLED,
|
||||||
|
BULLETNORMAL,
|
||||||
|
BULLETDISABLED,
|
||||||
|
CLOSED,
|
||||||
|
DEFAULTED,
|
||||||
|
DISABLED,
|
||||||
|
DISABLEDHOT,
|
||||||
|
DISABLEDPUSHED,
|
||||||
|
DOWNDISABLED,
|
||||||
|
DOWNHOT,
|
||||||
|
DOWNNORMAL,
|
||||||
|
DOWNPRESSED,
|
||||||
|
FOCUSED,
|
||||||
|
HOT,
|
||||||
|
HOTCHECKED,
|
||||||
|
ICONHOT,
|
||||||
|
ICONNORMAL,
|
||||||
|
ICONPRESSED,
|
||||||
|
ICONSORTEDHOT,
|
||||||
|
ICONSORTEDNORMAL,
|
||||||
|
ICONSORTEDPRESSED,
|
||||||
|
INACTIVE,
|
||||||
|
INACTIVENORMAL, // See note 1
|
||||||
|
INACTIVEHOT, // See note 1
|
||||||
|
INACTIVEPUSHED, // See note 1
|
||||||
|
INACTIVEDISABLED, // See note 1
|
||||||
|
LEFTDISABLED,
|
||||||
|
LEFTHOT,
|
||||||
|
LEFTNORMAL,
|
||||||
|
LEFTPRESSED,
|
||||||
|
MIXEDDISABLED,
|
||||||
|
MIXEDHOT,
|
||||||
|
MIXEDNORMAL,
|
||||||
|
MIXEDPRESSED,
|
||||||
|
NORMAL,
|
||||||
|
PRESSED,
|
||||||
|
OPENED,
|
||||||
|
PUSHED,
|
||||||
|
READONLY,
|
||||||
|
RIGHTDISABLED,
|
||||||
|
RIGHTHOT,
|
||||||
|
RIGHTNORMAL,
|
||||||
|
RIGHTPRESSED,
|
||||||
|
SELECTED,
|
||||||
|
UNCHECKEDDISABLED,
|
||||||
|
UNCHECKEDHOT,
|
||||||
|
UNCHECKEDNORMAL,
|
||||||
|
UNCHECKEDPRESSED,
|
||||||
|
UPDISABLED,
|
||||||
|
UPHOT,
|
||||||
|
UPNORMAL,
|
||||||
|
UPPRESSED,
|
||||||
|
HOVER,
|
||||||
|
UPHOVER,
|
||||||
|
DOWNHOVER,
|
||||||
|
LEFTHOVER,
|
||||||
|
RIGHTHOVER,
|
||||||
|
SORTEDDOWN,
|
||||||
|
SORTEDHOT,
|
||||||
|
SORTEDNORMAL,
|
||||||
|
SORTEDPRESSED,
|
||||||
|
SORTEDUP;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A map of allowed states for each Part
|
||||||
|
*/
|
||||||
|
private static EnumMap<Part, State[]> stateMap;
|
||||||
|
|
||||||
|
private static synchronized void initStates() {
|
||||||
|
stateMap = new EnumMap<Part, State[]>(Part.class);
|
||||||
|
|
||||||
|
stateMap.put(Part.EP_EDITTEXT,
|
||||||
|
new State[] {
|
||||||
|
NORMAL, HOT, SELECTED, DISABLED, FOCUSED, READONLY, ASSIST
|
||||||
|
});
|
||||||
|
|
||||||
|
stateMap.put(Part.BP_PUSHBUTTON,
|
||||||
|
new State[] { NORMAL, HOT, PRESSED, DISABLED, DEFAULTED });
|
||||||
|
|
||||||
|
stateMap.put(Part.BP_RADIOBUTTON,
|
||||||
|
new State[] {
|
||||||
|
UNCHECKEDNORMAL, UNCHECKEDHOT, UNCHECKEDPRESSED, UNCHECKEDDISABLED,
|
||||||
|
CHECKEDNORMAL, CHECKEDHOT, CHECKEDPRESSED, CHECKEDDISABLED
|
||||||
|
});
|
||||||
|
|
||||||
|
stateMap.put(Part.BP_CHECKBOX,
|
||||||
|
new State[] {
|
||||||
|
UNCHECKEDNORMAL, UNCHECKEDHOT, UNCHECKEDPRESSED, UNCHECKEDDISABLED,
|
||||||
|
CHECKEDNORMAL, CHECKEDHOT, CHECKEDPRESSED, CHECKEDDISABLED,
|
||||||
|
MIXEDNORMAL, MIXEDHOT, MIXEDPRESSED, MIXEDDISABLED
|
||||||
|
});
|
||||||
|
|
||||||
|
State[] comboBoxStates = new State[] { NORMAL, HOT, PRESSED, DISABLED };
|
||||||
|
stateMap.put(Part.CP_COMBOBOX, comboBoxStates);
|
||||||
|
stateMap.put(Part.CP_DROPDOWNBUTTON, comboBoxStates);
|
||||||
|
stateMap.put(Part.CP_BACKGROUND, comboBoxStates);
|
||||||
|
stateMap.put(Part.CP_TRANSPARENTBACKGROUND, comboBoxStates);
|
||||||
|
stateMap.put(Part.CP_BORDER, comboBoxStates);
|
||||||
|
stateMap.put(Part.CP_READONLY, comboBoxStates);
|
||||||
|
stateMap.put(Part.CP_DROPDOWNBUTTONRIGHT, comboBoxStates);
|
||||||
|
stateMap.put(Part.CP_DROPDOWNBUTTONLEFT, comboBoxStates);
|
||||||
|
stateMap.put(Part.CP_CUEBANNER, comboBoxStates);
|
||||||
|
|
||||||
|
stateMap.put(Part.HP_HEADERITEM, new State[] { NORMAL, HOT, PRESSED,
|
||||||
|
SORTEDNORMAL, SORTEDHOT, SORTEDPRESSED,
|
||||||
|
ICONNORMAL, ICONHOT, ICONPRESSED,
|
||||||
|
ICONSORTEDNORMAL, ICONSORTEDHOT, ICONSORTEDPRESSED });
|
||||||
|
|
||||||
|
stateMap.put(Part.HP_HEADERSORTARROW,
|
||||||
|
new State[] {SORTEDDOWN, SORTEDUP});
|
||||||
|
|
||||||
|
State[] scrollBarStates = new State[] { NORMAL, HOT, PRESSED, DISABLED, HOVER };
|
||||||
|
stateMap.put(Part.SBP_SCROLLBAR, scrollBarStates);
|
||||||
|
stateMap.put(Part.SBP_THUMBBTNVERT, scrollBarStates);
|
||||||
|
stateMap.put(Part.SBP_THUMBBTNHORZ, scrollBarStates);
|
||||||
|
stateMap.put(Part.SBP_GRIPPERVERT, scrollBarStates);
|
||||||
|
stateMap.put(Part.SBP_GRIPPERHORZ, scrollBarStates);
|
||||||
|
|
||||||
|
stateMap.put(Part.SBP_ARROWBTN,
|
||||||
|
new State[] {
|
||||||
|
UPNORMAL, UPHOT, UPPRESSED, UPDISABLED,
|
||||||
|
DOWNNORMAL, DOWNHOT, DOWNPRESSED, DOWNDISABLED,
|
||||||
|
LEFTNORMAL, LEFTHOT, LEFTPRESSED, LEFTDISABLED,
|
||||||
|
RIGHTNORMAL, RIGHTHOT, RIGHTPRESSED, RIGHTDISABLED,
|
||||||
|
UPHOVER, DOWNHOVER, LEFTHOVER, RIGHTHOVER
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
State[] spinnerStates = new State[] { NORMAL, HOT, PRESSED, DISABLED };
|
||||||
|
stateMap.put(Part.SPNP_UP, spinnerStates);
|
||||||
|
stateMap.put(Part.SPNP_DOWN, spinnerStates);
|
||||||
|
|
||||||
|
stateMap.put(Part.TVP_GLYPH, new State[] { CLOSED, OPENED });
|
||||||
|
|
||||||
|
State[] frameButtonStates = new State[] {
|
||||||
|
NORMAL, HOT, PUSHED, DISABLED, // See note 1
|
||||||
|
INACTIVENORMAL, INACTIVEHOT, INACTIVEPUSHED, INACTIVEDISABLED,
|
||||||
|
};
|
||||||
|
// Note 1: The INACTIVE frame button states apply when the frame
|
||||||
|
// is inactive. They are not defined in tmschema.h
|
||||||
|
|
||||||
|
// Fix for 6316538: Vista has five frame button states
|
||||||
|
/*if (ThemeReader.getInt(Control.WINDOW.toString(),
|
||||||
|
Part.WP_CLOSEBUTTON.getValue(), 1,
|
||||||
|
Prop.IMAGECOUNT.getValue()) == 10) {
|
||||||
|
frameButtonStates = new State[] {
|
||||||
|
NORMAL, HOT, PUSHED, DISABLED, null,
|
||||||
|
INACTIVENORMAL, INACTIVEHOT, INACTIVEPUSHED, INACTIVEDISABLED, null
|
||||||
|
};
|
||||||
|
}*/
|
||||||
|
|
||||||
|
stateMap.put(Part.WP_MINBUTTON, frameButtonStates);
|
||||||
|
stateMap.put(Part.WP_MAXBUTTON, frameButtonStates);
|
||||||
|
stateMap.put(Part.WP_RESTOREBUTTON, frameButtonStates);
|
||||||
|
stateMap.put(Part.WP_CLOSEBUTTON, frameButtonStates);
|
||||||
|
|
||||||
|
// States for Slider (trackbar)
|
||||||
|
stateMap.put(Part.TKP_TRACK, new State[] { NORMAL });
|
||||||
|
stateMap.put(Part.TKP_TRACKVERT, new State[] { NORMAL });
|
||||||
|
|
||||||
|
State[] sliderThumbStates =
|
||||||
|
new State[] { NORMAL, HOT, PRESSED, FOCUSED, DISABLED };
|
||||||
|
stateMap.put(Part.TKP_THUMB, sliderThumbStates);
|
||||||
|
stateMap.put(Part.TKP_THUMBBOTTOM, sliderThumbStates);
|
||||||
|
stateMap.put(Part.TKP_THUMBTOP, sliderThumbStates);
|
||||||
|
stateMap.put(Part.TKP_THUMBVERT, sliderThumbStates);
|
||||||
|
stateMap.put(Part.TKP_THUMBRIGHT, sliderThumbStates);
|
||||||
|
|
||||||
|
// States for Tabs
|
||||||
|
State[] tabStates = new State[] { NORMAL, HOT, SELECTED, DISABLED, FOCUSED };
|
||||||
|
stateMap.put(Part.TABP_TABITEM, tabStates);
|
||||||
|
stateMap.put(Part.TABP_TABITEMLEFTEDGE, tabStates);
|
||||||
|
stateMap.put(Part.TABP_TABITEMRIGHTEDGE, tabStates);
|
||||||
|
|
||||||
|
|
||||||
|
stateMap.put(Part.TP_BUTTON,
|
||||||
|
new State[] {
|
||||||
|
NORMAL, HOT, PRESSED, DISABLED, CHECKED, HOTCHECKED
|
||||||
|
});
|
||||||
|
|
||||||
|
State[] frameStates = new State[] { ACTIVE, INACTIVE };
|
||||||
|
stateMap.put(Part.WP_WINDOW, frameStates);
|
||||||
|
stateMap.put(Part.WP_FRAMELEFT, frameStates);
|
||||||
|
stateMap.put(Part.WP_FRAMERIGHT, frameStates);
|
||||||
|
stateMap.put(Part.WP_FRAMEBOTTOM, frameStates);
|
||||||
|
|
||||||
|
State[] captionStates = new State[] { ACTIVE, INACTIVE, DISABLED };
|
||||||
|
stateMap.put(Part.WP_CAPTION, captionStates);
|
||||||
|
stateMap.put(Part.WP_MINCAPTION, captionStates);
|
||||||
|
stateMap.put(Part.WP_MAXCAPTION, captionStates);
|
||||||
|
|
||||||
|
stateMap.put(Part.MP_BARBACKGROUND,
|
||||||
|
new State[] { ACTIVE, INACTIVE });
|
||||||
|
stateMap.put(Part.MP_BARITEM,
|
||||||
|
new State[] { NORMAL, HOT, PUSHED,
|
||||||
|
DISABLED, DISABLEDHOT, DISABLEDPUSHED });
|
||||||
|
stateMap.put(Part.MP_POPUPCHECK,
|
||||||
|
new State[] { CHECKMARKNORMAL, CHECKMARKDISABLED,
|
||||||
|
BULLETNORMAL, BULLETDISABLED });
|
||||||
|
stateMap.put(Part.MP_POPUPCHECKBACKGROUND,
|
||||||
|
new State[] { DISABLEDPUSHED, NORMAL, BITMAP });
|
||||||
|
stateMap.put(Part.MP_POPUPITEM,
|
||||||
|
new State[] { NORMAL, HOT, DISABLED, DISABLEDHOT });
|
||||||
|
stateMap.put(Part.MP_POPUPSUBMENU,
|
||||||
|
new State[] { NORMAL, DISABLED });
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static synchronized int getValue(Part part, State state) {
|
||||||
|
if (stateMap == null) {
|
||||||
|
initStates();
|
||||||
|
}
|
||||||
|
|
||||||
|
Enum[] states = stateMap.get(part);
|
||||||
|
if (states != null) {
|
||||||
|
for (int i = 0; i < states.length; i++) {
|
||||||
|
if (state == states[i]) {
|
||||||
|
return i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state == null || state == State.NORMAL) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An enumeration of the possible component attributes and the
|
||||||
|
* corresponding value type
|
||||||
|
*/
|
||||||
|
public static enum Prop {
|
||||||
|
COLOR(Color.class, 204),
|
||||||
|
SIZE(Dimension.class, 207),
|
||||||
|
|
||||||
|
FLATMENUS(Boolean.class, 1001),
|
||||||
|
|
||||||
|
BORDERONLY(Boolean.class, 2203), // only draw the border area of the image
|
||||||
|
|
||||||
|
IMAGECOUNT(Integer.class, 2401), // the number of state images in an imagefile
|
||||||
|
BORDERSIZE(Integer.class, 2403), // the size of the border line for bgtype=BorderFill
|
||||||
|
|
||||||
|
PROGRESSCHUNKSIZE(Integer.class, 2411), // size of progress control chunks
|
||||||
|
PROGRESSSPACESIZE(Integer.class, 2412), // size of progress control spaces
|
||||||
|
|
||||||
|
TEXTSHADOWOFFSET(Point.class, 3402), // where char shadows are drawn, relative to orig. chars
|
||||||
|
|
||||||
|
NORMALSIZE(Dimension.class, 3409), // size of dest rect that exactly source
|
||||||
|
|
||||||
|
|
||||||
|
SIZINGMARGINS ( Insets.class, 3601), // margins used for 9-grid sizing
|
||||||
|
CONTENTMARGINS(Insets.class, 3602), // margins that define where content can be placed
|
||||||
|
CAPTIONMARGINS(Insets.class, 3603), // margins that define where caption text can be placed
|
||||||
|
|
||||||
|
BORDERCOLOR(Color.class, 3801), // color of borders for BorderFill
|
||||||
|
FILLCOLOR ( Color.class, 3802), // color of bg fill
|
||||||
|
TEXTCOLOR ( Color.class, 3803), // color text is drawn in
|
||||||
|
|
||||||
|
TEXTSHADOWCOLOR(Color.class, 3818), // color of text shadow
|
||||||
|
|
||||||
|
BGTYPE(Integer.class, 4001), // basic drawing type for each part
|
||||||
|
|
||||||
|
TEXTSHADOWTYPE(Integer.class, 4010), // type of shadow to draw with text
|
||||||
|
|
||||||
|
TRANSITIONDURATIONS(Integer.class, 6000);
|
||||||
|
|
||||||
|
private final Class type;
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
private Prop(Class type, int value) {
|
||||||
|
this.type = type;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return name()+"["+type.getName()+"] = "+value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An enumeration of attribute values for some Props
|
||||||
|
*/
|
||||||
|
public static enum TypeEnum {
|
||||||
|
BT_IMAGEFILE (Prop.BGTYPE, "imagefile", 0),
|
||||||
|
BT_BORDERFILL(Prop.BGTYPE, "borderfill", 1),
|
||||||
|
|
||||||
|
TST_NONE(Prop.TEXTSHADOWTYPE, "none", 0),
|
||||||
|
TST_SINGLE(Prop.TEXTSHADOWTYPE, "single", 1),
|
||||||
|
TST_CONTINUOUS(Prop.TEXTSHADOWTYPE, "continuous", 2);
|
||||||
|
|
||||||
|
|
||||||
|
private TypeEnum(Prop prop, String enumName, int value) {
|
||||||
|
this.prop = prop;
|
||||||
|
this.enumName = enumName;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Prop prop;
|
||||||
|
private final String enumName;
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return prop+"="+enumName+"="+value;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getName() {
|
||||||
|
return enumName;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static TypeEnum getTypeEnum(Prop prop, int enumval) {
|
||||||
|
for (TypeEnum e : TypeEnum.values()) {
|
||||||
|
if (e.prop == prop && e.value == enumval) {
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user