nimbusstyle.java
来自「Mobile 应用程序使用 Java Micro Edition (Java M」· Java 代码 · 共 1,243 行 · 第 1/4 页
JAVA
1,243 行
private boolean contains(String[] names, String name) { assert name != null; for (int i=0; i<names.length; i++) { if (name.equals(names[i])) { return true; } } return false; } /** * <p>Gets the extended state for a given synth context. Nimbus supports the * ability to define custom states. The algorithm used for choosing what * style information to use for a given state requires a single integer * bit string where each bit in the integer represents a different state * that the component is in. This method uses the componentState as * reported in the SynthContext, in addition to custom states, to determine * what this extended state is.</p> * * <p>In addition, this method checks the component in the given context * for a client property called "Nimbus.State". If one exists, then it will * decompose the String associated with that property to determine what * state to return. In this way, the developer can force a component to be * in a specific state, regardless of what the "real" state of the component * is.</p> * * <p>The string associated with "Nimbus.State" would be of the form: * <pre>Enabled+CustomState+MouseOver</pre></p> * * @param ctx * @param v * @return */ private int getExtendedState(SynthContext ctx, Values v) { JComponent c = ctx.getComponent(); int xstate = 0; int mask = 1; //check for the Nimbus.State client property //Performance NOTE: getClientProperty ends up inside a synchronized //block, so there is some potential for performance issues here, however //I'm not certain that there is one on a modern VM. Object property = c.getClientProperty("Nimbus.State"); if (property != null) { String stateNames = property.toString(); String[] states = stateNames.split("\\+"); if (v.stateTypes == null){ // standard states only for (String stateStr : states) { State.StandardState s = State.getStandardState(stateStr); if (s != null) xstate |= s.getState(); } } else { // custom states for (State s : v.stateTypes) { if (contains(states, s.getName())) { xstate |= mask; } mask <<= 1; } } } else { //if there are no custom states defined, then simply return the //state that Synth reported if (v.stateTypes == null) return ctx.getComponentState(); //there are custom states on this values, so I'll have to iterate //over them all and return a custom extended state int state = ctx.getComponentState(); for (State s : v.stateTypes) { if (s.isInState(c, state)) { xstate |= mask; } mask <<= 1; } } return xstate; } /** * <p>Gets the RuntimeState that most closely matches the state in the given * context, but is less specific than the given "lastState". Essentially, * this allows you to search for the next best state.</p> * * <p>For example, if you had the following three states: * <pre> * Enabled * Enabled+Pressed * Disabled * </pre> * And you wanted to find the state that best represented * ENABLED+PRESSED+FOCUSED and <code>lastState</code> was null (or an * empty array, or an array with a single int with index == -1), then * Enabled+Pressed would be returned. If you then call this method again but * pass the index of Enabled+Pressed as the "lastState", then * Enabled would be returned. If you call this method a third time and pass * the index of Enabled in as the <code>lastState</code>, then null would be * returned.</p> * * <p>The actual code path for determining the proper state is the same as * in Synth.</p> * * @param ctx * @param lastState a 1 element array, allowing me to do pass-by-reference. * @return */ private RuntimeState getNextState(RuntimeState[] states, int[] lastState, int xstate) { // Use the StateInfo with the most bits that matches that of state. // If there are none, then fallback to // the StateInfo with a state of 0, indicating it'll match anything. // Consider if we have 3 StateInfos a, b and c with states: // SELECTED, SELECTED | ENABLED, 0 // // Input Return Value // ----- ------------ // SELECTED a // SELECTED | ENABLED b // MOUSE_OVER c // SELECTED | ENABLED | FOCUSED b // ENABLED c if (states != null && states.length > 0) { int bestCount = 0; int bestIndex = -1; int wildIndex = -1; //if xstate is 0, then search for the runtime state with component //state of 0. That is, find the exact match and return it. if (xstate == 0) { for (int counter = states.length - 1; counter >= 0; counter--) { if (states[counter].state == 0) { lastState[0] = counter; return states[counter]; } } //an exact match couldn't be found, so there was no match. lastState[0] = -1; return null; } //xstate is some value != 0 //determine from which index to start looking. If lastState[0] is -1 //then we know to start from the end of the state array. Otherwise, //we start at the lastIndex - 1. int lastStateIndex = lastState == null || lastState[0] == -1 ? states.length : lastState[0]; for (int counter = lastStateIndex - 1; counter >= 0; counter--) { int oState = states[counter].state; if (oState == 0) { if (wildIndex == -1) { wildIndex = counter; } } else if ((xstate & oState) == oState) { // This is key, we need to make sure all bits of the // StateInfo match, otherwise a StateInfo with // SELECTED | ENABLED would match ENABLED, which we // don't want. // This comes from BigInteger.bitCnt int bitCount = oState; bitCount -= (0xaaaaaaaa & bitCount) >>> 1; bitCount = (bitCount & 0x33333333) + ((bitCount >>> 2) & 0x33333333); bitCount = bitCount + (bitCount >>> 4) & 0x0f0f0f0f; bitCount += bitCount >>> 8; bitCount += bitCount >>> 16; bitCount = bitCount & 0xff; if (bitCount > bestCount) { bestIndex = counter; bestCount = bitCount; } } } if (bestIndex != -1) { lastState[0] = bestIndex; return states[bestIndex]; } if (wildIndex != -1) { lastState[0] = wildIndex; return states[wildIndex]; } } lastState[0] = -1; return null; } /** * Contains values such as the UIDefaults and painters asssociated with * a state. Whereas <code>State</code> represents a distinct state that a * component can be in (such as Enabled), this class represents the colors, * fonts, painters, etc associated with some state for this * style. */ private final class RuntimeState implements Cloneable { int state; Painter backgroundPainter; Painter foregroundPainter; Painter borderPainter; String stateName; UIDefaults defaults = new UIDefaults(10, .7f); private RuntimeState(int state, String stateName) { this.state = state; this.stateName = stateName; } @Override public String toString() { return stateName; } @Override public RuntimeState clone() { RuntimeState clone = new RuntimeState(state, stateName); clone.backgroundPainter = backgroundPainter; clone.foregroundPainter = foregroundPainter; clone.borderPainter = borderPainter; clone.defaults.putAll(defaults); return clone; } } /** * Essentially a struct of data for a style. A default instance of this * class is used by NimbusStyle. Additional instances exist for each * component that has overrides. */ private static final class Values { /** * The list of State types. A State represents a type of state, such * as Enabled, Default, WindowFocused, etc. These can be custom states. */ State[] stateTypes = null; /** * The list of actual runtime state representations. These can represent things such * as Enabled + Focused. Thus, they differ from States in that they contain * several states together, and have associated properties, data, etc. */ RuntimeState[] states = null; /** * The content margins for this region. */ Insets contentMargins; /** * Defaults on the region/component level. */ UIDefaults defaults = new UIDefaults(10, .7f); /** * Simple cache. After a value has been looked up, it is stored * in this cache for later retrieval. The key is a concatenation of * the property being looked up, two dollar signs, and the extended * state. So for example: * * foo.bar$$2353 */ Map<CacheKey,Object> cache = new HashMap<CacheKey,Object>(); } /** * This implementation presupposes that key is never null and that * the two keys being checked for equality are never null */ private static final class CacheKey { private String key; private int xstate; CacheKey(Object key, int xstate) { init(key, xstate); } void init(Object key, int xstate) { this.key = key.toString(); this.xstate = xstate; } @Override public boolean equals(Object obj) { final CacheKey other = (CacheKey) obj; if (obj == null) return false; if (this.xstate != other.xstate) return false; if (!this.key.equals(other.key)) return false; return true; } @Override public int hashCode() { int hash = 3; hash = 29 * hash + this.key.hashCode(); hash = 29 * hash + this.xstate; return hash; } } /** * This listener is used to listen to the UIDefaults tables and clear out * the cached-precompiled map of defaults in that case. */ private static final class DefaultsListener implements PropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent evt) { AppContext.getAppContext().put("NimbusStyle.defaults", null); } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?