jworkspace.ui.plaf.PlafFactory.java Source code

Java tutorial

Introduction

Here is the source code for jworkspace.ui.plaf.PlafFactory.java

Source

package jworkspace.ui.plaf;

/* ----------------------------------------------------------------------------
   Java Workspace
   Copyright (C) 1999-2003 Anton Troshin
    
   This file is part of Java Workspace.
    
   This application is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.
    
   This application 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
   Library General Public License for more details.
    
   You should have received a copy of the GNU Library General Public
   License along with this application; if not, write to the Free
   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    
   The author may be contacted at:
    
   anton.troshin@gmail.com
  ----------------------------------------------------------------------------
*/

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import javax.swing.plaf.metal.MetalTheme;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import jworkspace.ui.WorkspaceGUI;

/**
 * Pluggable look and feel factory
 * @author Anton Troshin
 */
public class PlafFactory {
    /**
     * Default logger
     */
    private static final Logger LOG = LoggerFactory.getLogger(PlafFactory.class);
    /**
     * The directory of config
     */
    private static final String CONFIG_FILE_PATH = "config";
    /**
     * Single instance
     */
    private static PlafFactory instance;
    /**
     * The name of configuration file
     */
    private static String sysConfig = "lafs.xml";
    /**
     * Array of plaf connectors
     */
    private List<XPlafConnector> connectors = new ArrayList<>();

    /**
     * Private constructor
     */
    private PlafFactory() {
    }

    /**
     * Get a single instance of this factory
     *
     * @return single instance
     */
    public static synchronized PlafFactory getInstance() {
        if (instance == null) {
            instance = new PlafFactory();
            instance.load();
        }
        return instance;
    }

    /**
     * Load and install look and feels from user configuration file
     */
    private void load() {
        String fileName = CONFIG_FILE_PATH + File.separator + sysConfig;
        LOG.info(
                WorkspaceGUI.PROMPT + "Reading file" + WorkspaceGUI.LOG_SPACE + fileName + WorkspaceGUI.LOG_FINISH);
        try {
            File file = new File(fileName);
            SAXBuilder builder = new SAXBuilder();
            Document doc = builder.build(file);
            Element root = doc.getRootElement();
            /*
             * Here we should find all plaf elements, described
             * in xml file under <plaf> tags
             */
            List<Element> plafs = root.getChildren("plaf");
            for (Element plaf : plafs) {
                XPlafConnector connector = XPlafConnector.create(plaf);
                if (connector != null) {
                    connectors.add(connector);
                }
            }
        } catch (JDOMException | IOException e) {
            LOG.error("Cannot load plaf factory", e);
        }
    }

    /**
     * Save all look and feel user config
     */
    public void save() {
        String fileName = CONFIG_FILE_PATH + File.separator + sysConfig;
        LOG.info(
                WorkspaceGUI.PROMPT + "Writing file" + WorkspaceGUI.LOG_SPACE + fileName + WorkspaceGUI.LOG_FINISH);
        File file = new File(fileName);

        try (StringWriter sw = new StringWriter(); FileOutputStream os = new FileOutputStream(file)) {

            Element plafs = new Element("plafs");
            for (XPlafConnector connector : connectors) {
                plafs.addContent(connector.serialize());
            }

            XMLOutputter serializer = new XMLOutputter();
            serializer.setFormat(Format.getPrettyFormat());
            serializer.output(plafs, sw);

            os.write(sw.toString().getBytes(StandardCharsets.UTF_8));
            os.flush();

        } catch (IOException e) {
            LOG.warn("Cannot save plaf factory", e);
        }
    }

    /**
     * Returns an instance of look and feel object without installing
     * it or switching gui. This can be used if any info about laf is needed.
     *
     * @param selectedLaf a string name of look and feel
     * @return look and feel object
     */
    public LookAndFeel getLookAndFeel(String selectedLaf) {
        try {
            return lookUp(selectedLaf);
        } catch (ClassNotFoundException e) {
            return null;
        }
    }

