From 592d1d68707ab25790788d5bc2c4025149f3eb37 Mon Sep 17 00:00:00 2001 From: micha3lp Date: Sat, 12 Aug 2006 22:23:01 +0000 Subject: [PATCH] 1. Dictionary support in Jskad 2. Local fonts from the .jar file are used if TWM fonts not available on the system 3. Bug fix - SWING not rendering font correctly --- source/org/thdl/tib/input/DuffPane.java | 459 +++++++++++++++++- source/org/thdl/tib/input/Jskad.java | 8 +- .../org/thdl/tib/input/PreferenceWindow.java | 320 +++++++++++- .../org/thdl/tib/scanner/StrictDuffPane.java | 2 +- .../org/thdl/tib/text/TibetanLabelView.java | 55 +++ 5 files changed, 823 insertions(+), 21 deletions(-) diff --git a/source/org/thdl/tib/input/DuffPane.java b/source/org/thdl/tib/input/DuffPane.java index 78d9438..eeb7744 100644 --- a/source/org/thdl/tib/input/DuffPane.java +++ b/source/org/thdl/tib/input/DuffPane.java @@ -28,6 +28,8 @@ import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.ActionEvent; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent ; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.io.BufferedWriter; @@ -57,6 +59,10 @@ import javax.swing.text.Style; import javax.swing.text.StyleConstants; import javax.swing.text.StyleContext; import javax.swing.text.StyledDocument; +import javax.swing.JButton; +import javax.swing.JToolBar; +import javax.swing.JFrame; +import javax.swing.JComponent; import org.thdl.tib.text.DuffCode; import org.thdl.tib.text.DuffData; @@ -71,6 +77,17 @@ import org.thdl.util.StatusBar; import org.thdl.util.ThdlDebug; import org.thdl.util.ThdlOptions; +import javax.swing.text.Element; +import org.thdl.tib.scanner.TibetanScanner ; +import org.thdl.tib.scanner.Word ; +import org.thdl.tib.text.Pronounciation; +import org.thdl.tib.input.SettingsServiceProvider; +import org.thdl.tib.input.DictionaryLoadState; +import java.util.Observable ; +import org.thdl.tib.input.GlobalResourceHolder ; +import org.thdl.tib.input.SettingsChangeListener ; + + /** * Enables input of Tibetan text * using Tibetan Computer Company's free cross-platform TibetanMachineWeb fonts. @@ -81,7 +98,9 @@ import org.thdl.util.ThdlOptions; * @author Edward Garrett, Tibetan and Himalayan Digital Library * @version 1.0 */ -public class DuffPane extends TibetanPane implements FocusListener { +public class DuffPane extends TibetanPane + implements FocusListener, SettingsServiceProvider +{ /** * The status bar to update with messages about the current input mode. * Are we expecting a vowel? a subscript? et cetera. @@ -225,18 +244,88 @@ public class DuffPane extends TibetanPane implements FocusListener { private String romanFontFamily; private int romanFontSize; - - protected Clipboard rtfBoard; + +/** +* The current dictionary information +* @TODO these three fields should be one class +*/ + private boolean dictionaryEnabled = false ; + private boolean dictionaryLocal = false ; + private String dictionaryPath ; private Hashtable actions; + private Observable observableObj ; + + protected Clipboard rtfBoard; + +/** +* Range +* +*/ + class Range + { + int startPos ; + int endPos ; + + public Range () + { + startPos = 0 ; + endPos = 0 ; + } + + public Range ( int start, int end ) + { + setRange ( start, end ) ; + } + + public void setRange ( int start, int end ) + { + startPos = start ; + endPos = end ; + } + + int getStartPos () + { + return startPos ; + } + + int getEndPos () + { + return endPos ; + } + + boolean isValid () + { + return ( startPos >= 0 && endPos >= 0 && startPos <= endPos ) ; + } + } + +/** + * the parent frame + */ + protected JFrame mainFrame = null ; + protected DictionaryFrame dictFrame = null ; + protected Pronounciation pronounciation ; + protected JButton buttonToggleDict = null ; + protected JButton buttonLookupDict = null ; /** Initializes this object. All constructors should call this. */ - private void initialize(StatusBar sb, + private void initialize(Object frame, + StatusBar sb, TibetanKeyboard keyboard, java.net.URL keyboardURL) { + observableObj = new Observable () ; + + GlobalResourceHolder.setSettingsServiceProvider ( this ) ; + + if ( null != frame ) + { + initDictionarySupport ( frame ) ; + } + if (null != keyboard) TibetanMachineWeb.setKeyboard(keyboard); if (null != keyboardURL) @@ -251,26 +340,48 @@ public class DuffPane extends TibetanPane implements FocusListener { /** Creates a new DuffPane that updates sb, if sb is not null, with messages about how the users' keypresses are being interpreted. */ + public DuffPane(Object frame, StatusBar sb) { + super(); + initialize(frame, sb, null, null); + } + + public DuffPane(Object frame) { + super(); + initialize(frame, null, null, null); + } + + public DuffPane(Object frame, TibetanKeyboard keyboard) { + super(); + initialize(frame, null, keyboard, null); + } + + public DuffPane(Object frame, java.net.URL keyboardURL) { + super(); + initialize(frame, null, null, keyboardURL); + } + + public DuffPane(StatusBar sb) { super(); - initialize(sb, null, null); + initialize(null, sb, null, null); } public DuffPane() { super(); - initialize(null, null, null); + initialize(null, null, null, null); } public DuffPane(TibetanKeyboard keyboard) { super(); - initialize(null, keyboard, null); + initialize(null, null, keyboard, null); } public DuffPane(java.net.URL keyboardURL) { super(); - initialize(null, null, keyboardURL); + initialize(null, null, null, keyboardURL); } + /** For testing purposes, it's useful to create a DuffPane and not * hook it up to the UI. If this is true, this DuffPane will * manage its document's caret rather than having the UI do @@ -334,6 +445,11 @@ public class DuffPane extends TibetanPane implements FocusListener { "Serif"); romanFontSize = defaultRomanFontSize(); + dictionaryEnabled = defaultDictionarySettingsEnabled () ; + dictionaryLocal = defaultDictionarySettingsLocal () ; + dictionaryPath = defaultDictionarySettingsPath () ; + onDictionarySettingsChanged () ; + newDocument(); caret = getCaret(); @@ -689,6 +805,82 @@ public class DuffPane extends TibetanPane implements FocusListener { return romanFontFamily; } +/** + * //MP add comment + */ + private static boolean defaultDictionarySettingsEnabled () { + return ThdlOptions.getBooleanOption("thdl.default.jskad.dictionary.enabled" + ); + } + +/** + * //MP add comment + */ + private static boolean defaultDictionarySettingsLocal () { + return ThdlOptions.getBooleanOption("thdl.default.jskad.dictionary.local" + ); + } + +/** + * //MP add comment + */ + private static String defaultDictionarySettingsPath () { + return ThdlOptions.getStringOption("thdl.default.jskad.dictionary.path", + "/home/mamrotek/thdl/dict/free" ); + } + +/** + * //MP add comment + */ + public boolean getDictionarySettingsEnabled () + { + return dictionaryEnabled ; + } + + public boolean getDictionarySettingsLocal () + { + return dictionaryLocal ; + } + + public String getDictionarySettingsPath () + { + return dictionaryPath ; + } + +/** + * + */ + public void setByUserDictionarySettings ( boolean enabled, boolean local, String path ) + { + ThdlOptions.setUserPreference("thdl.default.jskad.dictionary.enabled", enabled ); + ThdlOptions.setUserPreference("thdl.default.jskad.dictionary.local", local ); + ThdlOptions.setUserPreference("thdl.default.jskad.dictionary.path", path ); + + setDictionarySettings ( enabled, local, path ) ; + } + +/** + * + */ + public void setDictionarySettings ( boolean enabled, boolean local, String path ) + { + dictionaryEnabled = enabled ; + dictionaryLocal = local ; + dictionaryPath = path ; + + onDictionarySettingsChanged () ; + } + + public int getDictionaryLoadState () + { + return GlobalResourceHolder.getDictionaryLoadState () ; + } + + public void waitForDictionary () + { + GlobalResourceHolder.waitForDictionary () ; + } + /** * Backspace and remove k elements from the current caret position. * @@ -1763,7 +1955,256 @@ public void paste(int offset) } + public void onDictionarySettingsChanged () + { + GlobalResourceHolder.getListener ().update ( getObservable (), + (Object)new Integer ( SettingsChangeListener.DICTIONARY_SETTINGS ) ) ; + if ( null == buttonToggleDict || null == buttonLookupDict ) + return ; + + if ( GlobalResourceHolder.isDictionaryValid () && + GlobalResourceHolder.isDictionaryEnabled () ) + { + buttonToggleDict.setEnabled ( true ) ; + buttonLookupDict.setEnabled ( true ) ; + } + else + { + buttonToggleDict.setEnabled ( false ) ; + buttonLookupDict.setEnabled ( false ) ; + } + + } + + protected void lookupDictionary () + { + Range selection = new Range ( getSelectionStart (), getSelectionEnd () ) ; + + try + { + adjustSelection ( selection ) ; + } + catch ( Exception e ) + { + System.err.println ( e.toString () ) ; + return ; + } + + showCurrentPhraseFromPosInfo ( selection ) ; + } + + private void adjustSelection ( Range selection ) throws Exception + { + TibetanDocument doc = getTibDoc () ; + int startPos = selection.getStartPos () ; + int endPos = selection.getEndPos () ; + + while ( true ) + { + Element el = doc.getCharacterElement ( endPos ) ; + char code = doc.getText ( endPos, 1 ).charAt ( 0 ) ; + int fontNum = TibetanMachineWeb.getTMWFontNumber ( doc.getFont ( el.getAttributes () ).getName () ) ;// getFamily + + if ( 0 == fontNum || TibetanMachineWeb.isTMWFontCharBreakable ( code ) ) + { + endPos -- ; + break ; + } + + if ( endPos >= doc.getLength () - 1 ) + break ; + + endPos ++ ; + } + + if ( endPos < startPos ) + { + startPos = endPos ; + } + + // + // span left + // + while ( true ) + { + Element el = doc.getCharacterElement ( startPos ) ; + char code = doc.getText ( startPos, 1 ).charAt ( 0 ) ; + int fontNum = TibetanMachineWeb.getTMWFontNumber ( doc.getFont ( el.getAttributes () ).getName () ) ;// getFamily + if ( 0 == fontNum || TibetanMachineWeb.isTMWFontCharBreakable ( code ) ) + { + startPos++ ; + break ; + } + + if ( startPos <= 0 ) + break ; + + startPos -- ; + } + + selection.setRange ( startPos, endPos ) ; + } + + protected void showCurrentPhraseFromPosInfo ( Range range ) + { + String word = "" ; + TibetanDocument doc = getTibDoc () ; + int startPos = range.getStartPos () ; + int endPos = range.getEndPos () ; + + // + // collect the text the good way + // + boolean [] noSuch = new boolean [] { false } ; + word = doc.getWylie ( startPos, endPos+1, noSuch ) ; + word = word.replaceAll ( "[\\/\\_\\*]", " " ) ; + + // + // show dictionary data + // + if ( word.length () > 0 ) + { + try + { + dictFrame.reset () ; + dictFrame.setOriginal ( word, doc, startPos, endPos ) ; + dictFrame.setPronounciation ( pronounciation.process ( word ) ) ; + } + catch ( Exception e ) + { + // TODO + } + + TibetanScanner scanner = GlobalResourceHolder.getTibetanScanner () ; + if ( null != scanner ) + { + scanner.scanBody ( word ) ; + scanner.finishUp () ; + Word [] words = scanner.getWordArray () ; + for ( int i = 0; i < words.length ; i++ ) + { + dictFrame.addDescription ( words [i].toString () ) ; + } + + scanner.clearTokens () ; + + dictFrame.setVisible ( true ) ; + dictFrame.requestFocusInWindow () ; + + dictFrame.gotoList () ; + } + } + } + + private void initDictionarySupport ( Object frame ) + { + if ( frame instanceof JFrame ) + mainFrame = (JFrame)frame ; + else + mainFrame = null ; + + try + { + pronounciation = new Pronounciation () ; + } + catch ( Exception e ) + { + System.err.println ( e.toString () ) ; + System.exit ( 1 ) ; + } + + addKeyListener ( new KeyAdapter () + { + public void keyPressed ( KeyEvent ke ) + { + if ( KeyEvent.VK_F12 == ke.getKeyCode () ) + { + toggleDictionaryFrame () ; + } + else if ( KeyEvent.VK_F11 == ke.getKeyCode () ) + { + lookupDictionary () ; + } + } + } + ) ; + } + + public void postInitialize ( JComponent parent ) + { + // + // no main frame - do not init the dictionary frame + // + if ( null == mainFrame ) + return ; + + dictFrame = new DictionaryFrame ( mainFrame ) ; + + JToolBar toolbar = null ; + + System.out.println ( parent.toString () ) ; + for ( int child = 0; child < parent.getComponentCount (); child++ ) + { + if ( parent.getComponent ( child ) instanceof JToolBar ) + { + toolbar = (JToolBar)parent.getComponent ( child ) ; + break ; + } + } + + if ( toolbar != null ) + { + buttonToggleDict = new JButton ( "Tog. Dictionary F12" ) ; + buttonToggleDict.addMouseListener ( new MouseAdapter () + { + public void mouseClicked ( MouseEvent e ) + { + toggleDictionaryFrame () ; + } + } ) ; + + toolbar.add ( buttonToggleDict ) ; + + buttonLookupDict = new JButton ( "Lookup F11" ) ; + buttonLookupDict.addMouseListener ( new MouseAdapter () + { + public void mouseClicked ( MouseEvent e ) + { + lookupDictionary () ; + } + } ) ; + + toolbar.add ( buttonLookupDict ) ; + + buttonToggleDict.setEnabled ( GlobalResourceHolder.isDictionaryValid () && GlobalResourceHolder.isDictionaryEnabled () ) ; + buttonLookupDict.setEnabled ( GlobalResourceHolder.isDictionaryValid () && GlobalResourceHolder.isDictionaryEnabled () ) ; + } + } + + protected void toggleDictionaryFrame () + { + if ( dictFrame.isVisible () ) + dictFrame.setVisible ( false ) ; + else + { + // + // if text selected, feed the dictionary frame + // + + dictFrame.setVisible ( true ) ; + } + } + + public Observable getObservable () + { + return observableObj ; + } + + protected void finalize () + { + GlobalResourceHolder.removeSettingsServiceProvider ( this ) ; + } /** The JDK contains StringSelection, but we want to copy and paste RTF sometimes. Enter RTFSelection. */ @@ -1825,6 +2266,8 @@ class RTFSelection implements ClipboardOwner, Transferable { } } // inner class DuffPane.RTFSelection + + } // class DuffPane // TODO(dchandler): search for 'catch (Throwable' and 'catch diff --git a/source/org/thdl/tib/input/Jskad.java b/source/org/thdl/tib/input/Jskad.java index 044f06d..3e01115 100644 --- a/source/org/thdl/tib/input/Jskad.java +++ b/source/org/thdl/tib/input/Jskad.java @@ -799,9 +799,9 @@ public class Jskad extends JPanel implements DocumentListener { /* Initialize dp before calling JskadKeyboard.activate(DuffPane) or dp.toggleLanguage(). */ if (ThdlOptions.getBooleanOption(Jskad.enableKeypressStatusProp)) { - dp = new DuffPane(statusBar); + dp = new DuffPane(parentObject, statusBar); } else { - dp = new DuffPane(); + dp = new DuffPane(parentObject); } @@ -926,6 +926,8 @@ public class Jskad extends JPanel implements DocumentListener { add("Center", scrollingDuffPane); if (statusBar != null) add("South", statusBar); + + dp.postInitialize ( this ) ; } private void newFile() { @@ -1323,7 +1325,7 @@ public class Jskad extends JPanel implements DocumentListener { try { BufferedReader in = new BufferedReader(new FileReader(txt_fileChosen)); // FIXME: why do we need a whole DuffPane to do this? - DuffPane dp2 = new DuffPane(); + DuffPane dp2 = new DuffPane( parentObject ); try { String val = in.readLine(); diff --git a/source/org/thdl/tib/input/PreferenceWindow.java b/source/org/thdl/tib/input/PreferenceWindow.java index 2d59866..c84706a 100644 --- a/source/org/thdl/tib/input/PreferenceWindow.java +++ b/source/org/thdl/tib/input/PreferenceWindow.java @@ -21,22 +21,54 @@ package org.thdl.tib.input; import java.awt.Component; import java.awt.GraphicsEnvironment; import java.awt.GridLayout; +import java.awt.GridBagLayout; +import java.awt.GridBagConstraints; +import java.awt.Insets; +import java.awt.event.KeyEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemListener; +import javax.swing.BoxLayout; import javax.swing.BorderFactory; import javax.swing.JComboBox; import javax.swing.JDialog; import javax.swing.JOptionPane; import javax.swing.JPanel; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JCheckBox; +import javax.swing.JRadioButton; +import javax.swing.JTextField; +import javax.swing.ButtonGroup; +import java.beans.PropertyChangeListener ; +import java.beans.PropertyChangeEvent ; + +import org.thdl.tib.input.DictionaryLoadState ; /** Shows a standard dialog window to set the preferences for the tibetan and roman script used */ -public class PreferenceWindow +public class PreferenceWindow implements ActionListener, ItemListener { private JDialog dialog; private JComboBox tibetanFontSizes; private JComboBox romanFontSizes; private JComboBox romanFontFamilies; + private JCheckBox dictionaryEnabled ; + private ButtonGroup dictionaryType ; + private JRadioButton dictionaryLocal ; + private JRadioButton dictionaryRemote ; + private JLabel dictionaryPathLabel ; + private JTextField dictionaryPath ; + private JButton dictionaryBrowse ; + private JOptionPane pane ; + + boolean valDictionaryEnabled ; + boolean valDictionaryLocal ; + String valDictionaryPath ; + private DuffPane dp; public PreferenceWindow(Component parent, DuffPane dp) @@ -45,6 +77,14 @@ public class PreferenceWindow GraphicsEnvironment genv = GraphicsEnvironment.getLocalGraphicsEnvironment(); String[] fontNames = genv.getAvailableFontFamilyNames(); + // TODO + valDictionaryEnabled = dp.getDictionarySettingsEnabled () ; + valDictionaryLocal = dp.getDictionarySettingsLocal () ; + valDictionaryPath = dp.getDictionarySettingsPath () ; + + //dp.getDictionarySettings ( valDictionaryEnabled, valDictionaryLocal, valDictionaryPath ) ; + + JPanel tibetanPanel; tibetanPanel = new JPanel(); @@ -71,13 +111,101 @@ public class PreferenceWindow romanPanel.add(romanFontFamilies); romanPanel.add(romanFontSizes); + JPanel dictionaryPanel ; + dictionaryPanel = new JPanel () ; + dictionaryPanel.setBorder ( BorderFactory.createTitledBorder ( "Dictionary" ) ) ; + dictionaryEnabled = new JCheckBox ( "Enable Dictionary Support" ) ; + dictionaryEnabled.setMnemonic ( KeyEvent.VK_E ) ; + dictionaryEnabled.setActionCommand ( "SetDictionaryEnable" ) ; + dictionaryEnabled.addItemListener ( this ) ; + dictionaryLocal = new JRadioButton ( "Local") ; + dictionaryLocal.setActionCommand ( "SetDictionaryLocal" ) ; + dictionaryLocal.setMnemonic ( KeyEvent.VK_L ) ; + dictionaryLocal.addActionListener ( this ) ; + dictionaryRemote = new JRadioButton ( "Remote") ; + dictionaryRemote.setMnemonic ( KeyEvent.VK_R ) ; + dictionaryRemote.setActionCommand ( "SetDictionaryRemote" ) ; + dictionaryRemote.addActionListener ( this ) ; + dictionaryPathLabel = new JLabel ( "Path" ) ; + dictionaryPath = new JTextField () ; + dictionaryBrowse = new JButton ( "Browse" ) ; + dictionaryBrowse.setMnemonic ( KeyEvent.VK_B ) ; + dictionaryBrowse.setActionCommand ( "BrowseDictionaryPath" ) ; + dictionaryBrowse.addActionListener ( this ) ; + dictionaryPanel.setLayout ( new GridBagLayout () ) ; + GridBagConstraints gc = new GridBagConstraints () ; + gc.anchor = GridBagConstraints.NORTHWEST ; + gc.fill = GridBagConstraints.BOTH ; + gc.weightx = 1.0 ; + gc.weighty = 1.0 ; + gc.gridwidth = GridBagConstraints.REMAINDER ; + gc.insets = new Insets ( 1, 1, 1, 1 ) ; + dictionaryPanel.add ( dictionaryEnabled, gc ) ; + gc.gridwidth = GridBagConstraints.RELATIVE ; + dictionaryPanel.add ( dictionaryLocal, gc ) ; + gc.weightx = 0.0 ; + gc.gridwidth = GridBagConstraints.REMAINDER ; + dictionaryPanel.add ( dictionaryRemote, gc ) ; + gc.weightx = 1.0 ; + gc.gridwidth = GridBagConstraints.REMAINDER ; + dictionaryPanel.add ( dictionaryPathLabel, gc ) ; + gc.gridwidth = GridBagConstraints.RELATIVE ; + gc.weightx = 3.0 ; + dictionaryPanel.add ( dictionaryPath, gc ) ; + gc.weightx = 0.0 ; + gc.gridwidth = GridBagConstraints.REMAINDER ; + dictionaryPanel.add ( dictionaryBrowse, gc ) ; + + dictionaryType = new ButtonGroup () ; + dictionaryType.add ( dictionaryLocal ) ; + dictionaryType.add ( dictionaryRemote ) ; + JPanel preferencesPanel = new JPanel(); - preferencesPanel.setLayout(new GridLayout(2,1)); + preferencesPanel.setLayout(new BoxLayout(preferencesPanel,BoxLayout.Y_AXIS)); preferencesPanel.add(tibetanPanel); preferencesPanel.add(romanPanel); + preferencesPanel.add(dictionaryPanel); - JOptionPane pane = new JOptionPane(preferencesPanel); + pane = new JOptionPane(preferencesPanel); + updateDictionaryGui () ; dialog = pane.createDialog(parent, "Preferences"); + + dialog.setDefaultCloseOperation ( JDialog.DO_NOTHING_ON_CLOSE ) ; + + pane.addPropertyChangeListener ( new PropertyChangeListener () + { + public void propertyChange ( PropertyChangeEvent e ) + { + if ( /*dialog.isVisible () &&*/ e.getSource () == pane ) + { + if ( pane.getValue () != null && + e.getPropertyName ().equals ( JOptionPane.VALUE_PROPERTY ) ) + { + if ( pane.getValue ().toString ().equals ( JOptionPane.UNINITIALIZED_VALUE.toString () ) ) + return ; + + int val = ((Integer)pane.getValue ()).intValue () ; + + if ( val == JOptionPane.OK_OPTION ) + { + if ( validateInput () ) + { + + dialog.setVisible ( false ) ; + } + else + { + dialog.setVisible ( true ) ; + } + } + else if ( val == JOptionPane.CANCEL_OPTION ) + { + dialog.setVisible ( false ) ; + } + } + } + } + } ) ; } private static int stringToInt(String s) @@ -108,20 +236,194 @@ public class PreferenceWindow return romanFontFamilies.getSelectedItem().toString(); } + public void setDictionaryEnabled ( boolean enabled ) + { + valDictionaryEnabled = enabled ; + } + + public boolean getDictionaryEnabled () + { + return valDictionaryEnabled ; + } + + public void setDictionaryLocal ( boolean local ) + { + valDictionaryLocal = local ; + } + + public boolean getDictionaryLocal () + { + return valDictionaryLocal ; + } + + public void setDictionaryPath ( String path ) + { + valDictionaryPath = path ; + } + + public String getDictionaryPath () + { + return valDictionaryPath ; + } + + private void readDictionaryGui () + { + valDictionaryEnabled = dictionaryEnabled.isSelected () ; + valDictionaryLocal = dictionaryLocal.isSelected () ; + valDictionaryPath = dictionaryPath.getText () ; + } + + private void updateDictionaryGui () + { + if ( ! valDictionaryEnabled ) + { + dictionaryLocal.setEnabled ( false ) ; + dictionaryRemote.setEnabled ( false ) ; + dictionaryPathLabel.setEnabled ( false ) ; + dictionaryPath.setEnabled ( false ) ; + dictionaryBrowse.setEnabled ( false ) ; + } + else + { + dictionaryLocal.setEnabled ( true ) ; + dictionaryRemote.setEnabled ( true ) ; + + if ( valDictionaryLocal ) + { + dictionaryPathLabel.setEnabled ( true ) ; + dictionaryPathLabel.setText ( "Path" ) ; + dictionaryPath.setEnabled ( true ) ; + dictionaryBrowse.setEnabled ( true ) ; + } + else + { + dictionaryPathLabel.setEnabled ( true ) ; + dictionaryPathLabel.setText ( "URL" ) ; + dictionaryPath.setEnabled ( true ) ; + dictionaryBrowse.setEnabled ( false ) ; + } + } + + if ( valDictionaryEnabled != dictionaryEnabled.isSelected () ) + { + dictionaryEnabled.setSelected ( valDictionaryEnabled ) ; + } + + if ( valDictionaryLocal != dictionaryLocal.isSelected () ) + { + dictionaryLocal.setSelected ( valDictionaryLocal ) ; + dictionaryRemote.setSelected ( !valDictionaryLocal ) ; + } + + dictionaryPath.setText ( valDictionaryPath ) ; + } + + private void guiSetDictionaryEnabled ( boolean enabled ) + { + setDictionaryEnabled ( enabled ) ; + updateDictionaryGui () ; + } + + public void actionPerformed ( ActionEvent e ) + { + if ( e.getActionCommand () == "SetDictionaryLocal" ) + { + setDictionaryLocal ( true ) ; + updateDictionaryGui () ; + } + else if ( e.getActionCommand() == "SetDictionaryRemote" ) + { + setDictionaryLocal ( false ) ; + updateDictionaryGui () ; + } + else if ( e.getActionCommand() == "BrowseDictionaryPath" ) + { + //TODO + } + } + + public void itemStateChanged ( ItemEvent e ) + { + Object source = e.getItemSelectable () ; + + if ( dictionaryEnabled == source ) + { + guiSetDictionaryEnabled ( ( ItemEvent.SELECTED == e.getStateChange () ) ? true : false ) ; + } + } + /** This returns only when the user has closed the dialog */ public void show() { - int size; - String font; + valDictionaryEnabled = dp.getDictionarySettingsEnabled () ; + valDictionaryLocal = dp.getDictionarySettingsLocal () ; + valDictionaryPath = dp.getDictionarySettingsPath () ; + updateDictionaryGui () ; - dialog.show(); - + pane.setOptionType ( JOptionPane.OK_CANCEL_OPTION ) ; + + dialog.show(); + } + + /** + * + */ + protected boolean validateInput () + { + int size; + String font; + + readDictionaryGui () ; + valDictionaryEnabled = getDictionaryEnabled () ; + valDictionaryLocal = getDictionaryLocal () ; + valDictionaryPath = getDictionaryPath () ; + size = getTibetanFontSize(); if (size>0) dp.setByUserTibetanFontSize(size); size = getRomanFontSize(); if (size==-1) size = dp.getRomanFontSize(); font = getRomanFont(); - dp.setByUserRomanAttributeSet(font, size); + dp.setByUserRomanAttributeSet(font, size); + + dp.setByUserDictionarySettings ( valDictionaryEnabled, valDictionaryLocal, valDictionaryPath ) ; + + // + // wait for dictionary status to be either READY or ERROR LOADING + // + dp.waitForDictionary () ; + int dictState = dp.getDictionaryLoadState () ; + + if ( DictionaryLoadState.READY == dictState ) + { + return true ; + } + else if ( DictionaryLoadState.ERROR == dictState ) + { + if ( ask ( "Cannot load dictionary with the current settings\n" + + "Choose Yes to disable the dictionary, or No to correct the settings." ) ) + { + dp.setByUserDictionarySettings ( false, + valDictionaryLocal, + valDictionaryPath ) ; + return true ; + } + } + else + { + System.err.println ( "Dictionary load state incorrect." ) ; + } + + return false ; + } + + + /** + * + */ + protected boolean ask ( String question ) + { + return (JOptionPane.YES_OPTION == + JOptionPane.showConfirmDialog ( pane, question, "Question", JOptionPane.YES_NO_OPTION ) ) ; } -} \ No newline at end of file +} diff --git a/source/org/thdl/tib/scanner/StrictDuffPane.java b/source/org/thdl/tib/scanner/StrictDuffPane.java index 61e87d7..6f094d1 100644 --- a/source/org/thdl/tib/scanner/StrictDuffPane.java +++ b/source/org/thdl/tib/scanner/StrictDuffPane.java @@ -158,4 +158,4 @@ public class StrictDuffPane extends DuffPane ThdlDebug.noteIffyCode(); } } -} \ No newline at end of file +} diff --git a/source/org/thdl/tib/text/TibetanLabelView.java b/source/org/thdl/tib/text/TibetanLabelView.java index e67093a..c7bc653 100644 --- a/source/org/thdl/tib/text/TibetanLabelView.java +++ b/source/org/thdl/tib/text/TibetanLabelView.java @@ -22,6 +22,10 @@ import javax.swing.text.Element; import javax.swing.text.LabelView; import javax.swing.text.Segment; import javax.swing.text.View; +import java.awt.Font; +import javax.swing.text.* ; + +import org.thdl.tib.input.GlobalResourceHolder ; /** A TibetanLabelView is a LabelView that has its own idea, informed * by its knowledge of Tibetan, about where a good place to break @@ -184,4 +188,55 @@ class TibetanLabelView extends LabelView { return this.getGlyphPainter().getBoundedPosition(this, startPos, pos, len); } + + /** When an element contains only diacritic chars, the default + * implementation will return 0.0 (since there is no base char to + * attach the diacritic(s) to. But the painting scheme will ignore + * all zero sized items. The point of the workaround below is just to + * return any non-zero value so that the item doesn't get ignored. + * (Try typint oM in exteded-Wylie kbd mode to see the bug). */ + public float getPreferredSpan ( int axis ) + { + float span = super.getPreferredSpan ( axis ) ; + + // + // the condition should be safe enough, we want an element that has at least one char + // but whose default span is zero. + // + if ( View.X_AXIS == axis && 0.0f == span && + ( getElement ().getEndOffset () - getElement ().getStartOffset () + 1 ) > 0 ) + { + span = 1.0f ; + } + + return span ; + } + + /** + * getFont - we override the method so we can use local fonts + */ + public Font getFont () + { + String fontFamily = (String)getElement ().getAttributes () + .getAttribute ( StyleConstants.FontFamily ) ; + int fontSize = ((Integer)(getElement ().getAttributes () + .getAttribute ( StyleConstants.FontSize ))).intValue () ; + + Font font = null ; + + try + { + font = GlobalResourceHolder.getFont ( fontFamily, fontSize ) ; + + if ( null == font ) + font = super.getFont () ; + } + catch ( Exception e ) + { + System.err.println ( "No font !" ) ; + font = super.getFont () ; + } + + return font ; + } }