2002-10-04 04:52:41 +00:00
/ *
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
2003-02-01 06:42:07 +00:00
Library ( THDL ) . Portions created by the THDL are Copyright 2001 - 2003 THDL .
2002-10-04 04:52:41 +00:00
All Rights Reserved .
Contributor ( s ) : ______________________________________ .
* /
package org.thdl.tib.input ;
import java.io.* ;
import java.net.URL ;
import java.awt.* ;
import java.awt.event.* ;
import java.awt.print.* ;
import javax.swing.plaf.basic.* ;
import javax.swing.* ;
import javax.swing.event.* ;
import javax.swing.text.* ;
import javax.swing.text.rtf.* ;
2002-10-20 08:02:16 +00:00
import java.util.Vector ;
2002-10-04 04:52:41 +00:00
import org.thdl.tib.text.* ;
2002-10-06 18:23:27 +00:00
import org.thdl.util.ThdlDebug ;
Added a flexible mechanism for persistent boolean-, integer-, and
string-valued preferences built atop java.util.Properties.
How it works: the jvm is asked first, and then the user's prefs file, if it exists,
then the system-wide prefs file, and then the built-in preferences. Finally, for
robustness, a default may be optionally hard-coded in the source.
I made several things configurable, too:
the default Tibetan keyboard
the default font sizes and faces
whether you want developer-only features enabled
Savant's file extension (.savant)
etc.
The only known problems are the following:
The default location for the user's preferences file is windows-specific,
arbitrary, and not in the user documentation. Likewise for the location of the
system-wide preferences file. You can change them using 'java -D', though.
There is no "Save preferences" option yet, and closing the program does
not save preferences either.
2002-10-14 04:06:05 +00:00
import org.thdl.util.ThdlOptions ;
2002-11-16 19:18:44 +00:00
import org.thdl.util.ThdlVersion ;
2002-10-13 19:22:56 +00:00
import org.thdl.util.StatusBar ;
import org.thdl.util.ThdlActionListener ;
2003-02-01 06:42:07 +00:00
import org.thdl.util.HTMLPane ;
2002-10-13 20:42:23 +00:00
import org.thdl.util.SimpleFrame ;
import org.thdl.util.ThdlLazyException ;
2002-10-13 19:22:56 +00:00
2002-10-06 18:23:27 +00:00
2002-10-04 04:52:41 +00:00
/ * *
* A simple Tibetan text editor . Jskad editors lack most of the
* functionality of a word - processor , but they do provide
* multiple keyboard input methods , as well as
* conversion routines to go back and forth between Extended
* Wylie and TibetanMachineWeb .
* < p >
* Jskad embeds { @link DuffPane DuffPane } , which is the editing
* window where the keyboard logic and most functionality is housed .
* < p >
* Depending on the object passed to the constructor ,
* a Jskad object can be used in either an application or an
* applet .
* @author Edward Garrett , Tibetan and Himalayan Digital Library
* @version 1 . 0
* /
public class Jskad extends JPanel implements DocumentListener {
2002-10-13 19:22:56 +00:00
/ * * the name of the property a developer should set to see
low - level info on how keypresses in " Tibetan " input mode are
being interpreted * /
private final static String enableKeypressStatusProp
= " thdl.Jskad.enable.tibetan.mode.status " ;
2002-10-27 19:12:13 +00:00
/ * * the middleman that keeps code regarding Tibetan keyboards
* clean * /
2003-05-14 03:25:36 +00:00
private final static JskadKeyboardManager keybdMgr ;
static {
try {
keybdMgr
= new JskadKeyboardManager ( JskadKeyboardFactory . getAllAvailableJskadKeyboards ( ) ) ;
} catch ( Exception e ) {
throw new ThdlLazyException ( e ) ;
}
}
2002-10-27 19:12:13 +00:00
2002-10-04 04:52:41 +00:00
private JComboBox fontFamilies , fontSizes ;
private JFileChooser fileChooser ;
private javax . swing . filechooser . FileFilter rtfFilter ;
private javax . swing . filechooser . FileFilter txtFilter ;
private int fontSize = 0 ;
private Object parentObject = null ;
private static int numberOfTibsRTFOpen = 0 ;
private static int x_size ;
private static int y_size ;
/ * *
* The text editing window which this Jskad object embeds .
* /
public DuffPane dp ;
/ * *
* Has the document been saved since it was last changed ?
* /
public boolean hasChanged = false ;
/ * *
* The filename , if any , associated with this instance of Jskad .
* /
public String fileName = null ;
2002-10-13 19:22:56 +00:00
/** the status bar for this frame */
private StatusBar statusBar ;
2002-11-03 17:05:44 +00:00
/** Do not use this JPanel constructor. */
private Jskad ( ) { super ( ) ; }
/** Do not use this JPanel constructor. */
private Jskad ( boolean isDB ) { super ( isDB ) ; }
/** Do not use this JPanel constructor. */
private Jskad ( LayoutManager lm ) { super ( lm ) ; }
/** Do not use this JPanel constructor. */
private Jskad ( LayoutManager lm , boolean isDB ) { super ( lm , isDB ) ; }
2002-11-18 16:12:25 +00:00
/** Saves user preferences to disk if possible. */
2003-06-21 01:26:17 +00:00
private void savePreferencesAction ( ) {
2002-11-18 16:12:25 +00:00
try {
2003-06-21 01:26:17 +00:00
if ( ! ThdlOptions . saveUserPreferences ( ) ) {
JOptionPane . showMessageDialog ( Jskad . this ,
" You previously cleared preferences, \ nso you cannot now save them. " ,
" Cannot Save User Preferences " ,
JOptionPane . PLAIN_MESSAGE ) ;
}
2002-11-18 16:12:25 +00:00
} catch ( IOException ioe ) {
System . out . println ( " IO Exception saving user preferences to " + ThdlOptions . getUserPreferencesPath ( ) ) ;
ioe . printStackTrace ( ) ;
ThdlDebug . noteIffyCode ( ) ;
}
}
2003-06-21 01:26:17 +00:00
/ * * Clears user preferences by deleting the preferences file on
disk . Prompts the user to quit and reopen Jskad . * /
private void clearPreferencesAction ( ) {
try {
ThdlOptions . clearUserPreferences ( ) ;
} catch ( IOException ioe ) {
System . out . println ( " IO Exception deleting user preferences file " + ThdlOptions . getUserPreferencesPath ( ) ) ;
ioe . printStackTrace ( ) ;
ThdlDebug . noteIffyCode ( ) ;
}
JOptionPane . showMessageDialog ( Jskad . this ,
" You must now exit this application and restart \ nbefore default preferences will take effect. " ,
" Clearing Preferences " ,
JOptionPane . PLAIN_MESSAGE ) ;
}
2003-02-01 06:42:07 +00:00
/** pane displaying Jskad's single HTML help file */
private static HTMLPane helpPane ;
2002-11-03 17:05:44 +00:00
2002-10-04 04:52:41 +00:00
/ * *
* @param parent the object that embeds this instance of Jskad .
* Supported objects include JFrames and JApplets . If the parent
* is a JApplet then the File menu is omitted from the menu bar .
* /
public Jskad ( final Object parent ) {
2002-11-03 17:05:44 +00:00
super ( ) ;
Added a flexible mechanism for persistent boolean-, integer-, and
string-valued preferences built atop java.util.Properties.
How it works: the jvm is asked first, and then the user's prefs file, if it exists,
then the system-wide prefs file, and then the built-in preferences. Finally, for
robustness, a default may be optionally hard-coded in the source.
I made several things configurable, too:
the default Tibetan keyboard
the default font sizes and faces
whether you want developer-only features enabled
Savant's file extension (.savant)
etc.
The only known problems are the following:
The default location for the user's preferences file is windows-specific,
arbitrary, and not in the user documentation. Likewise for the location of the
system-wide preferences file. You can change them using 'java -D', though.
There is no "Save preferences" option yet, and closing the program does
not save preferences either.
2002-10-14 04:06:05 +00:00
if ( ThdlOptions . getBooleanOption ( " thdl.Jskad.disable.status.bar " ) ) {
2002-10-13 19:22:56 +00:00
statusBar = null ;
} else {
Added a flexible mechanism for persistent boolean-, integer-, and
string-valued preferences built atop java.util.Properties.
How it works: the jvm is asked first, and then the user's prefs file, if it exists,
then the system-wide prefs file, and then the built-in preferences. Finally, for
robustness, a default may be optionally hard-coded in the source.
I made several things configurable, too:
the default Tibetan keyboard
the default font sizes and faces
whether you want developer-only features enabled
Savant's file extension (.savant)
etc.
The only known problems are the following:
The default location for the user's preferences file is windows-specific,
arbitrary, and not in the user documentation. Likewise for the location of the
system-wide preferences file. You can change them using 'java -D', though.
There is no "Save preferences" option yet, and closing the program does
not save preferences either.
2002-10-14 04:06:05 +00:00
statusBar
= new StatusBar ( ThdlOptions . getStringOption ( " thdl.Jskad.initial.status.message " ,
" Welcome to Jskad! " ) ) ;
2002-10-13 19:22:56 +00:00
}
2002-10-04 04:52:41 +00:00
parentObject = parent ;
numberOfTibsRTFOpen + + ;
JMenuBar menuBar = new JMenuBar ( ) ;
if ( parentObject instanceof JFrame | | parentObject instanceof JInternalFrame ) {
2003-03-11 01:03:19 +00:00
String whereToStart
= ThdlOptions . getStringOption ( " thdl.Jskad.working.directory " ,
null ) ;
fileChooser
= new JFileChooser ( whereToStart . equals ( " " ) ? null : whereToStart ) ;
2002-10-04 04:52:41 +00:00
rtfFilter = new RTFFilter ( ) ;
txtFilter = new TXTFilter ( ) ;
fileChooser . addChoosableFileFilter ( rtfFilter ) ;
JMenu fileMenu = new JMenu ( " File " ) ;
JMenuItem newItem = new JMenuItem ( " New " ) ;
2002-10-22 03:53:33 +00:00
// newItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,java.awt.Event.CTRL_MASK)); //Ctrl-n
2002-10-06 18:23:27 +00:00
newItem . addActionListener ( new ThdlActionListener ( ) {
public void theRealActionPerformed ( ActionEvent e ) {
2002-10-04 04:52:41 +00:00
newFile ( ) ;
}
} ) ;
fileMenu . add ( newItem ) ;
JMenuItem openItem = new JMenuItem ( " Open " ) ;
2002-10-22 03:53:33 +00:00
// openItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O,java.awt.Event.CTRL_MASK)); //Ctrl-o
2002-10-06 18:23:27 +00:00
openItem . addActionListener ( new ThdlActionListener ( ) {
public void theRealActionPerformed ( ActionEvent e ) {
2002-10-04 04:52:41 +00:00
openFile ( ) ;
}
} ) ;
fileMenu . add ( openItem ) ;
if ( parentObject instanceof JFrame ) {
JMenuItem closeItem = new JMenuItem ( " Close " ) ;
2002-10-06 18:23:27 +00:00
closeItem . addActionListener ( new ThdlActionListener ( ) {
public void theRealActionPerformed ( ActionEvent e ) {
2002-10-04 04:52:41 +00:00
if ( ! hasChanged | | hasChanged & & checkSave ( ) ) {
2003-06-21 02:07:51 +00:00
Jskad . this . realCloseAction ( true ) ;
2002-10-04 04:52:41 +00:00
}
}
} ) ;
fileMenu . add ( closeItem ) ;
2003-06-21 02:07:51 +00:00
}
2002-10-04 04:52:41 +00:00
JMenuItem saveItem = new JMenuItem ( " Save " ) ;
2002-10-22 03:53:33 +00:00
// saveItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,java.awt.Event.CTRL_MASK)); //Ctrl-s
2002-10-06 18:23:27 +00:00
saveItem . addActionListener ( new ThdlActionListener ( ) {
public void theRealActionPerformed ( ActionEvent e ) {
2002-10-04 04:52:41 +00:00
if ( fileName = = null )
saveAsFile ( ) ;
else
saveFile ( ) ;
}
} ) ;
fileMenu . addSeparator ( ) ;
fileMenu . add ( saveItem ) ;
JMenuItem saveAsItem = new JMenuItem ( " Save as " ) ;
2002-10-06 18:23:27 +00:00
saveAsItem . addActionListener ( new ThdlActionListener ( ) {
public void theRealActionPerformed ( ActionEvent e ) {
2002-10-04 04:52:41 +00:00
saveAsFile ( ) ;
}
} ) ;
fileMenu . add ( saveAsItem ) ;
2003-06-21 02:07:51 +00:00
if ( parentObject instanceof JFrame ) {
JMenuItem exitItem = new JMenuItem ( " Exit " ) ;
exitItem . addActionListener ( new ThdlActionListener ( ) {
public void theRealActionPerformed ( ActionEvent e ) {
exitAction ( ) ;
}
} ) ;
fileMenu . addSeparator ( ) ;
fileMenu . add ( exitItem ) ;
}
2002-10-04 04:52:41 +00:00
menuBar . add ( fileMenu ) ;
}
JMenu editMenu = new JMenu ( " Edit " ) ;
if ( parentObject instanceof JFrame | | parentObject instanceof JInternalFrame ) {
JMenuItem cutItem = new JMenuItem ( " Cut " ) ;
2002-10-22 03:53:33 +00:00
cutItem . setAccelerator ( KeyStroke . getKeyStroke ( KeyEvent . VK_X ,
java . awt . Event . CTRL_MASK ) ) ; //Ctrl-x
2002-10-06 18:23:27 +00:00
cutItem . addActionListener ( new ThdlActionListener ( ) {
public void theRealActionPerformed ( ActionEvent e ) {
2002-10-04 04:52:41 +00:00
cutSelection ( ) ;
}
} ) ;
editMenu . add ( cutItem ) ;
JMenuItem copyItem = new JMenuItem ( " Copy " ) ;
2002-10-22 03:53:33 +00:00
copyItem . setAccelerator ( KeyStroke . getKeyStroke ( KeyEvent . VK_C ,
java . awt . Event . CTRL_MASK ) ) ; //Ctrl-c
2002-10-06 18:23:27 +00:00
copyItem . addActionListener ( new ThdlActionListener ( ) {
public void theRealActionPerformed ( ActionEvent e ) {
2002-10-04 04:52:41 +00:00
copySelection ( ) ;
}
} ) ;
editMenu . add ( copyItem ) ;
JMenuItem pasteItem = new JMenuItem ( " Paste " ) ;
2002-10-22 03:53:33 +00:00
pasteItem . setAccelerator ( KeyStroke . getKeyStroke ( KeyEvent . VK_V ,
java . awt . Event . CTRL_MASK ) ) ; //Ctrl-v
2002-10-06 18:23:27 +00:00
pasteItem . addActionListener ( new ThdlActionListener ( ) {
public void theRealActionPerformed ( ActionEvent e ) {
2002-10-04 04:52:41 +00:00
pasteSelection ( ) ;
}
} ) ;
editMenu . add ( pasteItem ) ;
editMenu . addSeparator ( ) ;
JMenuItem selectallItem = new JMenuItem ( " Select All " ) ;
2002-10-22 03:53:33 +00:00
selectallItem . setAccelerator ( KeyStroke . getKeyStroke ( KeyEvent . VK_A ,
java . awt . Event . CTRL_MASK ) ) ; //Ctrl-a
2002-10-06 18:23:27 +00:00
selectallItem . addActionListener ( new ThdlActionListener ( ) {
public void theRealActionPerformed ( ActionEvent e ) {
2002-10-04 04:52:41 +00:00
dp . setSelectionStart ( 0 ) ;
dp . setSelectionEnd ( dp . getDocument ( ) . getLength ( ) ) ;
}
} ) ;
editMenu . add ( selectallItem ) ;
}
2002-11-18 16:12:25 +00:00
{
JMenuItem preferencesItem = new JMenuItem ( " Preferences " ) ;
preferencesItem . addActionListener ( new ThdlActionListener ( ) {
public void theRealActionPerformed ( ActionEvent e ) {
getPreferences ( ) ;
}
} ) ;
editMenu . addSeparator ( ) ;
editMenu . add ( preferencesItem ) ;
}
{
JMenuItem preferencesItem = new JMenuItem ( " Save preferences to " + ThdlOptions . getUserPreferencesPath ( ) ) ;
preferencesItem . addActionListener ( new ThdlActionListener ( ) {
public void theRealActionPerformed ( ActionEvent e ) {
savePreferencesAction ( ) ;
}
} ) ;
editMenu . add ( preferencesItem ) ;
}
2002-10-04 04:52:41 +00:00
2003-06-21 01:26:17 +00:00
{
JMenuItem preferencesItem = new JMenuItem ( " Clear preferences " ) ;
preferencesItem . addActionListener ( new ThdlActionListener ( ) {
public void theRealActionPerformed ( ActionEvent e ) {
clearPreferencesAction ( ) ;
}
} ) ;
editMenu . addSeparator ( ) ;
editMenu . add ( preferencesItem ) ;
}
2002-11-18 16:12:25 +00:00
menuBar . add ( editMenu ) ;
2002-10-04 04:52:41 +00:00
JMenu toolsMenu = new JMenu ( " Tools " ) ;
JMenuItem TMWWylieItem = new JMenuItem ( " Convert Tibetan to Wylie " ) ;
2002-10-06 18:23:27 +00:00
TMWWylieItem . addActionListener ( new ThdlActionListener ( ) {
public void theRealActionPerformed ( ActionEvent e ) {
2002-10-04 04:52:41 +00:00
toWylie ( ) ;
}
} ) ;
toolsMenu . add ( TMWWylieItem ) ;
JMenuItem wylieTMWItem = new JMenuItem ( " Convert Wylie to Tibetan " ) ;
2002-10-06 18:23:27 +00:00
wylieTMWItem . addActionListener ( new ThdlActionListener ( ) {
public void theRealActionPerformed ( ActionEvent e ) {
2002-10-04 04:52:41 +00:00
toTibetan ( ) ;
}
} ) ;
toolsMenu . add ( wylieTMWItem ) ;
if ( parentObject instanceof JFrame | | parentObject instanceof JInternalFrame ) {
JMenuItem importItem = new JMenuItem ( " Import Wylie as Tibetan " ) ;
2002-10-06 18:23:27 +00:00
importItem . addActionListener ( new ThdlActionListener ( ) {
public void theRealActionPerformed ( ActionEvent e ) {
2002-10-04 04:52:41 +00:00
importWylie ( ) ;
}
} ) ;
toolsMenu . addSeparator ( ) ;
toolsMenu . add ( importItem ) ;
2003-05-31 23:21:29 +00:00
JMenuItem toTMItem = new JMenuItem ( " Convert TMW to TM " ) ; // DLC FIXME: do it just in the selection?
toTMItem . addActionListener ( new ThdlActionListener ( ) {
Fixed bug 617156, "DuffPane ignores setEditable(false)".
I fixed this the easy way, by checking the value of isEditable() before
cutting, pasting, or adding typed text. I may have missed a spot, but
checking at a lower level is a bit less efficient.
Fixing this the hard way, the keymaps-and-overridden-default-action way,
seems like it will make the code uglier, not cleaner. And it won't get us
closer to fixing the killer bug, 614475, "Improper Line Wrapping".
2002-10-20 05:54:29 +00:00
public void theRealActionPerformed ( ActionEvent e ) {
2003-06-01 23:05:32 +00:00
StringBuffer errors = new StringBuffer ( ) ;
boolean errorReturn
= ( ( TibetanDocument ) dp . getDocument ( ) ) . convertToTM ( 0 , - 1 , errors ) ; // entire document
if ( errorReturn ) {
JOptionPane . showMessageDialog ( Jskad . this ,
2003-06-15 16:27:36 +00:00
" At least one error occurred while converting Tibetan Machine Web \ nto Tibetan Machine. Your document is mostly converted, \ nexcept for the following glyphs, which you should replace manually \ nbefore retrying: \ n "
2003-06-01 23:05:32 +00:00
+ errors . toString ( ) ,
" TMW to TM Errors " ,
JOptionPane . PLAIN_MESSAGE ) ;
} else {
JOptionPane . showMessageDialog ( Jskad . this ,
" Converting Tibetan Machine Web to Tibetan Machine met with perfect success. " ,
" Success " , JOptionPane . PLAIN_MESSAGE ) ;
}
Fixed bug 617156, "DuffPane ignores setEditable(false)".
I fixed this the easy way, by checking the value of isEditable() before
cutting, pasting, or adding typed text. I may have missed a spot, but
checking at a lower level is a bit less efficient.
Fixing this the hard way, the keymaps-and-overridden-default-action way,
seems like it will make the code uglier, not cleaner. And it won't get us
closer to fixing the killer bug, 614475, "Improper Line Wrapping".
2002-10-20 05:54:29 +00:00
}
} ) ;
2003-05-31 23:21:29 +00:00
JMenuItem toTMWItem = new JMenuItem ( " Convert TM to TMW " ) ; // DLC FIXME: do it just in the selection?
toTMWItem . addActionListener ( new ThdlActionListener ( ) {
public void theRealActionPerformed ( ActionEvent e ) {
2003-06-01 23:05:32 +00:00
StringBuffer errors = new StringBuffer ( ) ;
boolean errorReturn
= ( ( TibetanDocument ) dp . getDocument ( ) ) . convertToTMW ( 0 , - 1 , errors ) ; // entire document
if ( errorReturn ) {
JOptionPane . showMessageDialog ( Jskad . this ,
2003-06-15 16:27:36 +00:00
" At least one error occurred while converting Tibetan Machine \ nto Tibetan Machine Web. Your document is mostly converted, \ nexcept for the following glyphs, which you should replace manually \ nbefore retrying: \ n "
2003-06-01 23:05:32 +00:00
+ errors . toString ( ) ,
" TM to TMW Errors " , JOptionPane . PLAIN_MESSAGE ) ;
} else {
JOptionPane . showMessageDialog ( Jskad . this ,
" Converting Tibetan Machine to Tibetan Machine Web met with perfect success. " ,
" Success " , JOptionPane . PLAIN_MESSAGE ) ;
}
2003-05-31 23:21:29 +00:00
}
} ) ;
2003-06-15 16:27:36 +00:00
JMenuItem toUnicodeItem = new JMenuItem ( " Convert TMW to Unicode " ) ; // DLC FIXME: do it just in the selection?
toUnicodeItem . addActionListener ( new ThdlActionListener ( ) {
public void theRealActionPerformed ( ActionEvent e ) {
StringBuffer errors = new StringBuffer ( ) ;
boolean errorReturn
= ( ( TibetanDocument ) dp . getDocument ( ) ) . convertToUnicode ( 0 , - 1 , errors ) ; // entire document
if ( errorReturn ) {
JOptionPane . showMessageDialog ( Jskad . this ,
" At least one error occurred while converting Tibetan Machine Web \ nto Unicode. Your document is mostly converted, \ nexcept for the following glyphs, which you should replace manually \ nbefore retrying: \ n "
+ errors . toString ( ) ,
" TMW to Unicode Errors " , JOptionPane . PLAIN_MESSAGE ) ;
} else {
JOptionPane . showMessageDialog ( Jskad . this ,
" Converting Tibetan Machine Web to Unicode met with perfect success. " ,
" Success " , JOptionPane . PLAIN_MESSAGE ) ;
}
}
} ) ;
2003-05-31 23:21:29 +00:00
toolsMenu . addSeparator ( ) ;
toolsMenu . add ( toTMItem ) ;
toolsMenu . add ( toTMWItem ) ;
2003-06-15 16:27:36 +00:00
toolsMenu . add ( toUnicodeItem ) ;
Fixed bug 617156, "DuffPane ignores setEditable(false)".
I fixed this the easy way, by checking the value of isEditable() before
cutting, pasting, or adding typed text. I may have missed a spot, but
checking at a lower level is a bit less efficient.
Fixing this the hard way, the keymaps-and-overridden-default-action way,
seems like it will make the code uglier, not cleaner. And it won't get us
closer to fixing the killer bug, 614475, "Improper Line Wrapping".
2002-10-20 05:54:29 +00:00
}
2003-05-31 23:21:29 +00:00
2003-05-18 14:14:47 +00:00
if ( ThdlOptions . getBooleanOption ( " thdl.add.developer.options.to.menu " ) ) {
toolsMenu . addSeparator ( ) ;
2003-05-31 23:21:29 +00:00
JMenuItem DevelItem = new JMenuItem ( " Toggle read-only " ) ;
2003-05-18 14:14:47 +00:00
DevelItem . addActionListener ( new ThdlActionListener ( ) {
public void theRealActionPerformed ( ActionEvent e ) {
2003-05-31 23:21:29 +00:00
dp . setEditable ( ! dp . isEditable ( ) ) ;
2003-05-18 14:14:47 +00:00
}
} ) ;
toolsMenu . add ( DevelItem ) ;
}
if ( ThdlOptions . getBooleanOption ( " thdl.add.developer.options.to.menu " ) ) {
toolsMenu . addSeparator ( ) ;
2003-05-31 23:21:29 +00:00
JMenuItem DevelItem = new JMenuItem ( " Check for non-TMW characters " ) ; // FIXME: do it just in the selection?
2003-05-18 14:14:47 +00:00
DevelItem . addActionListener ( new ThdlActionListener ( ) {
public void theRealActionPerformed ( ActionEvent e ) {
2003-05-31 23:21:29 +00:00
( ( TibetanDocument ) dp . getDocument ( ) ) . findSomeNonTMWCharacters ( 0 , - 1 ) ; // entire document.
2003-05-18 14:14:47 +00:00
}
} ) ;
toolsMenu . add ( DevelItem ) ;
}
2002-10-04 04:52:41 +00:00
menuBar . add ( toolsMenu ) ;
JMenu infoMenu = new JMenu ( " Info " ) ;
2003-02-01 06:42:07 +00:00
{
JMenuItem helpItem = new JMenuItem ( " Help " ) ;
helpItem . addActionListener ( new ThdlActionListener ( ) {
public void theRealActionPerformed ( ActionEvent e ) {
if ( helpPane = = null ) {
try {
helpPane
= new HTMLPane ( Jskad . class ,
" /org/thdl/tib/input/jskad_doc.html " ) ;
} catch ( Exception ex ) {
ex . printStackTrace ( System . err ) ;
throw new ThdlLazyException ( ex ) ;
/ * DLC FIXME - - handle this better .
show a dialog saying " help can't be
loaded , surf to thdl ' s web site and
also submit a bug report . " */
}
}
new SimpleFrame ( " Help for Jskad " , helpPane ) ;
/ * DLC FIXME - - pressing the " Help " menu item
twice causes the first pane to become dead .
We should check to see if the first pane
exists and raise it rather than creating a
second pane . * /
}
} ) ;
infoMenu . add ( helpItem ) ;
infoMenu . addSeparator ( ) ;
}
2002-10-13 20:42:23 +00:00
2002-10-20 08:02:16 +00:00
for ( int i = 0 ; i < keybdMgr . size ( ) ; i + + ) {
final JskadKeyboard kbd = keybdMgr . elementAt ( i ) ;
if ( kbd . hasQuickRefFile ( ) ) {
JMenuItem keybdItem = new JMenuItem ( kbd . getIdentifyingString ( ) ) ;
keybdItem . addActionListener ( new ThdlActionListener ( ) {
public void theRealActionPerformed ( ActionEvent e ) {
new SimpleFrame ( kbd . getIdentifyingString ( ) ,
kbd . getQuickRefPane ( ) ) ;
2003-02-01 06:42:07 +00:00
/ * DLC FIXME - - pressing the " Extended
2003-05-31 23:21:29 +00:00
Wylie " menu item (for example) twice
causes the first pane to become dead .
We should check to see if the first
pane exists and raise it rather than
creating a second pane . * /
2002-10-20 08:02:16 +00:00
}
} ) ;
infoMenu . add ( keybdItem ) ;
}
2002-10-13 20:42:23 +00:00
}
infoMenu . addSeparator ( ) ;
2003-02-01 06:42:07 +00:00
{
JMenuItem aboutItem = new JMenuItem ( " About " ) ;
aboutItem . addActionListener ( new ThdlActionListener ( ) {
public void theRealActionPerformed ( ActionEvent e ) {
JOptionPane . showMessageDialog ( Jskad . this ,
" Copyright 2001-2003 Tibetan and Himalayan Digital Library \ n \ n " +
2003-05-31 23:21:29 +00:00
" Jskad is protected by the THDL Open Community License. \ n \ n " + /* FIXME UPDATE THE YEAR REGULARLY */
2003-02-01 06:42:07 +00:00
" For more information, or to download the source code \ n " +
" for Jskad, visit our web site: \ n " +
2003-05-31 23:21:29 +00:00
" http://thdl.org/ \ n " +
2003-02-01 06:42:07 +00:00
" \ n " +
" When submitting bug reports, please indicate that the \ n " +
" time of compilation is "
+ ThdlVersion . getTimeOfCompilation ( ) + " \ n " ,
" About Jskad " , JOptionPane . PLAIN_MESSAGE ) ;
}
} ) ;
infoMenu . add ( aboutItem ) ;
}
2002-10-04 04:52:41 +00:00
menuBar . add ( infoMenu ) ;
2002-11-18 16:12:25 +00:00
/ * Initialize dp before calling
JskadKeyboard . activate ( DuffPane ) or dp . toggleLanguage ( ) . * /
if ( ThdlOptions . getBooleanOption ( Jskad . enableKeypressStatusProp ) ) {
dp = new DuffPane ( statusBar ) ;
} else {
dp = new DuffPane ( ) ;
}
2002-10-04 04:52:41 +00:00
JToolBar toolBar = new JToolBar ( ) ;
toolBar . setBorder ( null ) ;
toolBar . addSeparator ( ) ;
toolBar . add ( new JLabel ( " Input mode: " ) ) ;
toolBar . addSeparator ( ) ;
String [ ] input_modes = { " Tibetan " , " Roman " } ;
final JComboBox inputmethods = new JComboBox ( input_modes ) ;
2002-11-18 16:12:25 +00:00
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 ( ) ;
2002-10-06 18:23:27 +00:00
inputmethods . addActionListener ( new ThdlActionListener ( ) {
public void theRealActionPerformed ( ActionEvent e ) {
2002-11-18 16:12:25 +00:00
int si = inputmethods . getSelectedIndex ( ) ;
ThdlOptions . setUserPreference ( " thdl.Jskad.input.method " , si ) ;
switch ( si ) {
2002-10-04 04:52:41 +00:00
case 0 : //Tibetan
if ( dp . isRomanMode ( ) )
dp . toggleLanguage ( ) ;
2002-10-13 19:22:56 +00:00
statusBar . replaceStatus ( " Now inputting Tibetan script " ) ;
2002-10-04 04:52:41 +00:00
break ;
case 1 : //Roman
if ( ! dp . isRomanMode ( ) & & dp . isRomanEnabled ( ) )
dp . toggleLanguage ( ) ;
2002-10-13 19:22:56 +00:00
statusBar . replaceStatus ( " Now inputting Roman script " ) ;
2002-10-04 04:52:41 +00:00
break ;
}
}
} ) ;
toolBar . add ( inputmethods ) ;
toolBar . add ( Box . createHorizontalGlue ( ) ) ;
toolBar . add ( new JLabel ( " Keyboard: " ) ) ;
toolBar . addSeparator ( ) ;
2002-10-20 08:02:16 +00:00
final JComboBox keyboards
= new JComboBox ( keybdMgr . getIdentifyingStrings ( ) ) ;
Added a flexible mechanism for persistent boolean-, integer-, and
string-valued preferences built atop java.util.Properties.
How it works: the jvm is asked first, and then the user's prefs file, if it exists,
then the system-wide prefs file, and then the built-in preferences. Finally, for
robustness, a default may be optionally hard-coded in the source.
I made several things configurable, too:
the default Tibetan keyboard
the default font sizes and faces
whether you want developer-only features enabled
Savant's file extension (.savant)
etc.
The only known problems are the following:
The default location for the user's preferences file is windows-specific,
arbitrary, and not in the user documentation. Likewise for the location of the
system-wide preferences file. You can change them using 'java -D', though.
There is no "Save preferences" option yet, and closing the program does
not save preferences either.
2002-10-14 04:06:05 +00:00
int initialKeyboard
= ThdlOptions . getIntegerOption ( " thdl.default.tibetan.keyboard " , 0 ) ;
try {
keyboards . setSelectedIndex ( initialKeyboard ) ;
} catch ( IllegalArgumentException e ) {
2002-10-20 08:25:10 +00:00
initialKeyboard = 0 ; // good ol' Wylie
keyboards . setSelectedIndex ( initialKeyboard ) ;
Added a flexible mechanism for persistent boolean-, integer-, and
string-valued preferences built atop java.util.Properties.
How it works: the jvm is asked first, and then the user's prefs file, if it exists,
then the system-wide prefs file, and then the built-in preferences. Finally, for
robustness, a default may be optionally hard-coded in the source.
I made several things configurable, too:
the default Tibetan keyboard
the default font sizes and faces
whether you want developer-only features enabled
Savant's file extension (.savant)
etc.
The only known problems are the following:
The default location for the user's preferences file is windows-specific,
arbitrary, and not in the user documentation. Likewise for the location of the
system-wide preferences file. You can change them using 'java -D', though.
There is no "Save preferences" option yet, and closing the program does
not save preferences either.
2002-10-14 04:06:05 +00:00
}
2002-10-20 08:25:10 +00:00
keybdMgr . elementAt ( initialKeyboard ) . activate ( dp ) ;
2002-10-06 18:23:27 +00:00
keyboards . addActionListener ( new ThdlActionListener ( ) {
public void theRealActionPerformed ( ActionEvent e ) {
2002-11-18 16:12:25 +00:00
int ki = keyboards . getSelectedIndex ( ) ;
2002-10-20 08:25:10 +00:00
keybdMgr . elementAt ( keyboards . getSelectedIndex ( ) ) . activate ( dp ) ;
2002-11-18 16:12:25 +00:00
ThdlOptions . setUserPreference ( " thdl.default.tibetan.keyboard " ,
ki ) ;
2002-10-04 04:52:41 +00:00
}
} ) ;
toolBar . add ( keyboards ) ;
toolBar . add ( Box . createHorizontalGlue ( ) ) ;
2003-04-14 05:22:27 +00:00
JScrollPane sp
= new JScrollPane ( dp ,
JScrollPane . VERTICAL_SCROLLBAR_AS_NEEDED ,
JScrollPane . HORIZONTAL_SCROLLBAR_NEVER ) ;
2002-10-04 04:52:41 +00:00
dp . getDocument ( ) . addDocumentListener ( this ) ;
if ( parentObject instanceof JFrame ) {
final JFrame parentFrame = ( JFrame ) parentObject ;
parentFrame . setJMenuBar ( menuBar ) ;
parentFrame . setDefaultCloseOperation ( WindowConstants . DO_NOTHING_ON_CLOSE ) ;
parentFrame . addWindowListener ( new WindowAdapter ( ) {
public void windowClosing ( WindowEvent e ) {
if ( ! hasChanged | | hasChanged & & checkSave ( ) ) {
numberOfTibsRTFOpen - - ;
if ( numberOfTibsRTFOpen = = 0 )
System . exit ( 0 ) ;
else
parentFrame . dispose ( ) ;
}
}
} ) ;
}
else if ( parentObject instanceof JInternalFrame ) {
final JInternalFrame parentFrame = ( JInternalFrame ) parentObject ;
parentFrame . setJMenuBar ( menuBar ) ;
}
else if ( parentObject instanceof JApplet ) {
JApplet parentApplet = ( JApplet ) parentObject ;
parentApplet . setJMenuBar ( menuBar ) ;
dp . disableCutAndPaste ( ) ;
}
setLayout ( new BorderLayout ( ) ) ;
add ( " North " , toolBar ) ;
add ( " Center " , sp ) ;
2002-10-13 19:22:56 +00:00
if ( statusBar ! = null )
add ( " South " , statusBar ) ;
2002-10-04 04:52:41 +00:00
}
private void getPreferences ( ) {
GraphicsEnvironment genv = GraphicsEnvironment . getLocalGraphicsEnvironment ( ) ;
String [ ] fontNames = genv . getAvailableFontFamilyNames ( ) ;
JPanel tibetanPanel ;
JComboBox tibetanFontSizes ;
tibetanPanel = new JPanel ( ) ;
tibetanPanel . setBorder ( BorderFactory . createTitledBorder ( " Set Tibetan Font Size " ) ) ;
tibetanFontSizes = new JComboBox ( new String [ ] { " 8 " , " 10 " , " 12 " , " 14 " , " 16 " , " 18 " , " 20 " , " 22 " , " 24 " , " 26 " , " 28 " , " 30 " , " 32 " , " 34 " , " 36 " , " 48 " , " 72 " } ) ;
tibetanFontSizes . setMaximumSize ( tibetanFontSizes . getPreferredSize ( ) ) ;
tibetanFontSizes . setSelectedItem ( String . valueOf ( dp . getTibetanFontSize ( ) ) ) ;
tibetanFontSizes . setEditable ( true ) ;
tibetanPanel . add ( tibetanFontSizes ) ;
JPanel romanPanel ;
JComboBox romanFontFamilies ;
JComboBox romanFontSizes ;
romanPanel = new JPanel ( ) ;
romanPanel . setBorder ( BorderFactory . createTitledBorder ( " Set non-Tibetan Font and Size " ) ) ;
romanFontFamilies = new JComboBox ( fontNames ) ;
romanFontFamilies . setMaximumSize ( romanFontFamilies . getPreferredSize ( ) ) ;
romanFontFamilies . setSelectedItem ( dp . getRomanFontFamily ( ) ) ;
romanFontFamilies . setEditable ( true ) ;
romanFontSizes = new JComboBox ( new String [ ] { " 8 " , " 10 " , " 12 " , " 14 " , " 16 " , " 18 " , " 20 " , " 22 " , " 24 " , " 26 " , " 28 " , " 30 " , " 32 " , " 34 " , " 36 " , " 48 " , " 72 " } ) ;
romanFontSizes . setMaximumSize ( romanFontSizes . getPreferredSize ( ) ) ;
romanFontSizes . setSelectedItem ( String . valueOf ( dp . getRomanFontSize ( ) ) ) ;
romanFontSizes . setEditable ( true ) ;
romanPanel . setLayout ( new GridLayout ( 1 , 2 ) ) ;
romanPanel . add ( romanFontFamilies ) ;
romanPanel . add ( romanFontSizes ) ;
JPanel preferencesPanel = new JPanel ( ) ;
preferencesPanel . setLayout ( new GridLayout ( 2 , 1 ) ) ;
preferencesPanel . add ( tibetanPanel ) ;
preferencesPanel . add ( romanPanel ) ;
JOptionPane pane = new JOptionPane ( preferencesPanel ) ;
JDialog dialog = pane . createDialog ( this , " Preferences " ) ;
2002-11-16 19:18:44 +00:00
// This returns only when the user has closed the dialog:
2002-10-04 04:52:41 +00:00
dialog . show ( ) ;
int size ;
try {
size = Integer . parseInt ( tibetanFontSizes . getSelectedItem ( ) . toString ( ) ) ;
2002-11-18 16:12:25 +00:00
dp . setByUserTibetanFontSize ( size ) ;
2002-10-04 04:52:41 +00:00
}
catch ( NumberFormatException ne ) {
size = dp . getTibetanFontSize ( ) ;
2002-11-18 16:12:25 +00:00
dp . setTibetanFontSize ( size ) ;
2002-10-04 04:52:41 +00:00
}
String font = romanFontFamilies . getSelectedItem ( ) . toString ( ) ;
try {
size = Integer . parseInt ( romanFontSizes . getSelectedItem ( ) . toString ( ) ) ;
}
catch ( NumberFormatException ne ) {
size = dp . getRomanFontSize ( ) ;
}
2002-11-18 16:12:25 +00:00
dp . setByUserRomanAttributeSet ( font , size ) ;
2002-10-04 04:52:41 +00:00
}
private void newFile ( ) {
if ( dp . getDocument ( ) . getLength ( ) > 0 & & parentObject instanceof JFrame ) {
JFrame parentFrame = ( JFrame ) parentObject ;
JFrame newFrame = new JFrame ( " Jskad " ) ;
Point point = parentFrame . getLocationOnScreen ( ) ;
newFrame . setSize ( parentFrame . getSize ( ) . width , parentFrame . getSize ( ) . height ) ;
newFrame . setLocation ( point . x + 50 , point . y + 50 ) ;
2003-06-21 02:07:51 +00:00
Jskad jskad = new Jskad ( newFrame ) ;
jskads . add ( jskad ) ;
newFrame . getContentPane ( ) . add ( jskad ) ;
2002-10-04 04:52:41 +00:00
newFrame . setVisible ( true ) ;
}
else {
if ( parentObject instanceof JFrame ) {
JFrame parentFrame = ( JFrame ) parentObject ;
parentFrame . setTitle ( " Jskad " ) ;
}
else if ( parentObject instanceof JInternalFrame ) {
JInternalFrame parentFrame = ( JInternalFrame ) parentObject ;
parentFrame . setTitle ( " Jskad " ) ;
}
dp . newDocument ( ) ;
dp . getDocument ( ) . addDocumentListener ( Jskad . this ) ;
hasChanged = false ;
}
}
private void openFile ( ) {
2003-03-11 01:03:19 +00:00
String whereToStart
= ThdlOptions . getStringOption ( " thdl.Jskad.working.directory " ,
null ) ;
fileChooser
= new JFileChooser ( whereToStart . equals ( " " ) ? null : whereToStart ) ;
2002-10-04 04:52:41 +00:00
fileChooser . addChoosableFileFilter ( rtfFilter ) ;
2003-03-11 01:03:19 +00:00
setCursor ( Cursor . getPredefinedCursor ( Cursor . WAIT_CURSOR ) ) ;
2002-10-04 04:52:41 +00:00
2003-03-11 01:03:19 +00:00
if ( fileChooser . showOpenDialog ( this ) ! = JFileChooser . APPROVE_OPTION ) {
setCursor ( Cursor . getPredefinedCursor ( Cursor . DEFAULT_CURSOR ) ) ;
return ;
}
2002-10-04 04:52:41 +00:00
2003-03-11 01:03:19 +00:00
final File fileChosen = fileChooser . getSelectedFile ( ) ;
final String f_name = fileChosen . getAbsolutePath ( ) ;
2002-10-04 04:52:41 +00:00
2003-03-11 01:03:19 +00:00
try {
if ( dp . getDocument ( ) . getLength ( ) > 0 & & parentObject instanceof JFrame ) {
JFrame parentFrame = ( JFrame ) parentObject ;
InputStream in = new FileInputStream ( fileChosen ) ;
ThdlOptions . setUserPreference ( " thdl.Jskad.working.directory " ,
fileChosen . getParentFile ( ) . getAbsolutePath ( ) ) ;
JFrame newFrame = new JFrame ( f_name ) ;
Point point = parentFrame . getLocationOnScreen ( ) ;
newFrame . setSize ( x_size , y_size ) ;
newFrame . setLocation ( point . x + 50 , point . y + 50 ) ;
Jskad newRTF = new Jskad ( newFrame ) ;
2003-06-21 02:07:51 +00:00
jskads . add ( newRTF ) ;
2003-03-11 01:03:19 +00:00
newFrame . getContentPane ( ) . add ( newRTF ) ;
2003-05-14 01:34:39 +00:00
boolean error = false ;
try {
newRTF . dp . rtfEd . read ( in , newRTF . dp . getDocument ( ) , 0 ) ;
} catch ( Exception e ) {
JOptionPane . showMessageDialog ( newFrame ,
2003-06-15 19:19:23 +00:00
TibetanConverter . rtfErrorMessage ) ;
2003-05-14 01:34:39 +00:00
error = true ;
}
2003-03-11 01:03:19 +00:00
in . close ( ) ;
2003-05-14 01:34:39 +00:00
if ( error ) {
newFrame . dispose ( ) ;
numberOfTibsRTFOpen - - ;
} else {
2003-05-28 00:40:59 +00:00
if ( ! ThdlOptions . getBooleanOption ( " thdl.Jskad.do.not.fix.curly.braces.in.rtf " ) ) {
( ( TibetanDocument ) newRTF . dp . getDocument ( ) ) . replaceTahomaCurlyBracesAndBackslashes ( 0 , - 1 ) ;
}
2003-05-14 01:34:39 +00:00
newRTF . dp . getDocument ( ) . addDocumentListener ( newRTF ) ;
newFrame . setTitle ( " Jskad: " + f_name ) ;
newRTF . fileName = new String ( f_name ) ;
newRTF . hasChanged = false ;
newRTF . dp . getCaret ( ) . setDot ( 0 ) ;
newFrame . setVisible ( true ) ;
}
2003-03-11 01:03:19 +00:00
} else {
InputStream in = new FileInputStream ( fileChosen ) ;
ThdlOptions . setUserPreference ( " thdl.Jskad.working.directory " ,
fileChosen . getParentFile ( ) . getAbsolutePath ( ) ) ;
dp . newDocument ( ) ;
2003-05-14 01:34:39 +00:00
boolean error = false ;
try {
dp . rtfEd . read ( in , dp . getDocument ( ) , 0 ) ;
} catch ( Exception e ) {
JOptionPane . showMessageDialog ( this ,
2003-06-15 19:19:23 +00:00
TibetanConverter . rtfErrorMessage ) ;
2003-05-14 01:34:39 +00:00
error = true ;
2003-03-11 01:03:19 +00:00
}
2003-05-14 01:34:39 +00:00
in . close ( ) ;
if ( ! error ) {
2003-05-28 00:40:59 +00:00
if ( ! ThdlOptions . getBooleanOption ( " thdl.Jskad.do.not.fix.curly.braces.in.rtf " ) ) {
( ( TibetanDocument ) dp . getDocument ( ) ) . replaceTahomaCurlyBracesAndBackslashes ( 0 , - 1 ) ;
}
2003-05-14 01:34:39 +00:00
dp . getCaret ( ) . setDot ( 0 ) ;
dp . getDocument ( ) . addDocumentListener ( Jskad . this ) ;
hasChanged = false ;
fileName = new String ( f_name ) ;
if ( parentObject instanceof JFrame ) {
JFrame parentFrame = ( JFrame ) parentObject ;
parentFrame . setTitle ( " Jskad: " + fileName ) ;
}
else if ( parentObject instanceof JInternalFrame ) {
JInternalFrame parentFrame = ( JInternalFrame ) parentObject ;
parentFrame . setTitle ( " Jskad: " + fileName ) ;
}
2003-03-11 01:03:19 +00:00
}
}
}
catch ( FileNotFoundException fnfe ) {
JOptionPane . showMessageDialog ( Jskad . this ,
" No such file exists. " ,
" Open File Error " ,
JOptionPane . ERROR_MESSAGE ) ;
}
catch ( IOException ioe ) {
JOptionPane . showMessageDialog ( Jskad . this ,
" Error reading file. " ,
" Open File Error " ,
JOptionPane . ERROR_MESSAGE ) ;
}
setCursor ( Cursor . getPredefinedCursor ( Cursor . DEFAULT_CURSOR ) ) ;
2002-10-04 04:52:41 +00:00
}
2003-06-21 02:07:51 +00:00
/** Returns true iff the save was successful. */
private boolean saveFile ( ) {
2002-10-04 04:52:41 +00:00
String s = getSave ( fileName ) ;
if ( null ! = s ) {
if ( parentObject instanceof JFrame ) {
JFrame parentFrame = ( JFrame ) parentObject ;
2003-05-14 01:34:39 +00:00
parentFrame . setTitle ( " Jskad: " + s ) ;
2002-10-04 04:52:41 +00:00
fileName = new String ( s ) ;
}
else if ( parentObject instanceof JInternalFrame ) {
JInternalFrame parentFrame = ( JInternalFrame ) parentObject ;
2003-05-14 01:34:39 +00:00
parentFrame . setTitle ( " Jskad: " + s ) ;
2002-10-04 04:52:41 +00:00
fileName = new String ( s ) ;
}
2003-06-21 02:07:51 +00:00
return true ;
} else {
return false ;
2002-10-04 04:52:41 +00:00
}
}
2003-06-21 02:07:51 +00:00
/** Returns true iff the save was successful. */
private boolean saveAsFile ( ) {
2002-10-04 04:52:41 +00:00
String s = getSaveAs ( ) ;
if ( null ! = s ) {
if ( parentObject instanceof JFrame ) {
JFrame parentFrame = ( JFrame ) parentObject ;
2003-05-14 01:34:39 +00:00
parentFrame . setTitle ( " Jskad: " + s ) ;
2002-10-04 04:52:41 +00:00
fileName = new String ( s ) ;
}
else if ( parentObject instanceof JInternalFrame ) {
JInternalFrame parentFrame = ( JInternalFrame ) parentObject ;
2003-05-14 01:34:39 +00:00
parentFrame . setTitle ( " Jskad: " + s ) ;
2002-10-04 04:52:41 +00:00
fileName = new String ( s ) ;
}
2003-06-21 02:07:51 +00:00
return true ;
2002-10-04 04:52:41 +00:00
}
2003-06-21 02:07:51 +00:00
return false ;
2002-10-04 04:52:41 +00:00
}
2003-06-21 02:07:51 +00:00
/ * * Returns true iff the user says ( possibly after a successful
save ) that it is OK to destroy this Jskad widget . * /
2002-10-04 04:52:41 +00:00
private boolean checkSave ( ) {
2003-06-21 02:07:51 +00:00
if ( ThdlOptions . getBooleanOption ( " thdl.Jskad.do.not.confirm.quit " ) ) {
return true ;
}
2002-11-08 03:58:35 +00:00
2003-06-21 02:07:51 +00:00
int saveFirst
= JOptionPane . showConfirmDialog ( this ,
" Do you want to save your changes? " ,
" Please select " ,
JOptionPane . YES_NO_CANCEL_OPTION ) ;
2002-10-04 04:52:41 +00:00
switch ( saveFirst ) {
case JOptionPane . NO_OPTION : //don't save but do continue
return true ;
case JOptionPane . YES_OPTION : //save and continue
2003-06-21 02:07:51 +00:00
if ( fileName = = null )
return saveAsFile ( ) ;
2002-10-04 04:52:41 +00:00
else
2003-06-21 02:07:51 +00:00
return saveFile ( ) ;
2002-10-04 04:52:41 +00:00
default :
return false ;
}
}
private String getSave ( String f_name ) {
File fileChosen = new File ( f_name ) ;
try {
BufferedOutputStream out = new BufferedOutputStream ( new FileOutputStream ( fileChosen ) ) ;
dp . rtfEd . write ( out , dp . getDocument ( ) , 0 , dp . getDocument ( ) . getLength ( ) ) ;
out . flush ( ) ;
out . close ( ) ;
hasChanged = false ;
} catch ( IOException exception ) {
2003-03-11 01:03:19 +00:00
JOptionPane . showMessageDialog ( Jskad . this ,
" Cannot save to that file. " ,
" Save As Error " ,
JOptionPane . ERROR_MESSAGE ) ;
2002-10-04 04:52:41 +00:00
return null ;
} catch ( BadLocationException ble ) {
ble . printStackTrace ( ) ;
2002-10-06 18:23:27 +00:00
ThdlDebug . noteIffyCode ( ) ;
2002-10-04 04:52:41 +00:00
}
return f_name ;
}
private String getSaveAs ( ) {
setCursor ( Cursor . getPredefinedCursor ( Cursor . WAIT_CURSOR ) ) ;
if ( fileName = = null )
fileChooser . setSelectedFile ( null ) ;
else
fileChooser . setSelectedFile ( new File ( fileName ) ) ;
if ( fileChooser . showSaveDialog ( this ) ! = JFileChooser . APPROVE_OPTION ) {
setCursor ( Cursor . getPredefinedCursor ( Cursor . DEFAULT_CURSOR ) ) ;
return null ;
}
File fileChosen = fileChooser . getSelectedFile ( ) ;
2003-03-11 01:03:19 +00:00
ThdlOptions . setUserPreference ( " thdl.Jskad.working.directory " ,
fileChosen . getParentFile ( ) . getAbsolutePath ( ) ) ;
2002-10-04 04:52:41 +00:00
String fileName = fileChosen . getAbsolutePath ( ) ;
int i = fileName . lastIndexOf ( '.' ) ;
if ( i < 0 )
fileName + = " .rtf " ;
else
fileName = fileName . substring ( 0 , i ) + " .rtf " ;
getSave ( fileName ) ;
fileChooser . rescanCurrentDirectory ( ) ;
setCursor ( Cursor . getPredefinedCursor ( Cursor . DEFAULT_CURSOR ) ) ;
return fileName ;
}
private void cutSelection ( ) {
2003-04-02 20:37:14 +00:00
dp . cut ( ) ;
2002-10-04 04:52:41 +00:00
}
private void copySelection ( ) {
2003-04-02 20:37:14 +00:00
dp . copy ( ) ;
2002-10-04 04:52:41 +00:00
}
private void pasteSelection ( ) {
dp . paste ( dp . getCaret ( ) . getDot ( ) ) ;
}
private void toTibetan ( ) {
Jskad . this . setCursor ( Cursor . getPredefinedCursor ( Cursor . WAIT_CURSOR ) ) ;
dp . toTibetanMachineWeb ( ) ;
Jskad . this . setCursor ( Cursor . getPredefinedCursor ( Cursor . DEFAULT_CURSOR ) ) ;
}
private void toWylie ( ) {
Jskad . this . setCursor ( Cursor . getPredefinedCursor ( Cursor . WAIT_CURSOR ) ) ;
dp . toWylie ( dp . getSelectionStart ( ) , dp . getSelectionEnd ( ) ) ;
Jskad . this . setCursor ( Cursor . getPredefinedCursor ( Cursor . DEFAULT_CURSOR ) ) ;
}
private void importWylie ( ) {
fileChooser . removeChoosableFileFilter ( rtfFilter ) ;
fileChooser . addChoosableFileFilter ( txtFilter ) ;
if ( fileChooser . showDialog ( Jskad . this , " Import Wylie " ) ! = JFileChooser . APPROVE_OPTION ) {
setCursor ( Cursor . getPredefinedCursor ( Cursor . DEFAULT_CURSOR ) ) ;
fileChooser . removeChoosableFileFilter ( txtFilter ) ;
fileChooser . addChoosableFileFilter ( rtfFilter ) ;
return ;
}
File txt_fileChosen = fileChooser . getSelectedFile ( ) ;
fileChooser . rescanCurrentDirectory ( ) ;
setCursor ( Cursor . getPredefinedCursor ( Cursor . DEFAULT_CURSOR ) ) ;
fileChooser . removeChoosableFileFilter ( txtFilter ) ;
fileChooser . addChoosableFileFilter ( rtfFilter ) ;
if ( fileChooser . showDialog ( Jskad . this , " Save as Tibetan " ) ! = JFileChooser . APPROVE_OPTION ) {
setCursor ( Cursor . getPredefinedCursor ( Cursor . DEFAULT_CURSOR ) ) ;
return ;
}
File rtf_fileChosen = fileChooser . getSelectedFile ( ) ;
fileChooser . rescanCurrentDirectory ( ) ;
setCursor ( Cursor . getPredefinedCursor ( Cursor . DEFAULT_CURSOR ) ) ;
String rtf_fileName = rtf_fileChosen . getAbsolutePath ( ) ;
int i = rtf_fileName . lastIndexOf ( '.' ) ;
if ( i < 0 )
rtf_fileName + = " .rtf " ;
else
rtf_fileName = fileName . substring ( 0 , i ) + " .rtf " ;
try {
BufferedReader in = new BufferedReader ( new FileReader ( txt_fileChosen ) ) ;
2003-04-14 05:22:27 +00:00
// FIXME: why do we need a whole DuffPane to do this?
DuffPane dp2 = new DuffPane ( ) ;
2002-10-04 04:52:41 +00:00
try {
String val = in . readLine ( ) ;
while ( val ! = null ) {
dp2 . toTibetanMachineWeb ( val + " \ n " , dp2 . getCaret ( ) . getDot ( ) ) ;
val = in . readLine ( ) ;
}
TibetanDocument t_doc = ( TibetanDocument ) dp2 . getDocument ( ) ;
t_doc . writeRTFOutputStream ( new FileOutputStream ( new File ( rtf_fileName ) ) ) ;
2003-04-14 05:22:27 +00:00
} catch ( IOException ioe ) {
2002-11-16 19:18:44 +00:00
ThdlDebug . noteIffyCode ( ) ;
2002-10-04 04:52:41 +00:00
System . out . println ( " problem reading or writing file " ) ;
}
2003-04-14 05:22:27 +00:00
} catch ( FileNotFoundException fnfe ) {
ThdlDebug . noteIffyCode ( ) ;
2002-10-04 04:52:41 +00:00
System . out . println ( " problem reading file " ) ;
}
}
/ * *
* Allows use of Jskad as dependent JFrame .
* Once you ' ve called this method , users will
* be able to close Jskad without shutting
* down your superordinate application .
* /
public void makeDependent ( ) {
numberOfTibsRTFOpen + + ;
}
/ * *
* Fills the editing pane with content . If the
* editing pane already has content , this method does nothing .
*
* @param wylie the string of wylie you want to
* put in the editing pane
* /
public void setContent ( String wylie ) {
if ( dp . getDocument ( ) . getLength ( ) > 0 )
return ;
dp . newDocument ( ) ;
dp . toTibetanMachineWeb ( wylie , 0 ) ;
}
/ * *
* Enables typing of Roman ( non - Tibetan ) text along
* with Tibetan .
* /
public void enableRoman ( ) {
dp . enableRoman ( ) ;
}
/ * *
* Disables typing of Roman ( non - Tibetan ) text .
* /
public void disableRoman ( ) {
dp . disableRoman ( ) ;
}
/ *
private void showAttributes ( int pos ) {
dp . skipUpdate = true ;
AttributeSet attr = dp . getDocument ( ) . getCharacterElement ( pos ) . getAttributes ( ) ;
String name = StyleConstants . getFontFamily ( attr ) ;
if ( ! fontName . equals ( name ) ) {
fontName = name ;
fontFamilies . setSelectedItem ( name ) ;
}
int size = StyleConstants . getFontSize ( attr ) ;
if ( fontSize ! = size ) {
fontSize = size ;
fontSizes . setSelectedItem ( Integer . toString ( fontSize ) ) ;
}
dp . skipUpdate = false ;
}
* /
/ * *
* Required for implementations of DocumentListener .
* Does nothing .
* /
public void changedUpdate ( DocumentEvent de ) {
}
/ * *
* Required for implementations of DocumentListener .
* Informs the object that a change in the document
* has occurred .
*
* @param de a DocumentEvent
* /
public void insertUpdate ( DocumentEvent de ) {
hasChanged = true ;
}
/ * *
* Required for implementations of DocumentListener .
* Informs the object that a change in the document
* has occurred .
*
* @param de a DocumentEvent
* /
public void removeUpdate ( DocumentEvent de ) {
hasChanged = true ;
}
private class RTFFilter extends javax . swing . filechooser . FileFilter {
// Accept all directories and all RTF files.
public boolean accept ( File f ) {
if ( f . isDirectory ( ) ) {
return true ;
}
String fName = f . getName ( ) ;
int i = fName . lastIndexOf ( '.' ) ;
if ( i < 0 )
return false ;
else {
String ext = fName . substring ( i + 1 ) . toLowerCase ( ) ;
if ( ext . equals ( " rtf " ) )
return true ;
else
return false ;
}
}
//the description of this filter
public String getDescription ( ) {
return " Rich Text Format (.rtf) " ;
}
}
private class TXTFilter extends javax . swing . filechooser . FileFilter {
// Accept all directories and all TXT files.
public boolean accept ( File f ) {
if ( f . isDirectory ( ) ) {
return true ;
}
String fName = f . getName ( ) ;
int i = fName . lastIndexOf ( '.' ) ;
if ( i < 0 )
return false ;
else {
String ext = fName . substring ( i + 1 ) . toLowerCase ( ) ;
if ( ext . equals ( " txt " ) )
return true ;
else
return false ;
}
}
//the description of this filter
public String getDescription ( ) {
return " Text file (.txt) " ;
}
}
2003-06-21 02:07:51 +00:00
/ * * Closes this Jskad session without saving . If deleteFromList
is true , the jskads vector is updated so that it no longer
contains this instance . If this is the last instance open ,
the program exits . * /
private void realCloseAction ( boolean deleteFromList ) {
numberOfTibsRTFOpen - - ;
// Delete this Jskad from jskads.
if ( deleteFromList ) {
int i , sz = jskads . size ( ) ;
for ( i = 0 ; i < sz ; i + + ) {
if ( jskads . elementAt ( i ) = = this ) {
jskads . removeElementAt ( i ) ;
break ;
}
}
if ( i = = sz )
throw new Error ( " Couldn't find the Jskad session being closed in our list of open Jskad sessions! This is a bug. " ) ;
}
if ( numberOfTibsRTFOpen = = 0 )
System . exit ( 0 ) ;
else {
final JFrame parentFrame = ( JFrame ) parentObject ;
parentFrame . dispose ( ) ;
}
}
/** Stores all open Jskad sessions. */
private static Vector jskads = new Vector ( ) ;
/ * * Closes all Jskad windows after asking " Do you want to save? "
for the modified windows . If you don ' t cancel for any unsaved
session , then all sessions are closed . * /
private static void exitAction ( ) {
int sz = jskads . size ( ) ;
for ( int i = 0 ; i < sz ; i + + ) {
Jskad j = ( Jskad ) jskads . elementAt ( i ) ;
if ( j . hasChanged & & ! j . checkSave ( ) ) {
return ;
}
}
for ( int i = 0 ; i < sz ; i + + ) {
Jskad j = ( Jskad ) jskads . elementAt ( i ) ;
j . realCloseAction ( false ) ;
}
}
2002-10-13 20:42:23 +00:00
2002-10-04 04:52:41 +00:00
/ * *
2002-10-06 18:23:27 +00:00
* Runs Jskad . System output , including errors , is redirected to
* jskad . log in addition to appearing on the console as per usual . If
* you discover a bug , please send us an email , making sure to include
* the jskad . log file as an attachment . * /
2002-10-04 04:52:41 +00:00
public static void main ( String [ ] args ) {
Added a flexible mechanism for persistent boolean-, integer-, and
string-valued preferences built atop java.util.Properties.
How it works: the jvm is asked first, and then the user's prefs file, if it exists,
then the system-wide prefs file, and then the built-in preferences. Finally, for
robustness, a default may be optionally hard-coded in the source.
I made several things configurable, too:
the default Tibetan keyboard
the default font sizes and faces
whether you want developer-only features enabled
Savant's file extension (.savant)
etc.
The only known problems are the following:
The default location for the user's preferences file is windows-specific,
arbitrary, and not in the user documentation. Likewise for the location of the
system-wide preferences file. You can change them using 'java -D', though.
There is no "Save preferences" option yet, and closing the program does
not save preferences either.
2002-10-14 04:06:05 +00:00
try {
ThdlDebug . attemptToSetUpLogFile ( " jskad " , " .log " ) ;
2002-10-04 04:52:41 +00:00
Added a flexible mechanism for persistent boolean-, integer-, and
string-valued preferences built atop java.util.Properties.
How it works: the jvm is asked first, and then the user's prefs file, if it exists,
then the system-wide prefs file, and then the built-in preferences. Finally, for
robustness, a default may be optionally hard-coded in the source.
I made several things configurable, too:
the default Tibetan keyboard
the default font sizes and faces
whether you want developer-only features enabled
Savant's file extension (.savant)
etc.
The only known problems are the following:
The default location for the user's preferences file is windows-specific,
arbitrary, and not in the user documentation. Likewise for the location of the
system-wide preferences file. You can change them using 'java -D', though.
There is no "Save preferences" option yet, and closing the program does
not save preferences either.
2002-10-14 04:06:05 +00:00
try {
UIManager . setLookAndFeel ( UIManager . getSystemLookAndFeelClassName ( ) ) ;
}
catch ( Exception e ) {
2002-11-16 19:18:44 +00:00
ThdlDebug . noteIffyCode ( ) ;
Added a flexible mechanism for persistent boolean-, integer-, and
string-valued preferences built atop java.util.Properties.
How it works: the jvm is asked first, and then the user's prefs file, if it exists,
then the system-wide prefs file, and then the built-in preferences. Finally, for
robustness, a default may be optionally hard-coded in the source.
I made several things configurable, too:
the default Tibetan keyboard
the default font sizes and faces
whether you want developer-only features enabled
Savant's file extension (.savant)
etc.
The only known problems are the following:
The default location for the user's preferences file is windows-specific,
arbitrary, and not in the user documentation. Likewise for the location of the
system-wide preferences file. You can change them using 'java -D', though.
There is no "Save preferences" option yet, and closing the program does
not save preferences either.
2002-10-14 04:06:05 +00:00
}
2002-10-04 04:52:41 +00:00
Added a flexible mechanism for persistent boolean-, integer-, and
string-valued preferences built atop java.util.Properties.
How it works: the jvm is asked first, and then the user's prefs file, if it exists,
then the system-wide prefs file, and then the built-in preferences. Finally, for
robustness, a default may be optionally hard-coded in the source.
I made several things configurable, too:
the default Tibetan keyboard
the default font sizes and faces
whether you want developer-only features enabled
Savant's file extension (.savant)
etc.
The only known problems are the following:
The default location for the user's preferences file is windows-specific,
arbitrary, and not in the user documentation. Likewise for the location of the
system-wide preferences file. You can change them using 'java -D', though.
There is no "Save preferences" option yet, and closing the program does
not save preferences either.
2002-10-14 04:06:05 +00:00
JFrame f = new JFrame ( " Jskad " ) ;
Dimension d = f . getToolkit ( ) . getScreenSize ( ) ;
x_size = d . width / 4 * 3 ;
y_size = d . height / 4 * 3 ;
f . setSize ( x_size , y_size ) ;
f . setLocation ( d . width / 8 , d . height / 8 ) ;
2003-06-21 01:26:17 +00:00
final Jskad jskad = new Jskad ( f ) ;
2003-06-21 02:07:51 +00:00
jskads . add ( jskad ) ;
2003-06-21 01:26:17 +00:00
f . getContentPane ( ) . add ( jskad ) ;
Added a flexible mechanism for persistent boolean-, integer-, and
string-valued preferences built atop java.util.Properties.
How it works: the jvm is asked first, and then the user's prefs file, if it exists,
then the system-wide prefs file, and then the built-in preferences. Finally, for
robustness, a default may be optionally hard-coded in the source.
I made several things configurable, too:
the default Tibetan keyboard
the default font sizes and faces
whether you want developer-only features enabled
Savant's file extension (.savant)
etc.
The only known problems are the following:
The default location for the user's preferences file is windows-specific,
arbitrary, and not in the user documentation. Likewise for the location of the
system-wide preferences file. You can change them using 'java -D', though.
There is no "Save preferences" option yet, and closing the program does
not save preferences either.
2002-10-14 04:06:05 +00:00
f . setVisible ( true ) ;
2002-11-18 16:12:25 +00:00
/ * 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 ( ) {
2003-06-21 01:26:17 +00:00
jskad . savePreferencesAction ( ) ;
2002-11-18 16:12:25 +00:00
}
}
) ;
Added a flexible mechanism for persistent boolean-, integer-, and
string-valued preferences built atop java.util.Properties.
How it works: the jvm is asked first, and then the user's prefs file, if it exists,
then the system-wide prefs file, and then the built-in preferences. Finally, for
robustness, a default may be optionally hard-coded in the source.
I made several things configurable, too:
the default Tibetan keyboard
the default font sizes and faces
whether you want developer-only features enabled
Savant's file extension (.savant)
etc.
The only known problems are the following:
The default location for the user's preferences file is windows-specific,
arbitrary, and not in the user documentation. Likewise for the location of the
system-wide preferences file. You can change them using 'java -D', though.
There is no "Save preferences" option yet, and closing the program does
not save preferences either.
2002-10-14 04:06:05 +00:00
} catch ( ThdlLazyException e ) {
2002-11-16 19:18:44 +00:00
// FIXME: tell the users how to submit bug reports.
Added a flexible mechanism for persistent boolean-, integer-, and
string-valued preferences built atop java.util.Properties.
How it works: the jvm is asked first, and then the user's prefs file, if it exists,
then the system-wide prefs file, and then the built-in preferences. Finally, for
robustness, a default may be optionally hard-coded in the source.
I made several things configurable, too:
the default Tibetan keyboard
the default font sizes and faces
whether you want developer-only features enabled
Savant's file extension (.savant)
etc.
The only known problems are the following:
The default location for the user's preferences file is windows-specific,
arbitrary, and not in the user documentation. Likewise for the location of the
system-wide preferences file. You can change them using 'java -D', though.
There is no "Save preferences" option yet, and closing the program does
not save preferences either.
2002-10-14 04:06:05 +00:00
System . err . println ( " Jskad has a BUG: " ) ;
e . getRealException ( ) . printStackTrace ( System . err ) ;
2002-11-16 19:18:44 +00:00
System . exit ( 1 ) ;
Added a flexible mechanism for persistent boolean-, integer-, and
string-valued preferences built atop java.util.Properties.
How it works: the jvm is asked first, and then the user's prefs file, if it exists,
then the system-wide prefs file, and then the built-in preferences. Finally, for
robustness, a default may be optionally hard-coded in the source.
I made several things configurable, too:
the default Tibetan keyboard
the default font sizes and faces
whether you want developer-only features enabled
Savant's file extension (.savant)
etc.
The only known problems are the following:
The default location for the user's preferences file is windows-specific,
arbitrary, and not in the user documentation. Likewise for the location of the
system-wide preferences file. You can change them using 'java -D', though.
There is no "Save preferences" option yet, and closing the program does
not save preferences either.
2002-10-14 04:06:05 +00:00
}
2002-10-04 04:52:41 +00:00
}
}