    /**
     * Lookup installed look and feel
     *
     * @param selectedLaf a string name of look and feel
     * @return look and feel object
     */
    private LookAndFeel lookUp(String selectedLaf) throws ClassNotFoundException {
        UIManager.LookAndFeelInfo[] infos = UIManager.getInstalledLookAndFeels();
        for (UIManager.LookAndFeelInfo info : infos) {
            if (info.getName().equals(selectedLaf) || info.getClassName().equals(selectedLaf)) {
                Class clazz = Class.forName(selectedLaf, true, Thread.currentThread().getContextClassLoader());
                try {
                    return (LookAndFeel) clazz.newInstance();
                } catch (Exception e) {
                    LOG.error("Cannot instantiate the plaf discovered", e);
                }
            }
        }
        return null;
    }

    /**
     * Look up a proper connector for look and feel to get
     * themes list and other extra info
     *
     * @param selectedLaf the laf, which connector is needed
     * @return plaf connector for selected laf
     */
    private XPlafConnector lookUpConnector(LookAndFeel selectedLaf) {
        for (XPlafConnector connector : connectors) {
            if (connector.getInfo().getName().equals(selectedLaf.getName())) {
                return connector;
            }
        }
        return null;
    }

    /**
     * Look up a proper connector for look and feel to get
     * themes list and other extra info
     *
     * @param className the class name of laf, which connector is needed
     * @return plaf connector for selected laf
     */
    private XPlafConnector lookUpConnector(String className) {
        for (Object o : connectors) {
            XPlafConnector connector = (XPlafConnector) o;

            if (connector.getInfo().getClassName().equals(className)) {
                return connector;
            }
        }
        return null;
    }

    /**
     * List themes for a given look and feel. All themes are stored
     * in internal laf database and should be in class path.
     *
     * @param selectedLaf the laf, which themes are to be inspected
     * @return an array of selected lafs
     */
    public MetalTheme[] listThemes(LookAndFeel selectedLaf) {
        XPlafConnector connector = lookUpConnector(selectedLaf);
        if (connector != null) {
            return connector.getThemes();
        } else {
            return new MetalTheme[0];
        }
    }

    /**
     * Set look and feel as UIManager does, except for applying selected theme
     * in look and feel connector
     */
    public boolean setLookAndFeel(String laf) {
        try {
            XPlafConnector connector = lookUpConnector(laf);
            if (connector != null) {
                connector.setLookAndFeel();
            } else {
                UIManager.setLookAndFeel(laf);
            }
            return true;
        } catch (Exception ex) {
            LOG.error("Cannot set look and feel", ex);
        }
        return false;
    }

    /**
     * Returns currently selected theme for a given laf
     *
     * @param selectedLaf by user
     * @return currently selected theme
     */
    public MetalTheme getCurrentTheme(LookAndFeel selectedLaf) {
        /*
         * Look up connector for current look and feel
         */
        XPlafConnector connector = lookUpConnector(selectedLaf);
        if (connector != null) {
            return connector.getCurrentTheme();
        }
        return null;
    }

    /**
     * Returns currently selected theme for a current laf
     *
     * @return currently selected theme
     */
    public MetalTheme getCurrentTheme() {
        /*
         * Look up connector for current look and feel
         */
        XPlafConnector connector = lookUpConnector(UIManager.getLookAndFeel());
        if (connector != null) {
            return connector.getCurrentTheme();
        }
        return null;
    }

    /**
     * Sets current theme on current plaf
     *
     * @param laf   class of laf to be set with new theme
     * @param theme class of theme to be set
     */
    public void setCurrentTheme(String laf, String theme) {
        /*
         * Look up connector for current look and feel
         */
        XPlafConnector connector = lookUpConnector(laf);
        if (connector != null) {
            connector.setCurrentTheme(theme);
        }
    }
}