From d200b03d6676b4702903654fb8da195eed7fcce4 Mon Sep 17 00:00:00 2001 From: dchandler Date: Mon, 18 Nov 2002 16:12:25 +0000 Subject: [PATCH] Updated the build system so that you must do a cvs checkout of the 'Fonts' module inside the 'Jskad' module. I.e., you must now have the tree like so: Jskad/ source/ dist/ Fonts/ TibetanMachineWeb/ . . . This is because the THDL tools now optionally (and by default) load the TibetanMachineWeb fonts automatically. Updated the build system so that the 'web-start-releases' and 'self-contained-dist' targets JAR up optional JARs to create double-clickable, self-contained joy. Even the TMW fonts are in the JARs now. Changed the strings describing two Jskad keyboards so that "keyboard" is no longer in the description. It's in the label next to the combo box. Jskad now saves preferences on exit or when the user selects a menu item (that is there for debugging mainly) to ~/my_thdl_preferences.txt on *nix or C:\my_thdl_preferences.txt on Win32. I don't know the correct Mac location. There's a new paradigm for telling org.thdl.util.ThdlOptions that a user preference has been changed. If, for example, a combo box is manipulated so that the ACIP keyboard is selected, then you must call a certain method in ThdlOptions. --- build.xml | 121 ++++++++++++--- jwsbuild.xml | 4 +- source/options.txt | 18 ++- source/org/thdl/media/SmartPlayerFactory.java | 34 +++-- source/org/thdl/savant/SavantShell.java | 46 +++--- source/org/thdl/tib/input/DuffPane.java | 23 +++ source/org/thdl/tib/input/Jskad.java | 104 ++++++++++--- .../thdl/tib/input/JskadKeyboardFactory.java | 4 +- .../org/thdl/tib/text/TibetanMachineWeb.java | 53 ++++++- .../org/thdl/util/OperatingSystemUtils.java | 73 +++++++++ source/org/thdl/util/ThdlActionListener.java | 1 + source/org/thdl/util/ThdlOptions.java | 141 ++++++++++++++++-- 12 files changed, 529 insertions(+), 93 deletions(-) create mode 100644 source/org/thdl/util/OperatingSystemUtils.java 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); + } } - - - -