diff --git a/build.xml b/build.xml index 49ed85a..2039709 100644 --- a/build.xml +++ b/build.xml @@ -1,5 +1,11 @@ - + + + + + + + + + + + + + + + + @@ -284,6 +303,10 @@ + + + + + + + + @@ -344,6 +371,10 @@ + + + + - + + - - + + - - + + @@ -424,6 +454,7 @@ description="Builds the Java Web Start version of the translation tool"> + @@ -548,7 +579,7 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -689,11 +754,11 @@ - - + + because Ant doesn't always recompile when it should unless you use a + special task. --> @@ -921,7 +986,7 @@ - + @@ -966,7 +1031,7 @@ - + @@ -1009,7 +1074,7 @@ - + @@ -1141,6 +1206,26 @@ public class ThdlVersion { ]]> + + + + + + + + + + + + + + + + + diff --git a/jwsbuild.xml b/jwsbuild.xml index 29c58cc..63408dd 100644 --- a/jwsbuild.xml +++ b/jwsbuild.xml @@ -43,7 +43,7 @@ + description="Builds the Java Web Start version of ${my.app} given that you have compiled it to a JAR with the suffix ${jwsjarsuffix} (and from scratch, since our compilation procedure doesn't konw about dependencies)"> - + diff --git a/source/options.txt b/source/options.txt index f6d272d..568bd0e 100644 --- a/source/options.txt +++ b/source/options.txt @@ -19,6 +19,16 @@ ######################### User Preferences ########################### ############################################################################ +# Set this to the full path of the user preferences file, or to the +# empty string if you wish to use the default values, which are +# system-specific. +thdl.user.options.directory = + +# Should the TibetanMachineWeb fonts not be loaded from within the JAR? Set +# this to true if you can get away with it and want your THDL tools to load +# faster. +thdl.rely.on.system.tmw.fonts = false + # Set this to your preference of one of the following values: # # Framework: QuickTime for Java Value: org.thdl.media.SmartQT4JPlayer @@ -32,8 +42,14 @@ thdl.media.player = org.thdl.media.SmartJMFPlayer # 1: TCC Keyboard #1 # 2: TCC Keyboard #2 # 3: Sambhota Keymap One +# 4: *ALPHA VERSION* ACIP Keyboard thdl.default.tibetan.keyboard = 0 +# Should Jskad be in Roman input mode or Tibetan input mode upon startup? +# 0: Tibetan +# 1: Roman +thdl.Jskad.input.method = 0 + # Set this to the default font face for Roman input. No error is # given if this font is not found. thdl.default.roman.font.face = Serif @@ -52,7 +68,7 @@ thdl.Jskad.disable.status.bar = false # The message displayed in Jskad's status bar when you start it up # with thdl.Jskad.disable.status.bar set to false: -thdl.Jskad.initial.status.message = Welcome to Jskad! +thdl.Jskad.initial.status.message = Welcome to Jskad\! # Set this to true if you don't want Jskad to ask you "Do you really # want to quit?" when you try to exit the program. (Your changes will diff --git a/source/org/thdl/media/SmartPlayerFactory.java b/source/org/thdl/media/SmartPlayerFactory.java index 7aa89c3..80c5c80 100644 --- a/source/org/thdl/media/SmartPlayerFactory.java +++ b/source/org/thdl/media/SmartPlayerFactory.java @@ -25,6 +25,7 @@ import java.util.ArrayList; import org.thdl.util.*; import org.thdl.util.ThdlDebug; +import org.thdl.util.OperatingSystemUtils; public class SmartPlayerFactory { public static List moviePlayers; @@ -33,23 +34,28 @@ public class SmartPlayerFactory { private SmartPlayerFactory() { } public static List getAllAvailableSmartPlayers() { - String os; - try { - os = System.getProperty("os.name").toLowerCase(); - } catch (SecurityException e) { - os = "unknown"; - } + String defaultPlayer, player; + switch (OperatingSystemUtils.getOSType()) { + case OperatingSystemUtils.MAC: + //macs default to org.thdl.media.SmartQT4JPlayer + defaultPlayer = "org.thdl.media.SmartQT4JPlayer"; + break; + case OperatingSystemUtils.WIN32: + //windows defaults to SmartJMFPlayer + defaultPlayer = "org.thdl.media.SmartJMFPlayer"; + break; + default: + //put linux etc. here + defaultPlayer = "org.thdl.media.SmartJMFPlayer"; + break; + } + + player + = ThdlOptions.getStringOption("thdl.media.player", defaultPlayer); - String defaultPlayer; - if (os.indexOf("mac") != -1) //macs default to org.thdl.media.SmartQT4JPlayer - defaultPlayer = ThdlOptions.getStringOption("thdl.media.player", "org.thdl.media.SmartQT4JPlayer"); - else if (os.indexOf("windows") != -1) //windows defaults to SmartJMFPlayer - defaultPlayer = ThdlOptions.getStringOption("thdl.media.player", "org.thdl.media.SmartJMFPlayer"); - else //put linux etc. here - defaultPlayer = ThdlOptions.getStringOption("thdl.media.player", "org.thdl.media.SmartJMFPlayer"); String[] possiblePlayers; - if (defaultPlayer.equals("org.thdl.media.SmartJMFPlayer")) + if (player.equals("org.thdl.media.SmartJMFPlayer")) possiblePlayers = new String[] {"org.thdl.media.SmartJMFPlayer", "org.thdl.media.SmartQT4JPlayer"}; else possiblePlayers = new String[] {"org.thdl.media.SmartQT4JPlayer", "org.thdl.media.SmartJMFPlayer"}; diff --git a/source/org/thdl/savant/SavantShell.java b/source/org/thdl/savant/SavantShell.java index 220da44..23d1045 100644 --- a/source/org/thdl/savant/SavantShell.java +++ b/source/org/thdl/savant/SavantShell.java @@ -37,6 +37,7 @@ import org.thdl.util.ThdlActionListener; import org.thdl.util.RTFPane; import org.thdl.util.SimpleFrame; import org.thdl.util.ThdlI18n; +import org.thdl.util.ThdlOptions; public class SavantShell extends JFrame @@ -339,25 +340,34 @@ public class SavantShell extends JFrame } if (project.equals("THDL")) { - GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - String fonts[] = ge.getAvailableFontFamilyNames(); - int i=0; - for (; iIn addition, this class optionally loads the TibetanMachineWeb +* fonts manually via {@link #readInFontFiles()}. * @author Edward Garrett, Tibetan and Himalayan Digital Library * @version 1.0 */ @@ -258,12 +264,51 @@ public class TibetanMachineWeb { setKeyboard(keyboard); } + /** Assumes that the TMW font files are resources associated with + * this class and loads those font files. + * @throws Error if that assumption does not hold */ + private static void readInFontFiles() { + /* Note the leading slashes on these paths: */ + readInFontFile("/Fonts/TibetanMachineWeb/timwn.ttf"); + readInFontFile("/Fonts/TibetanMachineWeb/timwn1.ttf"); + readInFontFile("/Fonts/TibetanMachineWeb/timwn2.ttf"); + readInFontFile("/Fonts/TibetanMachineWeb/timwn3.ttf"); + readInFontFile("/Fonts/TibetanMachineWeb/timwn4.ttf"); + readInFontFile("/Fonts/TibetanMachineWeb/timwn5.ttf"); + readInFontFile("/Fonts/TibetanMachineWeb/timwn6.ttf"); + readInFontFile("/Fonts/TibetanMachineWeb/timwn7.ttf"); + readInFontFile("/Fonts/TibetanMachineWeb/timwn8.ttf"); + readInFontFile("/Fonts/TibetanMachineWeb/timwn9.ttf"); + } + + /** Assumes that the TMW font file at the given path is a resource + * associated with this class and loads that font file. + * @param path a path within the JAR containing this class file + * @throws Error if that assumption does not hold */ + private static void readInFontFile(String path) { + try { + InputStream is = TibetanMachineWeb.class.getResourceAsStream(path); + if (null == is) { + throw new Error("You selected the optional behavior of loading the TibetanMachineWeb font family manually, but the resource " + + path + " could not be found."); + } + Font.createFont(Font.TRUETYPE_FONT, is); + } catch( Exception e ) { + e.printStackTrace(); + ThdlDebug.noteIffyCode(); + } + } + /** * This method reads the data file ("tibwn.ini"), constructs * the character, punctuation, and vowel lists, as well as * performing other acts of initialization. */ private static void readData() { + if (!ThdlOptions.getBooleanOption("thdl.rely.on.system.tmw.fonts")) { + readInFontFiles(); + } + webFontAttributeSet[0] = null; for (int i=1; i int ord = (int)ch; diff --git a/source/org/thdl/util/OperatingSystemUtils.java b/source/org/thdl/util/OperatingSystemUtils.java new file mode 100644 index 0000000..9162dda --- /dev/null +++ b/source/org/thdl/util/OperatingSystemUtils.java @@ -0,0 +1,73 @@ +/* +The contents of this file are subject to the THDL Open Community License +Version 1.0 (the "License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License on the THDL web site +(http://www.thdl.org/). + +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +License for the specific terms governing rights and limitations under the +License. + +The Initial Developer of this software is the Tibetan and Himalayan Digital +Library (THDL). Portions created by the THDL are Copyright 2001 THDL. +All Rights Reserved. + +Contributor(s): ______________________________________. +*/ + +package org.thdl.util; + +/** This class contains our operating-system-specific code. This + * class is not instantiable. + */ +public class OperatingSystemUtils { + + /** This means that, because of security restrictions or the like, + * we cannot determine the OS. */ + public static final int UNKNOWN = 0; + /** Not WIN32, not MAC -- maybe a *nix box. */ + public static final int OTHER = 1; + /** Windows 9x, Me, 200*, or XP */ + public static final int WIN32 = 2; + /** Mac (OS X or otherwise) */ + public static final int MAC = 3; + + /** Do not instantiate this class. */ + private OperatingSystemUtils() { } + + /** cached result of {@link #getOSName()} */ + private static String OSName = null; + + /** Returns the lowercase name of the operating system, or + * "unknown" if the operating system's identity cannot be + * determined. */ + public static String getOSName() { + if (null == OSName) { + try { + OSName = System.getProperty("os.name").toLowerCase(); + } catch (SecurityException e) { + OSName = null; + } + if (null == OSName) { + OSName = "unknown"; + } + } + return OSName; + } + + /** Returns either {@link #UNKNOWN}, {@link #WIN32}, {@link #MAC}, + * or {@link #OTHER}. */ + public static int getOSType() { + String os = getOSName(); + if (os.startsWith("mac")) { + return MAC; + } else if (os.startsWith("win")) { + return WIN32; + } else if (os.equals("unknown")) { + return UNKNOWN; + } else { + return OTHER; + } + } +} diff --git a/source/org/thdl/util/ThdlActionListener.java b/source/org/thdl/util/ThdlActionListener.java index 1e37521..349a098 100644 --- a/source/org/thdl/util/ThdlActionListener.java +++ b/source/org/thdl/util/ThdlActionListener.java @@ -138,6 +138,7 @@ public class ThdlActionListener implements ActionListener { class. Handle it well so that users know what's up: */ ThdlDebug.handleClasspathError(null, err); } catch (Throwable t) { + /* FIXME: make aborting optional, and have it off by default */ System.err.println("THDL_ERR 106: This application failed due to the following exception: "); t.printStackTrace(System.err); System.exit(1); diff --git a/source/org/thdl/util/ThdlOptions.java b/source/org/thdl/util/ThdlOptions.java index c8e4fcf..968c118 100644 --- a/source/org/thdl/util/ThdlOptions.java +++ b/source/org/thdl/util/ThdlOptions.java @@ -20,11 +20,14 @@ package org.thdl.util; import java.io.InputStream; import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.File; import java.io.FileNotFoundException; import java.util.Properties; import org.thdl.util.ThdlLazyException; +import org.thdl.util.OperatingSystemUtils; /** * Provides a clean interface to the multi-tiered system of user @@ -184,7 +187,10 @@ public final class ThdlOptions { } private static boolean suppressErrs() { - return false; /* FIXME--make THIS configurable. */ + return false; + /* FIXME--make THIS configurable. It's not a simple thing, + * though, since you can't use the usual prefences mechanism + * because it helps to implement that mechanism. */ } private static void init() { try { @@ -246,10 +252,8 @@ public final class ThdlOptions { // Get the user's properties, if they've set any: userProperties - = tryToGetPropsFromFile("thdl.user.options.file", - // FIXME this default is - // system-dependent: - "C:\\thdl_uopt.txt", + = tryToGetPropsFromFile("thdl.user.options.directory", // DLC NOW FIXME: put in options.txt + getUserPreferencesPath(), systemWideProperties, suppressErrors); } catch (SecurityException e) { @@ -285,8 +289,13 @@ public final class ThdlOptions { boolean suppressErrors) throws FileNotFoundException, SecurityException { - Properties props = defaultProps; String systemPropFileName = System.getProperty(pName, defaultLoc); + + /* The empty string means "use the default location". See + * options.txt. */ + if ("".equals(systemPropFileName)) + systemPropFileName = defaultLoc; + FileInputStream fis = null; try { fis = new FileInputStream(systemPropFileName); @@ -297,12 +306,12 @@ public final class ThdlOptions { if (!suppressErrors) throw e; } else { - // definitely suppress this. On a Mac or - // Unix/Linux box, this'll happen every time - // at present. (FIXME) + // definitely suppress this. On a Mac, I think + // this'll happen every time at present. (FIXME) } } - + + Properties props = defaultProps; if (fis != null) { props = getPropertiesFromStream(fis, suppressErrors, @@ -347,8 +356,112 @@ public final class ThdlOptions { } } } + + /** Saves the user's preferences to a file whose path is the value + * of {@link #getUserPreferencesPath()}. You must call + * setUserPreference(..) for this to be effective. + * @throws IOException if an IO exception occurs while writing to + * the disk. */ + public static void saveUserPreferences() throws IOException { + if (null != userProperties) { + userProperties.store(new FileOutputStream(getUserPreferencesPath()), + " This file was automatically created by a THDL tool.\n" + + "# You may edit this file, but it will be recreated,\n" + + "# so your comments will be lost.\n" + + "# \n" + + "# To understand this file's contents, please see\n" + + "# options.txt in the JAR file.\n" + + "# \n" + + "# Note that this is the user-specific preferences file.\n" + + "# This tool also supports a system-specific preferences\n" + + "# file, which the user-specific preferences override.\n" + + "# \n" + + "# Note also that you can set a JVM preference at run-time.\n" + + "# Doing so will override both system- and user-specific\n" + + "# preferences. On many systems, you do this like so:\n" + + "# 'java -Dthdl.default.tibetan.font.size=36 -jar Jskad.jar'\n" + + "# \n" + + "# There is, unfortunately, no further documentation on the\n" + + "# preferences mechanism at this time. Yell for it!\n" + + "# \n" + + "# Created at:"); // DLC FIXME: document the preferences mechanism. + } + } + + /** This returns the location of the user's preferences file. + * This value may be overridden, by, you guessed it, a JVM, + * built-in, or system-wide preference + * thdl.user.options.directory + */ + public static String getUserPreferencesPath() { + String defaultUserDir; + switch (OperatingSystemUtils.getOSType()) { + case OperatingSystemUtils.MAC: + // where? DLC FIXME + defaultUserDir = "/tmp"; + break; + case OperatingSystemUtils.WIN32: + defaultUserDir = "C:\\"; + break; + default: + //put linux etc. here + defaultUserDir = "/tmp"; + break; + } + + String defaultLoc = System.getProperty("user.home", defaultUserDir); + String systemsOverridingValue + = System.getProperty("thdl.user.options.directory", defaultLoc); + + return (new File(systemsOverridingValue, + "my_thdl_preferences.txt")).getPath(); + } + + /** In order to save preferences, this class must know that the + * user (explicitly or implicitly) has changed a preference, + * either through selecting something in a ComboBox, going + * through a Preferences GUI, or the like. Calling this method + * indicates that the user has changed an integer-valued + * preference pref to value. + * @param pref the preference the user is setting + * @param value the user's new preference + */ + public static void setUserPreference(String pref, int value) { + if (userProperties == null) { + userProperties = new Properties(); // empty + } // else leave it as is. + userProperties.setProperty(pref, String.valueOf(value)); + } + + /** In order to save preferences, this class must know that the + * user (explicitly or implicitly) has changed a preference, + * either through selecting something in a ComboBox, going + * through a Preferences GUI, or the like. Calling this method + * indicates that the user has changed a boolean-valued + * preference pref to value. + * @param pref the preference the user is setting + * @param value the user's new preference + */ + public static void setUserPreference(String pref, boolean value) { + if (userProperties == null) { + userProperties = new Properties(); // empty + } // else leave it as is. + userProperties.setProperty(pref, String.valueOf(value)); + } + + /** In order to save preferences, this class must know that the + * user (explicitly or implicitly) has changed a preference, + * either through selecting something in a ComboBox, going + * through a Preferences GUI, or the like. Calling this method + * indicates that the user has changed a String-valued preference + * pref to value. + * @param pref the preference the user is setting + * @param value the user's new preference + */ + public static void setUserPreference(String pref, String value) { + if (userProperties == null) { + userProperties = new Properties(); // empty + } // else leave it as is. + userProperties.setProperty(pref, value); + } } - - - -