org.fife.ui.app.ThirdPartyLookAndFeelManager Maven / Gradle / Ivy
/*
* 03/11/2005
*
* ThirdPartyLookAndFeelManager.java - Class that can read an XML file
* specifying all 3rd party Look and Feels available to a GUIApplication.
* Copyright (C) 2005 Robert Futrell
* http://fifesoft.com/rtext
* Licensed under a modified BSD license.
* See the included license file for details.
*/
package org.fife.ui.app;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.InputSource;
import org.fife.ui.app.ExtendedLookAndFeelInfo;
/**
* NOTE: Specifying LookAndFeels in this XML file is done at your own risk!
* If a LookAndFeel throws an Exception on the EDT, for any reason (needs
* special configuration not handled by this LAF manager, requires a newer
* JRE version than is specified in the XML, etc.), it can hose the
* GUIApplication
and keep it from running!
*
* A class capable of reading an XML file specifying 3rd party Look and Feel
* JAR files, and returning an array of information about the Look and Feels,
* so your GUIApplication
can use them.
*
* The XML file read should have the following format:
*
* <?xml version="1.0" encoding="UTF-8" ?>
* <ThirdPartyLookAndFeels>
* <LookAndFeel name="name" class="class" jars="jar"/>
* <LookAndFeel name="name" class="class" jars="jar" minJavaVersion="1.6"/>
* ... other LookAndFeel tags if desired ...
* </ThirdPartyLookAndFeels>
*
*
* where name
is the name of the Look and Feel (as appears in
* RText's menu), class
is the main Look and Feel class, such as
* org.fife.plaf.OfficeXP.OfficeXPLookAndFeel
, and
* jars
is the path(s) to the JAR file(s) containing the Look and
* Feel, relative to the install location of the specified
* GUIApplication
. The minJavaVersion
attribute is
* optional, and specifies the minimum Java version the JRE must be for the
* application to offer this LookAndFeel as a choice. This should be a double
* value, such as "1.5", "1.6", etc.
*
* @author Robert Futrell
* @version 1.0
*/
public class ThirdPartyLookAndFeelManager {
/**
* The root directory of the application.
*/
private String appRoot;
private List lnfInfo;
private URLClassLoader lafLoader;
private static final String CLASS = "class";
private static final String JARS = "jars";
private static final String DIR = "dir";
private static final String LOOK_AND_FEEL = "LookAndFeel";
private static final String MIN_JAVA_VERSION = "minJavaVersion";
private static final String NAME = "name";
/**
* Constructor.
*/
public ThirdPartyLookAndFeelManager(String appRoot) {
this.appRoot = appRoot;
URL[] urls = null;
lnfInfo = load3rdPartyLookAndFeelInfo("lnfs/lookandfeels.xml");
try {
int count = lnfInfo==null ? 0 : lnfInfo.size();
// 3rd party Look and Feel jars? Add them to classpath.
// NOTE: The lines of code below MUST be in the order they're
// in or stuff breaks for some reason; I'm not sure why...
if (count>0) {
List lnfJarUrlList = new ArrayList();
for (Iterator i=lnfInfo.iterator(); i.hasNext(); ) {
ExtendedLookAndFeelInfo info =
(ExtendedLookAndFeelInfo)i.next();
urls = info.getURLs(appRoot);
for (int j=0; j0) {
sb.append(',');
}
sb.append(files[i].getPath());
}
//System.out.println("--- " + sb.toString());
return sb.length()==0 ? null : sb.toString();
}
public ClassLoader getLAFClassLoader() {
return lafLoader;
}
/**
* Returns an array with each element representing a 3rd party Look and
* Feel available to your GUI application.
*
* @param xmlFile The XML file specifying the 3rd party Look and Feels.
* @return A list of {@link ExtendedLookAndFeelInfo}s.
*/
private List load3rdPartyLookAndFeelInfo(String xmlFile) {
File file = new File(appRoot, xmlFile);
if (!file.isFile()) {
return null;
}
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = null;
Document doc = null;
try {
db = dbf.newDocumentBuilder();
InputSource is = new InputSource(new BufferedReader(
new InputStreamReader(new FileInputStream(file), "UTF-8")));
is.setEncoding("UTF-8");
doc = db.parse(is);
} catch (RuntimeException re) { // FindBugs
throw re;
} catch (Exception e) {
e.printStackTrace();
return null;
}
// Traverse the XML tree.
ArrayList lafInfo = new ArrayList(1);
try {
loadFromXML(doc.getDocumentElement(), lafInfo);
} catch (IOException ioe) {
ioe.printStackTrace();
}
return lafInfo;
}
/**
* Used in parsing the XML file containing the 3rd party look and feels.
*
* @param node The root node of the parsed XML document.
* @param lafInfo An array list of ExtendedLookAndFeelInfo
s.
* @throws IOException If an error occurs while parsing the XML.
*/
private static void loadFromXML(Element root, ArrayList lafInfo)
throws IOException {
if (root==null) {
throw new IOException("XML error: node==null!");
}
NodeList children = root.getChildNodes();
for (int i=0; i0) {
throw new IOException("XML error: LookAndFeel " +
"tags shouldn't have children!");
}
NamedNodeMap attributes = child.getAttributes();
if (attributes==null || attributes.getLength()<3) {
throw new IOException("XML error: LookAndFeel " +
"tags should have three attributes!");
}
String name = null;
String className = null;
String jars = null;
double minVersion = 0;
for (int j=0; j0) {
String javaSpecVersion = System.getProperty("java.specification.version");
try {
double javaSpecVersionVal = Double.parseDouble(javaSpecVersion);
add = javaSpecVersionVal >= minVersion;
} catch (NumberFormatException nfe) {
nfe.printStackTrace();
}
}
if (add) {
lafInfo.add(new ExtendedLookAndFeelInfo(name,
className, jars));
}
}
// Anything else is an error.
else {
throw new IOException("XML error: Unknown element " +
"node: " + elemName);
}
}
}
}
}