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.
This commit is contained in:
dchandler 2002-11-18 16:12:25 +00:00
parent 77b8c5e424
commit d200b03d66
12 changed files with 529 additions and 93 deletions

121
build.xml
View file

@ -1,5 +1,11 @@
<!-- @author David Chandler, dchandler@users.sourceforge.net
FIXME
Right now, the web-start-releases and self-contained-dist
targets hard-code the paths of the JARs/ZIPs they need. Be
sure you have yours in the right place.
FIXME
We have a document,
http://thdltools.sourceforge.net/BuildSystems.html, that
describes how to use this file to build Savant, Jskad,
@ -158,10 +164,8 @@
description="runs every target in this buildfile in a smart order; useful for testing the buildfile and your build environment" />
<!-- DLC FIXME: generate as-nearly-self-contained-as-possible Savant
and QuillDriver -->
<target name="self-contained-dist"
depends="jskad-all-in-one-dist"
depends="jskad-all-in-one-dist,savant-all-in-one-dist,qd-all-in-one-dist"
description="JARs up everything into self-contained JARs for double-click, classpath-worry-free joy" />
<target name="dist"
@ -175,7 +179,10 @@
<target name="jskad-compile" depends="init"
description="compiles Jskad" >
<antcall target="create-timestamp-source-code"/>
<antcall target="copy-tmw-fonts-to-bin-dir">
<param name="my.bin" value="${jskadbin}"/>
</antcall>
<antcall target="create-timestamp-source-code"/> <!-- DLC NOW! The -run targets are mucking with this! It isn't fatal, but it should be fixed. -->
<antcall target="our-internal-javac-task">
<param name="mybin" value="${jskadbin}"/>
<param name="my.included.source.file"
@ -204,6 +211,10 @@
<target name="savant-compile" depends="init"
description="compiles Savant" >
<antcall target="copy-tmw-fonts-to-bin-dir">
<param name="my.bin" value="${savantbin}"/>
</antcall>
<antcall target="create-timestamp-source-code"/>
<antcall target="our-internal-javac-task">
<param name="mybin" value="${savantbin}"/>
<param name="my.included.source.file"
@ -240,6 +251,10 @@
<!-- Builds the standalone translation tool: -->
<target name="tt-standalone-compile" depends="init"
description="compiles the standalone Translation Tool" >
<antcall target="copy-tmw-fonts-to-bin-dir">
<param name="my.bin" value="${ttstandalonebin}"/>
</antcall>
<antcall target="create-timestamp-source-code"/>
<antcall target="our-internal-javac-task">
<param name="mybin" value="${ttstandalonebin}"/>
<param name="my.included.source.file"
@ -269,6 +284,10 @@
Compiling with J2SDK 1.3 does so by default, by the way. -->
<target name="tt-handheld-compile" depends="init"
description="compiles the handheld Translation Tool" >
<antcall target="copy-tmw-fonts-to-bin-dir">
<param name="my.bin" value="${tthandheldbin}"/>
</antcall>
<antcall target="create-timestamp-source-code"/>
<antcall target="our-internal-javac-task">
<param name="target.jvm" value="1.1"/>
<param name="mybin" value="${tthandheldbin}"/>
@ -284,6 +303,10 @@
<!-- Builds the applet + the Java Web Start translation tool: -->
<target name="tt-applet-plus-jws-compile" depends="init"
description="compiles the applet + Java Web Start forms of the Translation Tool" >
<antcall target="copy-tmw-fonts-to-bin-dir">
<param name="my.bin" value="${ttappletjwsbin}"/>
</antcall>
<antcall target="create-timestamp-source-code"/>
<antcall target="our-internal-javac-task">
<param name="mybin" value="${ttappletjwsbin}"/>
<param name="my.included.source.file"
@ -307,6 +330,10 @@
depends="ttsc-init"
if="found.servlet.classes"
description="compiles the servlet form of the Translation Tool if you've set the j2ee.sdk.home property correctly" >
<antcall target="copy-tmw-fonts-to-bin-dir">
<param name="my.bin" value="${ttservletbin}"/>
</antcall>
<antcall target="create-timestamp-source-code"/>
<!-- For now, these two paths are identical: -->
<path id="ttsc.class.path">
<path refid="all.extras.class.path"/>
@ -344,6 +371,10 @@
<target name="qd-compile" depends="init"
description="compiles QuillDriver" >
<!-- Compile the java code from ${source} into ${qdbin} -->
<antcall target="copy-tmw-fonts-to-bin-dir">
<param name="my.bin" value="${qdbin}"/>
</antcall>
<antcall target="create-timestamp-source-code"/>
<antcall target="our-internal-javac-task">
<param name="mybin" value="${qdbin}"/>
<param name="my.included.source.file"
@ -387,33 +418,32 @@
description="Builds the Java Web Start version of Jskad">
<antcall target="compile-from-scratch-and-call-jws-subbuild">
<param name="my.app" value="Jskad"/>
<param name="my.prereq" value="jskad-dist"/>
<param name="jwsjarsuffix" value="-self-contained"/>
<param name="my.prereq" value="jskad-all-in-one-dist"/>
<param name="lib" value="${jwslib}"/>
</antcall>
</target>
<!-- DLC FIXME: package up all the XML jars and the JMF jars and libraries that Savant uses.
-->
<target name="savant-jws"
depends="init"
description="Builds the Java Web Start version of Savant">
<antcall target="compile-from-scratch-and-call-jws-subbuild">
<param name="my.app" value="Savant"/>
<param name="my.prereq" value="savant-dist"/>
<param name="jwsjarsuffix" value="-self-contained"/>
<param name="my.prereq" value="savant-all-in-one-dist"/>
<param name="lib" value="${jwslib}"/>
</antcall>
</target>
<!-- DLC FIXME: package up all the XML jars and the JMF jars and libraries that QuillDriver uses.
-->
<target name="qd-jws"
depends="init"
description="Builds the Java Web Start version of QuillDriver">
<antcall target="compile-from-scratch-and-call-jws-subbuild">
<param name="my.app" value="QuillDriver"/>
<param name="my.prereq" value="qd-dist"/>
<param name="jwsjarsuffix" value="-self-contained"/>
<param name="my.prereq" value="qd-all-in-one-dist"/>
<param name="lib" value="${jwslib}"/>
</antcall>
</target>
@ -424,6 +454,7 @@
description="Builds the Java Web Start version of the translation tool">
<antcall target="compile-from-scratch-and-call-jws-subbuild">
<param name="my.app" value="DictionarySearchAppletAndJavaWebStart"/>
<param name="jwsjarsuffix" value=""/>
<param name="my.prereq" value="tt-applet-plus-jws-dist"/>
<param name="lib" value="${jwslib}"/>
</antcall>
@ -548,7 +579,7 @@
<!-- DLC FIXME: This used to inlude Jskad2Javascript.class, etc. But it no longer does. Compile those extra files! -->
<!-- DLC FIXME: This used to inlude Jskad2Javascript.class, etc. But it no longer does. Compile those extra files, if Edward hasn't removed them! -->
<target name="jskad-all-in-one-dist" depends="jskad-compile"
description="generates the self-contained binary distribution for Jskad" >
<!-- Now put everything in ${bin} and ${ext}/netscape, plus
@ -569,6 +600,40 @@
</target>
<target name="savant-all-in-one-dist" depends="savant-compile"
description="generates the self-contained binary distribution for Savant" >
<!-- Put everything in ${savantbin} into the JAR file after unpacking the
JARs/ZIPs we need to ${savantbin}. -->
<antcall target="copy-SQD-jars">
<param name="unjardest" value="${savantbin}"/>
</antcall>
<jar jarfile="${lib}/Savant-self-contained${my.jar.suffix}.jar"
basedir="${savantbin}">
<manifest>
<attribute name="Main-Class" value="org.thdl.savant.SavantShell"/>
</manifest>
</jar>
<delete dir="${savantbin}"/>
</target>
<target name="qd-all-in-one-dist" depends="qd-compile"
description="generates the self-contained QuillDriver binary distribution" >
<!-- Put everything in ${savantbin} into the JAR file after unpacking the
JARs/ZIPs we need to ${savantbin}. -->
<antcall target="copy-SQD-jars">
<param name="unjardest" value="${qdbin}"/>
</antcall>
<jar jarfile="${lib}/QuillDriver-self-contained${my.jar.suffix}.jar"
basedir="${qdbin}">
<manifest>
<attribute name="Main-Class" value="org.thdl.quilldriver.QDShell"/>
</manifest>
</jar>
<delete dir="${qdbin}"/>
</target>
<target name="clean"
description="cleans up a few things, but not all (not the Javadocs or the JWS releases, e.g.)" >
<!-- Delete the ${bin} and ${dist} directory trees -->
@ -689,11 +754,11 @@
</target>
<!-- DLC FIXME: build the tt-servlet release if the J2EE SDK is present. -->
<!-- DLC FIXME build web start WARs -->
<!-- DLC FIXME: build the tt-servlet release if the J2EE SDK is present. UPDATE: doesn't it do this? -->
<!-- See http://thdltools.sf.net/BuildSystems.html for info on
how to use this target. Note that we must do a distclean
because Ant doesn't always recompile when it should. -->
because Ant doesn't always recompile when it should unless you use a
special task. -->
<target name="releases"
description="builds the releases under 'dist/releases/' after doing a distclean"
depends="distclean,init">
@ -921,7 +986,7 @@
</security>
<resources>
<j2se version="1.2+"/>
<jar href="Jskad.jar" />
<jar href="Jskad-self-contained.jar" />
</resources>
<application-desc />
</jnlp>
@ -966,7 +1031,7 @@
</security>
<resources>
<j2se version="1.2+"/>
<jar href="Savant.jar" />
<jar href="Savant-self-contained.jar" />
</resources>
<application-desc />
</jnlp>
@ -1009,7 +1074,7 @@
</security>
<resources>
<j2se version="1.2+"/>
<jar href="QuillDriver.jar" />
<jar href="QuillDriver-self-contained.jar" />
</resources>
<application-desc />
</jnlp>
@ -1141,6 +1206,26 @@ public class ThdlVersion {
]]></echo>
</target>
<target name="copy-SQD-jars"
description="Unpacks the JARs/WARs/ZIP files that Savant and QuillDriver use to the chosen bin/ directory">
<unjar src="${ext}/jdom.jar" dest="${unjardest}"/>
<unjar src="${ext}/xml-apis.jar" dest="${unjardest}"/>
<unjar src="${ext}/xalan.jar" dest="${unjardest}"/>
<unjar src="${ext}/xercesImpl.jar" dest="${unjardest}"/>
<unjar src="${ext}/jmf.jar" dest="${unjardest}"/>
<unzip src="${ext}/drop-ins/QTJava.zip" dest="${unjardest}"/>
<!-- One or more of the above may have a META-INF directory. We don't
want theirs to overwrite our own, so we delete it. -->
<delete dir="${unjardest}/META-INF"/>
</target>
<target name="copy-tmw-fonts-to-bin-dir"
description="Unpacks the JARs/WARs/ZIP files that Savant and QuillDriver use to the chosen bin/ directory">
<copy todir="${my.bin}/Fonts/TibetanMachineWeb">
<fileset dir="Fonts/TibetanMachineWeb"/>
</copy>
</target>
</project>
<!-- My TO-DO list: -->

