⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fxobjectstylesupport.java

📁 java css java css java css java css
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code 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
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */
package com.sun.stylesheet.styleable;

import com.sun.stylesheet.Styleable;
import com.sun.stylesheet.StylesheetException;
import com.sun.stylesheet.PseudoclassListener;
import com.sun.stylesheet.types.TypeManager;
import com.sun.javafx.runtime.FXObject;

import com.sun.javafx.runtime.location.AbstractVariable;
import com.sun.javafx.runtime.location.BooleanVariable;
import com.sun.javafx.runtime.location.ChangeListener;
import com.sun.javafx.runtime.location.DoubleVariable;
import com.sun.javafx.runtime.location.IntVariable;
import com.sun.javafx.runtime.location.SequenceVariable;
import com.sun.javafx.runtime.sequence.Sequence;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * <p>An intermediate implementation of FXObjectStyleSupport based on reverse
 * engineered reflective access to the generated class files. This may break.
 * This needs to be rewritten based on javafx reflection when possible. Some
 * things here may not work.</p>
 *
 * <p>The FX script compiler generates a great number of class files from
 * a single FX script class. Each bound function ends up generating an inner
 * class. Each trigger implementation also (I think) generates an inner class.
 * Each attribute is represented by an AbstractVariable (as opposed to generating
 * getter and setter methods instead). Oddly, a generated file has both a public
 * final field for each attribute, and then a get$attrname method for each
 * attribute. Both have the same values(?? weird).</p>
 *
 * <p>Due to multiple inheritance support in fx-script, the compiler actually
 * ends up flattening the inheritance heirarchy and preserving the inheritance
 * graph in interfaces. (I think the get$attrname methods are used for
 * preserving the attribute names available in the inheritance graph).</p>
 *
 * <p>Given a javafx class Foo, two files will be generated: Foo.class and
 * Foo$Impl.class. The Foo.class contains ALL the implementation for that
 * class, whereas Foo$Impl.class preserves the API defined in javafx class Foo.</p>
 *
 * <p>Given a javafx class Baz that extends both a javafx class Foo and a
 * javafx class Bar, the Baz class files will include Baz.class and Baz$Intf.class.
 * Baz$Intf.class will extend both Bar$Intf and Foo$Intf. Baz.class there implements
 * all of Foo$Intf, Bar$Intf, and Baz$Intf. However, Baz.class contains ALL the
 * implementation for all three of these classes. This is done by essentially
 * copy & paste from Bar.class and Foo.class into Bar.class (plus the Bar
 * implementation).</p>
 *
 * <p>This particular implementation is focused squarely on Reprise and the
 * new Node-based Controls. Note that Node-based Controls are not part of publicly
 * available API and thus this class cannot be committed as is to the javacss
 * project.</p>
 *
 * <p>Currently Nodes and Reprise Components are two different things. When
 * they are successfully merged, this class will need to be fixed.</p>
 *
 * @author Richard Bair
 */
public class FXObjectStyleSupport implements StyleSupport {

    /**
     * All of the implementation classes that are part of the inheritance
     * heirarchy.... Hmm.
     */
    private Class[] objectClasses = new Class[0];
    /**
     * The class that this FXObjectStyleSupport is intended to support. For
     * example, this could be javafx.gui.Button.
     */
    private Class cls;
    private boolean isControl;
    private boolean isNode;
    private boolean isCanvas;
    private boolean isComponent;
    private boolean isGroup;
    private boolean isContainer;
    
    private Map<String, Attribute> attributes = new HashMap<String, Attribute>();

