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 + -
显示快捷键?