View file

@ -43,7 +43,7 @@
<target name="package-for-java-web-start"
depends="this-init"
description="Builds the Java Web Start version of ${my.app} given that you have compiled it (and from scratch, since our compilation procedure doesn't konw about dependencies)">
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)">
<!-- First, you must give the passwords so that we can sign the JARs. -->
<fail message="Use 'ant -Dkeystore.password=psst' to sign a Java Web Start WAR file."
@ -89,7 +89,7 @@
<jnlp src="${dist}/${my.app}.jnlp">
<resources>
<fileset dir="${lib}">
<include name="${my.app}.jar" />
<include name="${my.app}${jwsjarsuffix}.jar" />
</fileset>
</resources>
</jnlp>

View file

@ -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

View file

@ -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"};

View file

@ -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 (; i<fonts.length; i++)
if (fonts[i].equals("TibetanMachineWeb"))
{
i=-1;
break;
}
// See if we have the TMW fonts available. If we do,
// allow showing Tibetan as well as Wylie and English.
if (i!=-1)
{
/*
JOptionPane.showMessageDialog(this,
"If you want to see text in Tibetan script, "+
"please visit www.thdl.org to download and "+
"install the Tibetan Machine Web fonts.",
"Note", JOptionPane.INFORMATION_MESSAGE);
*/
int i=0;
if (!ThdlOptions.getBooleanOption("thdl.rely.on.system.tmw.fonts")) {
// We do have the TMW fonts available because we
// manually loaded them.
i = -1;
} else {
// DLC FIXME: scan for this in TibetanMachineWeb.java
// before manually loading the TMW fonts.
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
String fonts[] = ge.getAvailableFontFamilyNames();
for (; i<fonts.length; i++) {
if (fonts[i].equals("TibetanMachineWeb"))
{
i=-1;
break;
}
}
}
if (i!=-1) {
JOptionPane.showMessageDialog(this,
"If you want to see text in Tibetan script, "+
"please set the option " +
"thdl.rely.on.system.tmw.fonts" +
" to false.",
"Note", JOptionPane.INFORMATION_MESSAGE);
TranscriptView[] views = new TranscriptView[3];
views[0] = new org.thdl.savant.tib.Wylie(isr);

View file

@ -495,6 +495,20 @@ public class DuffPane extends TibetanPane implements KeyListener, FocusListener
getTibDoc().setTibetanFontSize(size);
}
/**
* Like {@link #setTibetanFontSize(int)}, but should be called only
* when the user has somewhat explicitly chosen the font size.
* This will set the font size but also record this as a user
* preference. Then you can choose to save the user preferences
* via {@link org.thdl.util.ThdlOptions.saveUserPreferences()}.
*
* @param size a point size
*/
public void setByUserTibetanFontSize(int size) {
ThdlOptions.setUserPreference("thdl.default.tibetan.font.size", size);
setTibetanFontSize(size);
}
/**
* Gets the current point size for Tibetan text.
* @return the current default font size for Tibetan
@ -517,6 +531,15 @@ public class DuffPane extends TibetanPane implements KeyListener, FocusListener
StyleConstants.setFontSize(romanAttributeSet, size);
}
/** Like {@link #setRomanAttributeSet}, but allows for noting the
* (explicit or implicit) choice in the user's preferences
* file. */
public void setByUserRomanAttributeSet(String font, int size) {
ThdlOptions.setUserPreference("thdl.default.roman.font.face", font);
ThdlOptions.setUserPreference("thdl.default.roman.font.size", size);
setRomanAttributeSet(font, size);
}
/**
* Gets the current point size for non-Tibetan text.
* @return the current default font size for non-Tibetan

View file

@ -112,7 +112,18 @@ public class Jskad extends JPanel implements DocumentListener {
/** Do not use this JPanel constructor. */
private Jskad(LayoutManager lm, boolean isDB) { super(lm, isDB); }
/** Saves user preferences to disk if possible. */
private static void savePreferencesAction() {
try {
ThdlOptions.saveUserPreferences();
} catch (IOException ioe) {
System.out.println("IO Exception saving user preferences to " + ThdlOptions.getUserPreferencesPath());
ioe.printStackTrace();
ThdlDebug.noteIffyCode();
}
}
/**
* @param parent the object that embeds this instance of Jskad.
@ -249,16 +260,28 @@ public class Jskad extends JPanel implements DocumentListener {
editMenu.add(selectallItem);
}
JMenuItem preferencesItem = new JMenuItem("Preferences");
preferencesItem.addActionListener(new ThdlActionListener() {
public void theRealActionPerformed(ActionEvent e) {
getPreferences();
}
});
editMenu.addSeparator();
editMenu.add(preferencesItem);
{
JMenuItem preferencesItem = new JMenuItem("Preferences");
preferencesItem.addActionListener(new ThdlActionListener() {
public void theRealActionPerformed(ActionEvent e) {
getPreferences();
}
});
editMenu.addSeparator();
editMenu.add(preferencesItem);
}
menuBar.add(editMenu);
{
JMenuItem preferencesItem = new JMenuItem("Save preferences to " + ThdlOptions.getUserPreferencesPath());
preferencesItem.addActionListener(new ThdlActionListener() {
public void theRealActionPerformed(ActionEvent e) {
savePreferencesAction();
}
});
editMenu.add(preferencesItem);
}
menuBar.add(editMenu);
JMenu toolsMenu = new JMenu("Tools");
@ -347,6 +370,15 @@ public class Jskad extends JPanel implements DocumentListener {
menuBar.add(infoMenu);
/* Initialize dp before calling
JskadKeyboard.activate(DuffPane) or dp.toggleLanguage(). */
if (ThdlOptions.getBooleanOption(Jskad.enableKeypressStatusProp)) {
dp = new DuffPane(statusBar);
} else {
dp = new DuffPane();
}
JToolBar toolBar = new JToolBar();
toolBar.setBorder(null);
toolBar.addSeparator();
@ -355,9 +387,30 @@ public class Jskad extends JPanel implements DocumentListener {
String[] input_modes = {"Tibetan","Roman"};
final JComboBox inputmethods = new JComboBox(input_modes);
int initialInputMethod
= ThdlOptions.getIntegerOption("thdl.Jskad.input.method", 0);
if (!dp.isRomanEnabled() && 1 == initialInputMethod) {
initialInputMethod = 0;
System.out.println("Hey yo! Roman input mode is not enabled, but your preference is for Roman mode at startup. Sorry!");
ThdlDebug.noteIffyCode();
}
try {
inputmethods.setSelectedIndex(initialInputMethod);
} catch (IllegalArgumentException e) {
initialInputMethod = 0; // Tibetan is the default.
inputmethods.setSelectedIndex(initialInputMethod);
}
// Because we start in Tibetan mode, we must toggle initially
// if the user wants it that way:
if (1 == initialInputMethod && dp.isRomanEnabled())
dp.toggleLanguage();
inputmethods.addActionListener(new ThdlActionListener() {
public void theRealActionPerformed(ActionEvent e) {
switch (inputmethods.getSelectedIndex()) {
int si = inputmethods.getSelectedIndex();
ThdlOptions.setUserPreference("thdl.Jskad.input.method", si);
switch (si) {
case 0: //Tibetan
if (dp.isRomanMode())
dp.toggleLanguage();
@ -380,15 +433,6 @@ public class Jskad extends JPanel implements DocumentListener {
toolBar.add(new JLabel("Keyboard:"));
toolBar.addSeparator();
/* Initialize dp before calling
JskadKeyboard.activate(DuffPane). */
if (ThdlOptions.getBooleanOption(Jskad.enableKeypressStatusProp)) {
dp = new DuffPane(statusBar);
} else {
dp = new DuffPane();
}
final JComboBox keyboards
= new JComboBox(keybdMgr.getIdentifyingStrings());
int initialKeyboard
@ -402,7 +446,10 @@ public class Jskad extends JPanel implements DocumentListener {
keybdMgr.elementAt(initialKeyboard).activate(dp);
keyboards.addActionListener(new ThdlActionListener() {
public void theRealActionPerformed(ActionEvent e) {
int ki = keyboards.getSelectedIndex();
keybdMgr.elementAt(keyboards.getSelectedIndex()).activate(dp);
ThdlOptions.setUserPreference("thdl.default.tibetan.keyboard",
ki);
}
});
toolBar.add(keyboards);
@ -493,11 +540,12 @@ public class Jskad extends JPanel implements DocumentListener {
int size;
try {
size = Integer.parseInt(tibetanFontSizes.getSelectedItem().toString());
dp.setByUserTibetanFontSize(size);
}
catch (NumberFormatException ne) {
size = dp.getTibetanFontSize();
dp.setTibetanFontSize(size);
}
dp.setTibetanFontSize(size);
String font = romanFontFamilies.getSelectedItem().toString();
try {
@ -506,7 +554,7 @@ public class Jskad extends JPanel implements DocumentListener {
catch (NumberFormatException ne) {
size = dp.getRomanFontSize();
}
dp.setRomanAttributeSet(font, size);
dp.setByUserRomanAttributeSet(font, size);
}
private void newFile() {
@ -991,6 +1039,18 @@ public class Jskad extends JPanel implements DocumentListener {
f.setLocation(d.width/8, d.height/8);
f.getContentPane().add(new Jskad(f));
f.setVisible(true);
/* Make it so that any time the user exits Jskad by
* (almost) any means, the user's preferences are saved if
* the SecurityManager allows it and the path is
* correct. */
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
savePreferencesAction();
}
}
);
} catch (ThdlLazyException e) {
// FIXME: tell the users how to submit bug reports.
System.err.println("Jskad has a BUG:");

View file

@ -27,7 +27,7 @@ import org.thdl.tib.input.JskadKeyboard;
public class JskadKeyboardFactory {
public static JskadKeyboard[] getAllAvailableJskadKeyboards() {
return new JskadKeyboard[] {
new JskadKeyboard("Extended Wylie Keyboard",
new JskadKeyboard("Extended Wylie",
null,
"Wylie_keyboard.rtf"),
new JskadKeyboard("TCC Keyboard #1",
@ -39,7 +39,7 @@ public class JskadKeyboardFactory {
new JskadKeyboard("Sambhota Keymap One",
"sambhota_keyboard_1.ini",
"Sambhota_keymap_one.rtf"),
new JskadKeyboard("Asian Classics Input Project (ACIP) Keyboard",
new JskadKeyboard("Asian Classics Input Project (ACIP)",
"acip_keyboard.ini",
null)
};

View file

@ -29,11 +29,17 @@ import java.awt.font.*;
import org.thdl.util.ThdlDebug;
import org.thdl.util.Trie;
import org.thdl.util.ThdlOptions;
/**
* Interfaces between Extended Wylie and the TibetanMachineWeb fonts.
* To do this this must first read the code table, which lives in "tibwn.ini",
* and which must be found in the same directory as this class.
* To do this this must first read the code table, which lives in
* "tibwn.ini", and which must be found in the same directory as this
* class. Note that WylieWord has its own copy of this file, so edit
* both or neither.
*
* <p>In 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<webFontAttributeSet.length; i++) {
webFontAttributeSet[i] = new SimpleAttributeSet();
@ -1184,6 +1229,10 @@ public static boolean isTopVowel(DuffCode dc) {
@return true iff this is a tsheg or whitespace or the like */
public static boolean isTMWFontCharBreakable(char ch) {
// DLC FIXME: treat whitespace differently than you do
// punctuation. And treat "/ka nga/", Tibetan verse,
// specially in the caller of this method.
if (false) {
//<?Input:Punctuation?>
int ord = (int)ch;

View file

@ -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;
}
}
}

View file

@ -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);

View file

@ -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
* <code>setUserPreference(..)</code> 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
* <code>thdl.user.options.directory</code>
*/
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);
}
}