    /**
     * Create an FXObjectStyleSupport for an FXObject class. All fx-script classes
     * are compiled to classes that extend Object and implement FXObject.
     *
     * @param cls
     */
    public FXObjectStyleSupport(Class cls) {
        if (!FXObject.class.isAssignableFrom(cls)) {
            throw new IllegalArgumentException("Illegal attempt to use " +
                    "FXObjectStyleSupport with a non-fx class");
        }

        this.cls = cls;

        try {
            Class intf = Class.forName("javafx.gui.Node$Intf");
            isNode = intf.isAssignableFrom(cls);
            intf = Class.forName("javafx.gui.Group$Intf");
            isGroup = intf.isAssignableFrom(cls);
            intf = Class.forName("javafx.gui.Control$Intf");
            isControl = intf.isAssignableFrom(cls);
            intf = Class.forName("javafx.gui.Canvas$Intf");
            isCanvas = intf.isAssignableFrom(cls);
            intf = Class.forName("javafx.gui.swing.Component$Intf");
            isComponent = intf.isAssignableFrom(cls);
            intf = Class.forName("javafx.gui.swing.Container$Intf");
            isContainer = intf.isAssignableFrom(cls);
        } catch (Exception e) {
            throw new IllegalStateException("Failed to load necessary " +
                    "FX classes. They may not be on the classpath", e);
        }

        // pre-determine the class hierarchy here
        // All JavaFX classes that do not extend Java classes directly
        // end up extending java.lang.Object directly.
        // Their "fx inheritance" is determined actually by the interfaces
        // that the class implements and inherits from. Each "fx class" is
        // represented as Foo.class and Foo$Intf.class. If the javafx class
        // Foo extends Bar, then there will be an
        // interface Foo$Intf extends Bar$Intf

        // get the $Intf interface associated with this class
        Class intf = null;
        Class[] interfaces = cls.getInterfaces();
        for (Class c : interfaces) {
            if (c.getName().equals(cls.getName() + "$Intf")) {
                intf = c;
                break;
            }
        }

        if (intf == null) {
            throw new IllegalStateException("Failed to find the $Intf class " +
                    "for " + cls.getName());
        }

        if (cls.getSuperclass() != Object.class) {
            // I have an FX class which extends a traditional Java class.
            // In this case, I don't have to worry about figuring out
            // the inheritance graph, so I can go ahead and just set the
            // object classes to be this class and its interfaces.
            objectClasses = new Class[interfaces.length + 1];
            objectClasses[0] = cls;
            System.arraycopy(interfaces, 0, objectClasses, 1, interfaces.length);
        } else {
            // I have an FX class that extends another FX class. I have to
            // therefore construct my objectClasses to contain the implementation
            // classes for all of the $Intf interfaces that are implemented
            Set<Class> classes = new HashSet<Class>();
            try {
                accumulateClasses(cls, classes);
                objectClasses = classes.toArray(new Class[classes.size()]);
            } catch (Exception e) {
                throw new IllegalStateException("Failed to load the class " +
                        "heirarchy for " + cls.getName(), e);
            }
        }
    }

    private void accumulateClasses(Class cls, Set<Class> classes) throws Exception {
        classes.add(cls);
        for (Class c : cls.getInterfaces()) {
            String name = c.getName();
            if (name.endsWith("$Intf")) {
                // must have found an FX class interface. Find the corresponding
                // concrete implementation class and include that
                ClassLoader loader = c.getClassLoader();
                Class concrete = Class.forName(name.substring(0, name.length() - 5), false, loader);
                classes.add(concrete);
                accumulateClasses(c, classes);
            }
        }
    }

    /**
     * All Nodes have an "id" attribute. Component has a "name" attribute. Both
     * of these act as the "id". If a class happens to extend both Node and
     * Component, then Node's id is honored and "name" is ignored.
     *
     * @param object
     * @return
     */
    public String getID(Object object) {
        Object id = null;
        if (isNode) {
            id = getAttribute("id").getProperty(object);
        } else if (isComponent) {
            id = getAttribute("name").getProperty(object);
        }
        return id == null ? null : id.toString();
    }

    /**
     * Only controls currently have a styleClass attribute, so only they
     * return a non-null value from this method.
     *
     * @param object
     * @return
     */
    public String getStyleClass(Object object) {
        if (isControl) {
            Object styleClass = getAttribute("styleClass").getProperty(object);
            return styleClass == null ? null : styleClass.toString();
        }
        return null;
    }

    public Class[] getObjectClasses(Object object) {
        return objectClasses;
    }

    /**
     * If the given object is a Node, then we find the parent node and wrap it
     * as a Styleable. If the given object is a Component, then we find the
     * parent component and wrap it as a Styleable.
     *
     * @param object
     * @return
     */
    public Styleable getStyleableParent(Object object) {
        if (isNode || isComponent) {
            Object parent = getAttribute("parent").getProperty(object);
            return parent == null ? null : TypeManager.getStyleable(parent);
        }
        return null;
    }

    /**

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -