InternationalInput.java

Go to the documentation of this file.
00001 // (C) 2003 by Dominique Unruh. GPL 00002 00013 import java.awt.event.*; 00014 import java.awt.*; 00015 import java.util.*; 00016 import javax.swing.*; 00017 import java.io.*; 00018 import java.net.*; 00019 import javax.swing.event.*; 00020 import javax.swing.text.*; 00021 import java.awt.datatransfer.*; 00022 import java.awt.font.*; 00023 import java.awt.geom.*; 00024 import java.awt.print.*; 00025 00029 class IITextArea extends JTextPane 00030 implements KeyListener, InputViewer { 00031 00032 InputManager inputManager = null; 00033 String temporaryInput = ""; 00034 int tempStart = -1, tempEnd; 00035 Keymap keymap; 00036 InternationalInputContext context = null; 00037 InternationalInput internationalInput = null; 00038 SimpleAttributeSet tempStyle; 00039 StyledDocument document = (StyledDocument)getDocument(); 00040 00041 public void addFinal(String input) { 00042 if (tempStart != -1) 00043 throw new IllegalStateException 00044 ("addFinal called while there was temporary input "+ 00045 temporaryInput); 00046 //System.out.println("addFinal("+input+")"); 00047 internationalInput.noCaretCheck = true; 00048 if (getSelectionStart()!=getSelectionEnd()) 00049 replaceSelection(""); 00050 if (internationalInput.lastCaret>getText().length()) 00051 internationalInput.lastCaret = getText().length(); 00052 insert(input,internationalInput.lastCaret); 00053 int normalizeStart = internationalInput.lastCaret; 00054 try { 00055 normalizeStart = internationalInput.normalize 00056 (normalizeStart,getCaretPosition()); 00057 } catch (BadLocationException e) { 00058 e.printStackTrace(); 00059 throw new RuntimeException("Internal error: "+e); 00060 } 00061 internationalInput.lastCaret = getCaretPosition(); 00062 00063 try { 00064 internationalInput.iconify(normalizeStart,internationalInput.lastCaret); 00065 } catch (BadLocationException e) { 00066 e.printStackTrace(); 00067 throw new RuntimeException("Internal error: "+e); 00068 } 00069 00070 if (internationalInput.autoSetFont) internationalInput.autoSetFont(input,true); 00071 00072 // Test. REMOVE 00073 //DefaultStyledDocument d = (DefaultStyledDocument)document; 00074 Element e = document.getParagraphElement(getCaretPosition()); 00075 System.out.print("Paragraph: "+e); 00076 AttributeSet a = e.getAttributes(); 00077 while (a!=null) { 00078 System.out.println("==="); 00079 for (Enumeration en = a.getAttributeNames(); 00080 en.hasMoreElements();) { 00081 Object name = en.nextElement(); 00082 System.out.println(name+" = "+a.getAttribute(name)); 00083 } 00084 a = a.getResolveParent(); 00085 } 00086 00087 internationalInput.noCaretCheck = false; 00088 } 00089 00090 // emulation of JTextArea 00091 public void insert(String txt, int pos) { 00092 setCaretPosition(pos); 00093 replaceSelection(txt); }; 00094 00095 // emulation of JTextArea 00096 public void replaceRange(String txt, int start, int end) { 00097 setSelectionStart(start); 00098 setSelectionEnd(end); 00099 replaceSelection(txt); 00100 } 00101 00102 public void addTemporary(String input) { 00103 if (tempStart != -1) 00104 throw new IllegalStateException 00105 ("addTemporary called while there was temporary input "+ 00106 temporaryInput); 00107 //System.out.println("addTemporary("+input+")"); 00108 internationalInput.noCaretCheck = true; 00109 if (getSelectionStart()!=getSelectionEnd()) 00110 replaceSelection(""); 00111 //input = "["+input+"]"; 00112 if (internationalInput.lastCaret>getText().length()) 00113 internationalInput.lastCaret = getText().length(); 00114 try { 00115 document.insertString(internationalInput.lastCaret,input,tempStyle); 00116 } catch (BadLocationException e) { 00117 throw new RuntimeException(e.toString()); 00118 } 00119 temporaryInput = input; 00120 tempStart = internationalInput.lastCaret; 00121 internationalInput.lastCaret = tempEnd = tempStart+input.length(); 00122 setCaretPosition(internationalInput.lastCaret); 00123 internationalInput.noCaretCheck = false; 00124 if (internationalInput.autoSetFont) internationalInput.autoSetFont(temporaryInput,true); 00125 } 00126 00127 public void removeTemporary() { 00128 if (tempStart == -1) return; 00129 //System.out.println("removeTemporary()"); 00130 internationalInput.noCaretCheck = true; 00131 if (tempStart > tempEnd) 00132 throw new IllegalArgumentException 00133 ("tempStart > tempEnd"); 00134 try { 00135 replaceRange("",tempStart,tempEnd); 00136 } catch (IllegalArgumentException e) { 00137 e.printStackTrace(); 00138 } 00139 internationalInput.lastCaret = tempStart; 00140 tempStart = -1; 00141 internationalInput.noCaretCheck = false; 00142 } 00143 00144 public IITextArea(InputManager _inputManager, 00145 InternationalInputContext _context, 00146 InternationalInput _internationalInput) { 00147 inputManager = _inputManager; 00148 internationalInput = _internationalInput; 00149 context = _context; 00150 addKeyListener(this); 00151 //setLineWrap(true); 00152 //setWrapStyleWord(true); 00153 keymap = addKeymap("IITextArea-keymap",null); 00154 keymap.setDefaultAction(new AbstractAction() { 00155 public void actionPerformed(ActionEvent e) { 00156 internationalInput.keyStroke(e); 00157 }}); 00158 tempStyle = new SimpleAttributeSet(); 00159 StyleConstants.setForeground(tempStyle, Color.blue); 00160 setKeymap(keymap); 00161 } 00162 00163 public void specialKey(int key) { 00164 switch (key) { 00165 case InputManager.KEY_BACKSPACE: 00166 int car = getCaretPosition(); 00167 if (getSelectionStart()!=getSelectionEnd()) 00168 replaceSelection(""); 00169 else if (car>0) { 00170 try { 00171 String str = document.getText(car-1,1); 00172 if (car>=2 && Normalizer.isLowSurrogate(str.charAt(0))) { 00173 str = document.getText(car-2,1); 00174 if (Normalizer.isHighSurrogate(str.charAt(0))) 00175 replaceRange("",car-2,car); 00176 else 00177 replaceRange("",car-1,car); 00178 } 00179 else 00180 replaceRange("",car-1,car); 00181 } catch (BadLocationException e) { 00182 e.printStackTrace(); 00183 throw new RuntimeException 00184 ("Internal error: "+e); 00185 } 00186 } 00187 internationalInput.lastCaret = getCaretPosition(); 00188 break; 00189 default: 00190 throw new IllegalArgumentException("Unknown special key "+key); 00191 } 00192 } 00193 00194 public void keyPressed(KeyEvent e) { 00195 /* Todo.doActions(); */ 00196 int c = e.getKeyCode(); 00197 if (c==KeyEvent.VK_ENTER || c==KeyEvent.VK_BACK_SPACE) 00198 e.consume(); 00199 internationalInput.checkCaret(); 00200 }; 00201 public void keyReleased(KeyEvent e) { 00202 internationalInput.checkCaret(); 00203 }; 00204 public void keyTyped(KeyEvent e) { 00205 internationalInput.checkCaret(); 00206 if (e.getKeyChar()=='\b') 00207 { e.consume(); internationalInput.backSpace(); }; 00208 }; 00209 } 00210 00211 public class InternationalInput extends JPanel 00212 implements InputManagerContext, MouseListener, 00213 KeyListener { 00214 public static final int MIN_FONT_SIZE = 10; 00215 public static final int MAX_FONT_SIZE = 40; 00216 public static final int FONT_SIZE_STEPPING = 2; 00217 public static final int DEFAULT_FONT_SIZE = 14; 00218 00219 // Global variables 00220 InputManager inputManager; 00221 IITextArea inputField; 00222 JScrollPane scrollPane; 00223 boolean disableButtons = false; 00224 JPanel buttons; 00225 JPanel fKeyPanel; 00226 LinkedList fkeys = new LinkedList(); 00227 InternationalInputContext context = null; 00228 Properties properties = null; 00229 String fonts[] = null; 00230 JMenuItem fontMenuItems[] = null; 00231 JMenuItem fontSizeMenuItems[] = null; 00232 JButton noFontItem = new JButton(); 00233 JButton noSizeItem = new JButton(); 00234 JMenu inputMethodMenu = null; 00235 JCheckBoxMenuItem inputMethodMenuItems[] = null; 00236 String inputMethodMenuItemNames[] = null; 00237 JMenu webPageMenu = null; 00238 Clipboard clipboard = null; 00239 boolean noSystemClipboard = false; 00240 Documentation currentDocumentation = 00241 new Documentation() { 00242 public String getFullDocuName() { return "nothing"; } 00243 public String getDocumentation() { 00244 return "<html><head><title>Nothing activated.</title></head><body>"+ 00245 "<h1>Nothing activated</h1>Please activate something (e.g. an input method) "+ 00246 "before trying to access its documentation.</body></html>"; }}; 00247 int fontSize = InternationalInput.DEFAULT_FONT_SIZE; 00248 boolean autoSetFont = false; 00249 boolean noCaretCheck = false; 00250 int lastCaret = 0; 00251 FileChooser fileChooser = null; 00252 File currentFile = null; 00253 PrinterJob printerJob = null; 00254 PageFormat pageFormat = null; 00255 JFrame previewFrame = null; 00256 00257 interface FKey { 00258 AbstractButton getComponent(); 00259 void setKey(String key); 00260 boolean isValid(); 00261 } 00262 public static String fKeyCombineString(String key, String name) { 00263 return "<html><font face=sansserif size=-1><b>"+key+"</b> "+name; 00264 } 00265 class WebPageFKey implements FKey { 00266 JButton button; 00267 InputManager.WebPage webpage; 00268 public void init() { 00269 if (button!=null) return; 00270 button = new JButton("uninitialized"); 00271 button.addActionListener(new ActionListener() { 00272 public void actionPerformed(ActionEvent e) { 00273 callWebPage(webpage); 00274 inputField.requestFocus(); 00275 }}); 00276 button.setToolTipText(webpage.getName()); 00277 button.setBorderPainted(false); 00278 button.setMargin(new Insets(0,0,0,0)); 00279 button.setFont(button.getFont().deriveFont(Font.PLAIN)); 00280 } 00281 public boolean isValid() { return true; }; 00282 public WebPageFKey(InputManager.WebPage wp) { 00283 webpage = wp; } 00284 public AbstractButton getComponent() { 00285 return button; } 00286 public void setKey(String key) { 00287 if (button==null) init(); 00288 button.setText(fKeyCombineString(key,webpage.getShortName())); 00289 } 00290 public boolean equals(Object a) { 00291 if (!(a instanceof WebPageFKey)) return false; 00292 if (webpage != ((WebPageFKey)a).webpage) return false; 00293 return true; 00294 } 00295 } 00296 class GroupFKey implements FKey { 00297 JCheckBox button; 00298 String name; 00299 String screenName; 00300 public void init() { 00301 if (button!=null) return; 00302 button = new JCheckBox("uninitialized", 00303 inputManager.isInputMethodActive(name)); 00304 screenName = inputManager.getInputMethodScreenName(name); 00305 button.addActionListener(new ActionListener() { 00306 public void actionPerformed(ActionEvent e) { 00307 try { 00308 breakComposition(); 00309 if (button.isSelected()) { 00310 inputManager.activateGroup(name); 00311 //currentDocumentation = 00312 //inputManager.getGroup(name); 00313 } else 00314 inputManager.deactivateGroup(name); 00315 } catch (IOException ex) { 00316 ex.printStackTrace(); 00317 showMessage("Could not activate "+name+": "+ex.toString()); 00318 } 00319 inputField.requestFocus(); 00320 }}); 00321 button.setMargin(new Insets(0,0,0,0)); 00322 button.setFont(button.getFont().deriveFont(Font.PLAIN)); 00323 } 00324 public boolean isValid() { 00325 if (button==null) init(); 00326 boolean newState = inputManager.isInputMethodActive(name); 00327 if (newState!=button.isSelected()) 00328 button.setSelected(newState); 00329 return !inputManager.getGroup(name).isHidden(); 00330 }; 00331 public GroupFKey(String _name) { 00332 name = _name; } 00333 public AbstractButton getComponent() { 00334 return button; } 00335 public void setKey(String key) { 00336 if (button==null) init(); 00337 button.setText(fKeyCombineString(key,screenName)); 00338 } 00339 public boolean equals(Object a) { 00340 if (!(a instanceof GroupFKey)) return false; 00341 if (!name.equals(((GroupFKey)a).name)) return false; 00342 return true; 00343 } 00344 } 00345 00346 public InternationalInput(InternationalInputContext _context) { 00347 context = _context; 00348 try { 00349 inputManager = new InputManager(this); 00350 } catch (IOException e) { 00351 throw new RuntimeException(e.getMessage()); 00352 } 00353 00354 setLayout(new BorderLayout()); 00355 00356 inputField = new IITextArea(inputManager,context,this); 00357 inputManager.setViewer(inputField); 00358 scrollPane = new JScrollPane(); 00359 scrollPane.setViewportView(inputField); 00360 add("Center",scrollPane); 00361 00362 /* // Buttons not needed. 00363 JButton copybutton = new JButton("Copy"); 00364 copybutton.addActionListener(new ActionListener() { 00365 public void actionPerformed(ActionEvent e) { 00366 copyText(false); 00367 inputField.requestFocus(); 00368 System.out.println("Copy: "+inputField.getSelected()); 00369 }}); 00370 JButton clearbutton = new JButton("Clear"); 00371 clearbutton.addActionListener(new ActionListener() { 00372 public void actionPerformed(ActionEvent e) { 00373 inputField.clearText(); 00374 inputField.requestFocus(); 00375 }}); 00376 buttons = new JPanel(); 00377 buttons.add(copybutton); 00378 buttons.add(clearbutton); 00379 if (!disableButtons) add("South",buttons); 00380 else buttons = null; 00381 */ 00382 00383 fKeyPanel = new JPanel(); 00384 //fKeyPanel.setLayout(new FlowLayout(FlowLayout.LEFT,0,0)); 00385 fKeyPanel.setLayout(new VerticalFlowLayout(FlowLayout.LEFT,0,0)); 00386 //fKeyPanel.setLayout(new GridLayout(4,3)); 00387 add("South",fKeyPanel); 00388 00389 initMenu(); 00390 applyProperties(); 00391 00392 updateFKeys(); 00393 00394 //addMouseMotionListener(this); 00395 //addMouseListener(this); 00396 //addFocusListener(this); 00397 addKeyListener(this); 00398 //inputField.addMouseMotionListener(this); 00399 inputField.addMouseListener(this); 00400 //inputField.addFocusListener(this); 00401 inputField.addKeyListener(this); 00402 00403 //RepaintManager.currentManager(this).setDoubleBufferingEnabled(false); 00404 //setDebugGraphicsOptions(DebugGraphics.LOG_OPTION); 00405 } 00406 00407 // F1 not supported in IE 00408 public static final String fKeyNames[] = { 00409 "F2", "F3", "F4", "F5", "F6", 00410 "F7", "F8", "F9", "F10", "F11", "F12" }; 00411 public static final int fKeyCodes[] = { 00412 KeyEvent.VK_F2, KeyEvent.VK_F3, KeyEvent.VK_F4, 00413 KeyEvent.VK_F5, KeyEvent.VK_F6, KeyEvent.VK_F7, KeyEvent.VK_F8, 00414 KeyEvent.VK_F9, KeyEvent.VK_F10, KeyEvent.VK_F11, KeyEvent.VK_F12, 00415 }; 00416 public void updateFKeys() { 00417 if (fKeyPanel==null) return; 00418 fKeyPanel.removeAll(); 00419 int keyNum = 0; 00420 boolean empty = true; 00421 for (ListIterator it = fkeys.listIterator(); 00422 it.hasNext();) { 00423 FKey fkey = (FKey)it.next(); 00424 if (!fkey.isValid()) { it.remove(); continue; }; 00425 if (keyNum < fKeyNames.length) fkey.setKey(fKeyNames[keyNum]); 00426 else fkey.setKey(""); 00427 AbstractButton button = fkey.getComponent(); 00428 if (keyNum < fKeyCodes.length) 00429 button.setMnemonic(fKeyCodes[keyNum]); 00430 else button.setMnemonic(KeyEvent.VK_UNDEFINED); 00431 fKeyPanel.add(button); 00432 keyNum++; empty = false; 00433 } 00434 fKeyPanel.setVisible(!empty); 00435 repaint(getBounds()); 00436 //System.out.println("fKeyPanel, pref "+fKeyPanel.getPreferredSize()); 00437 //System.out.println("fKeyPanel, min "+fKeyPanel.getMinimumSize()); 00438 } 00439 00440 boolean checkFKeyHotKey(int code) { 00441 int num = 0; 00442 ListIterator it = fkeys.listIterator(); 00443 while (it.hasNext() && num < fKeyCodes.length) { 00444 FKey fkey = (FKey)it.next(); 00445 if (fKeyCodes[num]==code) { 00446 fkey.getComponent().doClick(); 00447 return true; 00448 } 00449 num++; 00450 } 00451 return false; 00452 } 00453 00454 public void addFKey(FKey fkey) { 00455 int num = 0; 00456 for (ListIterator it = fkeys.listIterator(); 00457 it.hasNext(); num++) 00458 if (fkey.equals(it.next())) return; 00459 if (num>fKeyCodes.length-1 || num>fKeyNames.length-1) 00460 fkeys.removeFirst(); 00461 fkeys.add(fkey); 00462 updateFKeys(); 00463 revalidate(); 00464 } 00465 00466 public InternationalInputContext getInternationalInputContext() { 00467 return context; }; 00468 00469 public void showMessage(String msg) { 00470 System.out.println(msg); 00471 try { 00472 context.showInfo(msg, true); 00473 } catch (UnsupportedOperationException e) {}; 00474 } 00475 00476 public void createIMMenu(String im[]) { 00477 inputMethodMenuItems = new JCheckBoxMenuItem[im.length]; 00478 inputMethodMenuItemNames = new String[im.length]; 00479 HashMap groups = new HashMap(im.length); 00480 JMenu imMenus[] = new JMenu[27]; 00481 char h[] = new char[1]; 00482 boolean createSubMenus = (im.length>27); 00483 00484 inputMethodMenu.removeAll(); 00485 00486 // Input method->None 00487 JMenuItem clearMenu = new JMenuItem("None (0)"); 00488 clearMenu.setMnemonic(KeyEvent.VK_0); 00489 clearMenu.addActionListener(new ActionListener() { 00490 public void actionPerformed(ActionEvent e) { 00491 inputManager.deselectNonHiddenGroups(); 00492 }}); 00493 inputMethodMenu.add(clearMenu); 00494 00495 // Input method->single 00496 JCheckBoxMenuItem singleMenuItem = new JCheckBoxMenuItem 00497 ("Single (1)",inputManager.getSingleInputMethod()); 00498 singleMenuItem.setMnemonic(KeyEvent.VK_1); 00499 singleMenuItem.addActionListener(new ActionListener() { 00500 public void actionPerformed(ActionEvent e) { 00501 JCheckBoxMenuItem item = 00502 (JCheckBoxMenuItem)(e.getSource()); 00503 try { 00504 inputManager.setSingleInputMethod(item.isSelected()); 00505 } catch (IOException ex) { 00506 showMessage(ex.toString()); ex.printStackTrace(); } 00507 }}); 00508 inputMethodMenu.add(singleMenuItem); 00509 inputMethodMenu.add(new JSeparator()); 00510 00511 for (int i=0; i<im.length; i++) { 00512 if (im[i]==null) continue; 00513 String screenName = inputManager.getInputMethodScreenName(im[i]); 00514 JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(screenName); 00515 00516 inputMethodMenuItemNames[i] = im[i]; 00517 inputMethodMenuItems[i] = menuItem; 00518 menuItem.addActionListener((new ActionListener() { 00519 String name = null; 00520 ActionListener init(String n) { name = n; return this; }; 00521 public void actionPerformed(ActionEvent e) { 00522 try { 00523 JCheckBoxMenuItem m = (JCheckBoxMenuItem)e.getSource(); 00524 breakComposition(); 00525 if (m.isSelected()) { 00526 inputManager.activateGroup(name); 00527 //currentDocumentation = 00528 //inputManager.getGroup(name); 00529 } else 00530 inputManager.deactivateGroup(name); 00531 } catch (IOException ex) { 00532 ex.printStackTrace(); 00533 showMessage("Could not activate "+name+": "+ex.toString()); 00534 } 00535 }}).init(im[i])); 00536 00537 String groupName = screenName.replaceFirst("\\s*[\\(-/].*",""); 00538 JMenu container = (JMenu)groups.get(groupName); 00539 if (container == null) { 00540 container = new JMenu(groupName); 00541 groups.put(groupName,container); 00542 } 00543 container.add(menuItem); 00544 } 00545 00546 Iterator it=groups.values().iterator(); 00547 while (it.hasNext()) { 00548 JMenuItem menuItem = (JMenu)it.next(); 00549 if (menuItem == null) continue; 00550 if (((JMenu)menuItem).getItemCount()==1) 00551 menuItem = ((JMenu)menuItem).getItem(0); 00552 if (createSubMenus) { 00553 h[0] = menuItem.getText().charAt(0); 00554 int num; 00555 String name; 00556 if (h[0] >= 'A' && h[0] <= 'Z') { 00557 num = h[0]-'A'; 00558 name = new String(h)+"..."; 00559 } else if (h[0] >= 'a' && h[0] <= 'z') { 00560 num = h[0]-'a'; 00561 h[0] += 'A'-'a'; 00562 name = new String(h)+"..."; 00563 } else { 00564 num = 26; 00565 name = "others (*)"; 00566 } 00567 if (imMenus[num]==null) 00568 imMenus[num] = new JMenu(name); 00569 imMenus[num].add(menuItem); 00570 } else { 00571 inputMethodMenu.add(menuItem); 00572 } 00573 } 00574 00575 00576 if (createSubMenus) { 00577 for (int i=0; i<27; i++) { 00578 if (imMenus[i]==null) continue; 00579 if (imMenus[i].getItemCount()==1) { 00580 JMenuItem sub = imMenus[i].getItem(0); 00581 sub.setMnemonic((i<26)?('A'+i):'*'); 00582 inputMethodMenu.add(sub); 00583 } else { 00584 imMenus[i].setMnemonic((i<26)?('A'+i):'*'); 00585 mnemonifyMenu(imMenus[i],true); 00586 inputMethodMenu.add(imMenus[i]); 00587 } 00588 }; 00589 } else 00590 mnemonifyMenu(inputMethodMenu,false); 00591 updateIMMenu(); 00592 }; 00593 00594 public void createWebPageMenu(InputManager.WebPage wp[]) { 00595 JMenuItem webPageMenuItems[] = new JMenuItem[wp.length]; 00596 //webPageMenuItemNames = new String[wp.length]; 00597 JMenu wpMenus[] = new JMenu[27]; 00598 char h[] = new char[1]; 00599 boolean createSubMenus = (wp.length>20); 00600 00601 webPageMenu.removeAll(); 00602 00603 for (int i=0; i<wp.length; i++) { 00604 if (wp[i]==null) continue; 00605 String screenName = wp[i].getName(); 00606 JMenuItem menuItem = new JMenuItem(screenName); 00607 00608 webPageMenuItems[i] = menuItem; 00609 menuItem.addActionListener((new ActionListener() { 00610 InputManager.WebPage wp; 00611 ActionListener init(InputManager.WebPage _wp) { 00612 wp=_wp; return this; }; 00613 public void actionPerformed(ActionEvent e) { 00614 addFKey(new WebPageFKey(wp)); 00615 callWebPage(wp); 00616 }}).init(wp[i])); 00617 // Leads to Gfx-Errors 00618 //menuItem.setToolTipText(wp[i].getToolTipText()); 00619 00620 if (createSubMenus) { 00621 h[0] = screenName.charAt(0); 00622 int num; 00623 String name; 00624 if (h[0] >= 'A' && h[0] <= 'Z') { 00625 num = h[0]-'A'; 00626 name = new String(h)+"..."; 00627 } else if (h[0] >= 'a' && h[0] <= 'z') { 00628 num = h[0]-'a'; 00629 h[0] += 'A'-'a'; 00630 name = new String(h)+"..."; 00631 } else { 00632 num = 26; 00633 name = "others (*)"; 00634 } 00635 if (wpMenus[num]==null) 00636 wpMenus[num] = new JMenu(name); 00637 wpMenus[num].add(menuItem); 00638 } else { 00639 webPageMenu.add(menuItem); 00640 } 00641 } 00642 if (createSubMenus) { 00643 for (int i=0; i<27; i++) { 00644 if (wpMenus[i]==null) continue; 00645 wpMenus[i].setMnemonic((i<26)?('A'+i):'*'); 00646 mnemonifyMenu(wpMenus[i],true); 00647 webPageMenu.add(wpMenus[i]); 00648 }; 00649 } else 00650 mnemonifyMenu(webPageMenu,false); 00651 }; 00652 00653 public void groupStateChanged(String name, boolean active) { 00654 FKey fkey = new GroupFKey(name); 00655 if (active) currentDocumentation = inputManager.getGroup(name); 00656 addFKey(fkey); 00657 updateFKeys(); 00658 updateIMMenu(); 00659 } 00660 00661 public void updateIMMenu() { 00662 if (inputMethodMenuItems==null) return; 00663 for (int i=0; i<inputMethodMenuItems.length; i++) { 00664 JCheckBoxMenuItem item = inputMethodMenuItems[i]; 00665 if (item==null) continue; 00666 String name = inputMethodMenuItemNames[i]; 00667 item.setSelected(inputManager.isInputMethodActive(name)); 00668 } 00669 } 00670 00671 void applyProperties() { 00672 try { 00673 properties = context.getProperties(new String[] { "config", "font", "text" }); 00674 } catch (UnsupportedOperationException e) { 00675 properties = new Properties(); 00676 } 00677 00678 String paramConfig = properties.getProperty("config","config.inp.gz"); 00679 try { 00680 URL configURL; 00681 try { 00682 configURL = new URL(context.getDocumentBase(),paramConfig); 00683 } catch (UnsupportedOperationException e) { 00684 configURL = new URL(paramConfig); 00685 }; 00686 inputManager.loadConfig(configURL); 00687 } catch (Exception e) { 00688 e.printStackTrace(); 00689 showMessage("While trying to load initial config file "+ 00690 paramConfig+":\n"+e); 00691 } 00692 00693 String defaultFont = properties.getProperty 00694 ("font","Arial Unicode MS, Code2000, Bitstream Cyberbit"); 00695 if (defaultFont!=null) { 00696 String fontList = defaultFont; 00697 boolean fontLoaded = false; 00698 StringBuffer errors = new StringBuffer(); 00699 while (fontList!=null && !fontLoaded) { 00700 String font; 00701 int index = fontList.indexOf(','); 00702 if (index==-1) { 00703 font = fontList.trim(); 00704 fontList = null; 00705 } else { 00706 font = fontList.substring(0,index).trim(); 00707 fontList = fontList.substring(index+1).trim(); 00708 } 00709 //System.out.println("["+font+"] ["+fontList+"]"); 00710 try { 00711 setInputFont(font); 00712 fontLoaded = true; 00713 } catch (RuntimeException e) { 00714 errors.append(e.getMessage()); 00715 errors.append('\n'); 00716 } 00717 } 00718 if (!fontLoaded) { 00719 System.out.println("Could not load default font "+ 00720 defaultFont+":"); 00721 System.out.print(errors); } 00722 } 00723 00724 String initialText = properties.getProperty("text"); 00725 if (initialText!=null) { 00726 inputField.setText(initialText); 00727 } 00728 } 00729 00735 public static void mnemonifyMenu(JMenu menu, boolean override) { 00736 final int maxCharCode = 127; 00737 Component components[] = menu.getMenuComponents(); 00738 //System.out.println(menu); 00739 HashSet usedMnemonics = new HashSet(); 00740 if (!override) { 00741 for (int i=0; i<components.length; i++) { 00742 if (!(components[i] instanceof JMenuItem)) continue; 00743 JMenuItem item = (JMenuItem)components[i]; 00744 int mnemonic = item.getMnemonic(); 00745 if (mnemonic==KeyEvent.VK_UNDEFINED) continue; 00746 usedMnemonics.add(new Integer(mnemonic)); 00747 } 00748 } 00749 for (int i=0; i<components.length; i++) { 00750 //System.out.println(components[i]); 00751 if (!(components[i] instanceof JMenuItem)) continue; 00752 JMenuItem item = (JMenuItem)components[i]; 00753 if (item instanceof JMenu) mnemonifyMenu((JMenu)item,override); 00754 if (!override && item.getMnemonic()!=KeyEvent.VK_UNDEFINED) 00755 continue; 00756 String text = item.getText().toUpperCase(); 00757 int strLen = text.length(); 00758 for (int j=0; j<=strLen; j++) { 00759 if (j==strLen) { 00760 item.setMnemonic(KeyEvent.VK_UNDEFINED); break; } 00761 char c = text.charAt(j); 00762 if (c<=maxCharCode) { 00763 item.setMnemonic(c); 00764 int mnemonic = item.getMnemonic(); 00765 if (!usedMnemonics.contains(new Integer(mnemonic))) { 00766 usedMnemonics.add(new Integer(mnemonic)); 00767 break; 00768 } 00769 } 00770 } 00771 } 00772 } 00773 00774 final static int PERMISSION_READ = 1; 00775 final static int PERMISSION_WRITE = 2; 00776 final static int PERMISSION_PRINT = 3; 00777 final static int PERMISSION_EXIT = 4; 00778 boolean checkPossiblePermission(int permission) { 00779 SecurityManager securityManager; 00780 switch (permission) { 00781 case PERMISSION_READ: 00782 File roots[] = File.listRoots(); 00783 return (roots!=null && roots.length>0); 00784 case PERMISSION_WRITE: 00785 securityManager = System.getSecurityManager(); 00786 if (securityManager==null) return true;; 00787 roots = File.listRoots(); 00788 if (roots!=null) { 00789 for (int i=0; i<roots.length; i++) { 00790 try { 00791 securityManager.checkWrite(roots[i].toString()); 00792 return true; 00793 } catch (SecurityException e) {}; 00794 } 00795 } 00796 return false; 00797 case PERMISSION_PRINT: 00798 // Checking leads to a box asking the user. 00799 // Therefore we omit this test and assume permission. 00800 return true; 00801 /*try { 00802 securityManager = System.getSecurityManager(); 00803 if (securityManager != null) securityManager.checkPrintJobAccess(); 00804 return true; 00805 } catch (SecurityException e) {}; 00806 return false;*/ 00807 case PERMISSION_EXIT: 00808 try { 00809 securityManager = System.getSecurityManager(); 00810 if (securityManager != null) securityManager.checkExit(0); 00811 return true; 00812 } catch (SecurityException e) {}; 00813 return false; 00814 default: 00815 throw new IllegalArgumentException 00816 ("Internal Error: Unknown permission "+permission); 00817 } 00818 } 00819 00820 void initMenu() { 00821 SecurityManager securityManager = System.getSecurityManager(); 00822 JMenuBar menuBar = new JMenuBar(); 00823 JMenuItem menuItem = null; 00824 JMenu subMenu = null; 00825 JMenu menu = null; 00826 00827 menu = new JMenu("File"); 00828 menu.setMnemonic(KeyEvent.VK_F); 00829 boolean emptyMenu = true; 00830 00831 // File->Open... 00832 if (checkPossiblePermission(PERMISSION_READ)) { 00833 menuItem = new JMenuItem("Open..."); 00834 menuItem.setMnemonic(KeyEvent.VK_O); 00835 menuItem.addActionListener(new ActionListener() { 00836 public void actionPerformed(ActionEvent e) { 00837 try { 00838 initFileChooser(); fileChooser.setSelectedFile(currentFile); 00839 if (fileChooser.showDialog(FileChooser.MODE_OPEN) 00840 == JFileChooser.APPROVE_OPTION) 00841 openFile(fileChooser.getSelectedFile(), 00842 fileChooser.getEncoding(), 00843 fileChooser.getOptionInsert(), 00844 fileChooser.getOptionAsInput()); 00845 } catch (Exception ex) { 00846 ex.printStackTrace(); 00847 showMessage("Could not open file: "+ex); } 00848 }}); 00849 menu.add(menuItem); 00850 00851 emptyMenu = false; 00852 } 00853 00854 if (checkPossiblePermission(PERMISSION_WRITE)) { 00855 // File->Save as... 00856 menuItem = new JMenuItem("Save as..."); 00857 menuItem.setMnemonic(KeyEvent.VK_A); 00858 menuItem.addActionListener(new ActionListener() { 00859 public void actionPerformed(ActionEvent e) { 00860 try { 00861 initFileChooser(); fileChooser.setSelectedFile(currentFile); 00862 if (fileChooser.showDialog(FileChooser.MODE_SAVE) 00863 == JFileChooser.APPROVE_OPTION) 00864 saveFile(fileChooser.getSelectedFile(), 00865 fileChooser.getEncoding(), 00866 fileChooser.getOptionSaveSelection()); 00867 } catch (Exception ex) { 00868 ex.printStackTrace(); 00869 showMessage("Could not open file: "+ex); } 00870 }}); 00871 menu.add(menuItem); 00872 emptyMenu = false; 00873 } 00874 00875 if (checkPossiblePermission(PERMISSION_READ)) { 00876 // File->Load config 00877 menuItem = new JMenuItem("Load config..."); 00878 menuItem.setMnemonic('l'); 00879 menuItem.addActionListener(new ActionListener() { 00880 public void actionPerformed(ActionEvent e) { 00881 try { 00882 initFileChooser(); fileChooser.setSelectedFile(null); 00883 if (fileChooser.showDialog(FileChooser.MODE_LOAD) 00884 == JFileChooser.APPROVE_OPTION) 00885 loadConfig(fileChooser.getSelectedFile()); 00886 } catch (Exception ex) { 00887 ex.printStackTrace(); 00888 showMessage("Could not open file: "+ex); } 00889 }}); 00890 menu.add(menuItem); 00891 emptyMenu = false; 00892 } 00893 00894 if (checkPossiblePermission(PERMISSION_PRINT)) { 00895 if (!emptyMenu) menu.add(new JSeparator()); 00896 00897 // File->Print 00898 menuItem = new JMenuItem("Print..."); 00899 menuItem.setMnemonic('p'); 00900 menuItem.addActionListener(new ActionListener() { 00901 public void actionPerformed(ActionEvent e) { 00902 try { 00903 if (printerJob==null) { 00904 printerJob = PrinterJob.getPrinterJob(); 00905 pageFormat = printerJob.defaultPage(); } 00906 00907 PrintableText job = 00908 new PrintableText(getSelected(), 00909 inputField.getFont()); 00910 printerJob.setPrintable(job,pageFormat); 00911 if (printerJob.printDialog()) { 00912 printerJob.print(); 00913 } 00914 } catch (Exception ex) { 00915 ex.printStackTrace(); 00916 showMessage("Could not print: "+ex); 00917 } 00918 }}); 00919 menu.add(menuItem); 00920 00921 // File->Page setup... 00922 menuItem = new JMenuItem("Page setup..."); 00923 menuItem.setMnemonic('u'); 00924 menuItem.addActionListener(new ActionListener() { 00925 public void actionPerformed(ActionEvent e) { 00926 try { 00927 if (printerJob==null) { 00928 printerJob = PrinterJob.getPrinterJob(); 00929 pageFormat = printerJob.defaultPage(); } 00930 pageFormat = printerJob.pageDialog(pageFormat); 00931 } catch (Exception ex) { 00932 ex.printStackTrace(); 00933 showMessage("Could not change page format: "+ex); 00934 } 00935 }}); 00936 menu.add(menuItem); 00937 00938 // File->Page setup... 00939 menuItem = new JMenuItem("Print preview"); 00940 menuItem.setMnemonic('v'); 00941 menuItem.addActionListener(new ActionListener() { 00942 public void actionPerformed(ActionEvent e) { 00943 try { 00944 if (printerJob==null) { 00945 printerJob = PrinterJob.getPrinterJob(); 00946 pageFormat = printerJob.defaultPage(); } 00947 PrintableText job = 00948 new PrintableText(getSelected(), 00949 inputField.getFont()); 00950 previewFrame = job.showPreview(previewFrame,pageFormat); 00951 } catch (Exception ex) { 00952 ex.printStackTrace(); 00953 showMessage("Could not show print preview: "+ex); 00954 } 00955 }}); 00956 menu.add(menuItem); 00957 00958 emptyMenu = false; 00959 } 00960 00961 boolean mayExit = true; 00962 try { 00963 mayExit = context.isExitAllowed(); 00964 } catch (UnsupportedOperationException e) {}; 00965 if (mayExit && 00966 checkPossiblePermission(PERMISSION_EXIT)) { 00967 // File->Exit 00968 if (!emptyMenu) menu.add(new JSeparator()); 00969 menuItem = new JMenuItem("Exit"); 00970 menuItem.setMnemonic(KeyEvent.VK_X); 00971 menuItem.addActionListener(new ActionListener() { 00972 public void actionPerformed(ActionEvent e) { 00973 try { 00974 System.exit(0); 00975 } catch (Exception ex) { 00976 ex.printStackTrace(); 00977 showMessage("Could not open file: "+ex); } 00978 }}); 00979 menu.add(menuItem); 00980 emptyMenu = false; 00981 } 00982 00983 // File 00984 if (!emptyMenu) menuBar.add(menu); 00985 00986 menu = new JMenu("Edit"); 00987 menu.setMnemonic(KeyEvent.VK_E); 00988 menuBar.add(menu); 00989 00990 // Edit->Copy 00991 menuItem = new JMenuItem("Copy"); 00992 menuItem.setMnemonic(KeyEvent.VK_C); 00993 menuItem.addActionListener(new ActionListener() { 00994 public void actionPerformed(ActionEvent e) { 00995 copyText(false); 00996 }}); 00997 menu.add(menuItem); 00998 00999 // Edit->Paste 01000 menuItem = new JMenuItem("Paste"); 01001 menuItem.setMnemonic(KeyEvent.VK_P); 01002 menuItem.addActionListener(new ActionListener() { 01003 public void actionPerformed(ActionEvent e) { 01004 pasteText(false); 01005 }}); 01006 menu.add(menuItem); 01007 01008 // Edit->Paste as input 01009 menuItem = new JMenuItem("Paste as input"); 01010 menuItem.setMnemonic(KeyEvent.VK_I); 01011 menuItem.addActionListener(new ActionListener() { 01012 public void actionPerformed(ActionEvent e) { 01013 pasteText(true); 01014 }}); 01015 menu.add(menuItem); 01016 01017 // Edit->Clear 01018 menuItem = new JMenuItem("Clear"); 01019 menuItem.setMnemonic(KeyEvent.VK_L); 01020 menuItem.addActionListener(new ActionListener() { 01021 public void actionPerformed(ActionEvent e) { 01022 clearText(); 01023 }}); 01024 menu.add(menuItem); 01025 01026 inputMethodMenu = new JMenu("Input method"); 01027 inputMethodMenu.setMnemonic(KeyEvent.VK_I); 01028 menuBar.add(inputMethodMenu); 01029 01030 webPageMenu = new JMenu("Web page"); 01031 webPageMenu.setMnemonic(KeyEvent.VK_W); 01032 menuBar.add(webPageMenu); 01033 01034 menu = new JMenu("Font"); 01035 menu.setMnemonic(KeyEvent.VK_O); 01036 menuBar.add(menu); 01037 01038 // Font->Select best 01039 menuItem = new JMenuItem("Select best (!)"); 01040 menuItem.setMnemonic('!'); 01041 menuItem.addActionListener(new ActionListener() { 01042 public void actionPerformed(ActionEvent e) { 01043 String name = autoSetFont(getSelected(),false); 01044 String info; 01045 if (name==null) { 01046 info = "Font not changed ("+ 01047 inputField.getFont().getFamily()+")"; 01048 } else { 01049 info = "Font changed to "+name; 01050 } 01051 showMessage(info); 01052 }}); 01053 menu.add(menuItem); 01054 01055 // Font->Auto select 01056 menuItem = new JCheckBoxMenuItem("Auto select (@)",false); 01057 menuItem.setMnemonic('@'); 01058 menuItem.addActionListener(new ActionListener() { 01059 public void actionPerformed(ActionEvent e) { 01060 JCheckBoxMenuItem item = (JCheckBoxMenuItem)e.getSource(); 01061 setAutoSetFont(item.isSelected()); 01062 }}); 01063 menu.add(menuItem); 01064 01065 // Font->Font Viewer 01066 subMenu = new JMenu("Font Viewer (?)"); 01067 subMenu.setMnemonic('?'); 01068 menu.add(subMenu); 01069 01070 // Font->Font Viewer->All fonts (sample) 01071 menuItem = new JMenuItem("All fonts (sample)"); 01072 menuItem.setMnemonic('a'); 01073 menuItem.addActionListener(new ActionListener() { 01074 public void actionPerformed(ActionEvent e) { 01075 new FontViewer().showSample(getSelected()); 01076 }}); 01077 subMenu.add(menuItem); 01078 01079 // Font->Font Viewer->Current font (repertoire) 01080 menuItem = new JMenuItem("Current font (repertoire)"); 01081 menuItem.setMnemonic('c'); 01082 menuItem.addActionListener(new ActionListener() { 01083 public void actionPerformed(ActionEvent e) { 01084 new FontViewer().showFont 01085 (inputField.getFont().getFamily()); 01086 }}); 01087 subMenu.add(menuItem); 01088 01089 // Font->Size 01090 subMenu = new JMenu("Size (=)"); 01091 subMenu.setMnemonic('='); 01092 menu.add(subMenu); 01093 01094 // Font->Size->Larger 01095 menuItem = new JMenuItem("Larger"); 01096 menuItem.setMnemonic(KeyEvent.VK_L); 01097 menuItem.addActionListener(new ActionListener() { 01098 public void actionPerformed(ActionEvent e) { 01099 setFontSize(getFontSize()+FONT_SIZE_STEPPING); 01100 }}); 01101 subMenu.add(menuItem); 01102 01103 // Font->Size->Smaller 01104 menuItem = new JMenuItem("Smaller"); 01105 menuItem.setMnemonic(KeyEvent.VK_S); 01106 menuItem.addActionListener(new ActionListener() { 01107 public void actionPerformed(ActionEvent e) { 01108 int size = getFontSize()-FONT_SIZE_STEPPING; 01109 if (size<=0) size = 1; 01110 setFontSize(size); 01111 }}); 01112 subMenu.add(menuItem); 01113 01114 subMenu.add(new JSeparator()); 01115 01116 // Font->Size->n 01117 ButtonGroup buttonGroup = new ButtonGroup(); 01118 fontSizeMenuItems = new JMenuItem[MAX_FONT_SIZE+1]; 01119 for (int i=MIN_FONT_SIZE; i<=MAX_FONT_SIZE; i+=FONT_SIZE_STEPPING) { 01120 menuItem = new JRadioButtonMenuItem(""+i); 01121 subMenu.add(menuItem); 01122 buttonGroup.add(menuItem); 01123 menuItem.addActionListener((new ActionListener() { 01124 int size = 0; 01125 ActionListener setSize(int s) { size = s; return this; }; 01126 public void actionPerformed(ActionEvent e) { 01127 setFontSize(size); 01128 }}).setSize(i)); 01129 fontSizeMenuItems[i] = menuItem; 01130 } 01131 buttonGroup.add(noSizeItem); 01132 01133 menu.add(new JSeparator()); 01134 01135 char h[] = new char[1]; 01136 JMenu fontMenus[] = new JMenu[27]; 01137 buttonGroup = new ButtonGroup(); 01138 fonts = getAvailableFontFamilyNames(); 01139 fontMenuItems = new JMenuItem[fonts.length]; 01140 for (int i=0; i<fonts.length; i++) { 01141 if (fonts[i].length()==0) continue; 01142 menuItem = new JRadioButtonMenuItem(fonts[i]); 01143 buttonGroup.add(menuItem); 01144 menuItem.setActionCommand(fonts[i]); 01145 menuItem.addActionListener(new ActionListener() { 01146 public void actionPerformed(ActionEvent e) { 01147 try { 01148 setInputFont(e.getActionCommand()); 01149 showMessage("Font changed to "+ 01150 e.getActionCommand()); 01151 } catch (IllegalArgumentException e1) { 01152 showMessage("Font not changed: "+e1.getMessage()); 01153 } 01154 }}); 01155 h[0] = fonts[i].charAt(0); 01156 int num; 01157 String name; 01158 if (h[0] >= 'A' && h[0] <= 'Z') { 01159 num = h[0]-'A'; 01160 name = new String(h)+"..."; 01161 } else if (h[0] >= 'a' && h[0] <= 'z') { 01162 num = h[0]-'a'; 01163 h[0] += 'A'-'a'; 01164 name = new String(h)+"..."; 01165 } else { 01166 num = 26; 01167 name = "others (*)"; 01168 } 01169 if (fontMenus[num]==null) 01170 fontMenus[num] = new JMenu(name); 01171 fontMenus[num].add(menuItem); 01172 fontMenuItems[i] = menuItem; 01173 } 01174 for (int i=0; i<27; i++) { 01175 if (fontMenus[i]==null) continue; 01176 fontMenus[i].setMnemonic((i<26)?('A'+i):'*'); 01177 01178 mnemonifyMenu(fontMenus[i],true); 01179 menu.add(fontMenus[i]); 01180 }; 01181 buttonGroup.add(noFontItem); 01182 01183 menuBar.add(Box.createHorizontalGlue()); 01184 menu = new JMenu("Help"); 01185 menu.setMnemonic(KeyEvent.VK_H); 01186 menuBar.add(menu); 01187 01188 // Help->General 01189 menuItem = new JMenuItem("General"); 01190 menuItem.setMnemonic(KeyEvent.VK_G); 01191 menuItem.addActionListener(new ActionListener() { 01192 public void actionPerformed(ActionEvent e) { 01193 showHelp(); 01194 }}); 01195 menu.add(menuItem); 01196 01197 // Help->Current object 01198 menuItem = new JMenuItem("Current object"); 01199 menuItem.setMnemonic('c'); 01200 menuItem.addActionListener(new ActionListener() { 01201 public void actionPerformed(ActionEvent e) { 01202 showCurrentDocumentation(); 01203 }}); 01204 menu.add(menuItem); 01205 01206 try { 01207 context.addMenuBar(menuBar); 01208 } catch (UnsupportedOperationException e) { 01209 System.out.println("Cannot add menu bar: "+e.getMessage()); } 01210 } 01211 01212 String[] getAvailableFontFamilyNames() { 01213 Font fonts[] = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts(); 01214 TreeSet set = new TreeSet(); 01215 for (int i=0; i<fonts.length; i++) { 01216 String fam = fonts[i].getFamily(); 01217 if (fam.endsWith(".bold")) continue; 01218 if (fam.endsWith(".bolditalic")) continue; 01219 if (fam.endsWith(".italic")) continue; 01220 set.add(fonts[i].getFamily()); 01221 } 01222 String fn[] = new String[set.size()]; 01223 Iterator it=set.iterator(); 01224 for (int i=0; it.hasNext(); i++) { 01225 fn[i] = (String)it.next(); 01226 //System.out.println(fn[i]); 01227 } 01228 return fn; 01229 } 01230 01231 void initFileChooser() { 01232 if (fileChooser==null) { 01233 fileChooser = new FileChooser(this); 01234 fileChooser.setCurrentDirectory(new File(".")); 01235 } 01236 } 01237 01238 void selectSizeItem(int size) { 01239 AbstractButton item = null; 01240 if (size<fontSizeMenuItems.length) 01241 item = fontSizeMenuItems[size]; 01242 if (item==null) item = noSizeItem; 01243 item.setSelected(true); 01244 } 01245 01246 void selectFontItem(String name) { 01247 for (int i=0; i<fonts.length; i++) { 01248 if (fonts[i]==null || fontMenuItems[i]==null || 01249 !fonts[i].equals(name)) continue; 01250 fontMenuItems[i].setSelected(true); 01251 return; 01252 } 01253 noFontItem.setSelected(true); 01254 } 01255 01256 void showHelp() { 01257 try { 01258 context.showDocument 01259 (new URL(context.getDocumentBase(),"documentation.html"),false); 01260 } catch (Exception e1) { 01261 showMessage("Could not display help: "+e1); 01262 e1.printStackTrace(); 01263 } 01264 } 01265 01270 public void loadConfig(String config) { 01271 try { 01272 inputManager.loadConfig(new URL(context.getDocumentBase(),config)); 01273 } catch (Exception e) { 01274 showMessage("Loading of "+config+" failed:\n"+e); 01275 e.printStackTrace(); 01276 } 01277 } 01278 01283 public void loadConfig(File config) { 01284 try { 01285 inputManager.loadConfig(config.toURL()); 01286 } catch (Exception e) { 01287 showMessage("Loading of "+config+" failed:\n"+e); 01288 e.printStackTrace(); 01289 } 01290 } 01291 01296 public void loadConfigString(String config) throws IOException { 01297 System.out.println("InternationalInput::loadConfigString("+config+")"); 01298 try { 01299 inputManager.loadConfigString(config); 01300 } catch (Exception e) { 01301 showMessage("Executing config string failed:\n"+e); 01302 } 01303 } 01304 01308 public String getSelected() { 01309 breakComposition(); 01310 String text = inputField.getSelectedText(); 01311 if (text==null) text = inputField.getText(); 01312 try { 01313 if (text!=null) 01314 text = Normalizer.normalize(Normalizer.C,text); 01315 } catch (IOException e) { 01316 showMessage("Normalization not possible: "+e); 01317 e.printStackTrace(); 01318 } 01319 return text; 01320 } 01321 01322 public boolean hasSelection() { 01323 return (inputField.getSelectionStart()!=inputField.getSelectionEnd()); 01324 } 01325 01326 /* * Returns, whether content has changed since last call to mirror(). 01327 * @see #mirror() 01328 * @see InternationalInputApp#hasChangedSinceMirror() 01329 public boolean hasChangedSinceMirror() { 01330 return true; 01331 } */ 01332 01333 /* * Returns content of the input field. 01334 * The composition is not interrupted. 01335 * @see InternationalInputApp#mirror() 01336 public String mirror() { 01337 return inputField.getText(); 01338 } */ 01342 public void noButtons() { 01343 disableButtons = true; 01344 if (buttons==null) return; 01345 remove(buttons); 01346 buttons = null; 01347 revalidate(); 01348 } 01353 public String getDocumentation(String group) { 01354 try { 01355 return inputManager.getGroup(group).getDocumentation(); 01356 } catch (IOException e) { 01357 e.printStackTrace(); 01358 return "Could not load documentation for "+group; 01359 } 01360 } 01361 01364 public String getCurrentDocumentation() { 01365 try { 01366 return currentDocumentation.getDocumentation(); 01367 } catch (Exception e) { 01368 e.printStackTrace(); 01369 showMessage("Could not load documentation for "+ 01370 currentDocumentation.getFullDocuName()+": "+e); 01371 return "Could not load documentation for "+ 01372 currentDocumentation.getFullDocuName()+": "+e; 01373 } 01374 } 01375 01376 public void showCurrentDocumentation() { 01377 try { 01378 context.showDocumentFromString 01379 (currentDocumentation.getDocumentation()); 01380 } catch (Exception e) { 01381 e.printStackTrace(); 01382 showMessage("Could not show documentation for "+ 01383 currentDocumentation.getFullDocuName()+": "+e); 01384 } 01385 } 01386 01387 /* 01391 /* public String getScreenName(String group) { 01392 return inputManager.getInputMethodScreenName(group); 01393 } */ 01394 /* 01397 /*public String lastActivatedGroup() { 01398 return inputManager.getLastActivatedGroupName(); 01399 }*/ 01400 01403 public void ready() { 01404 inputField.requestFocus(); 01405 setFontSize(DEFAULT_FONT_SIZE); 01406 } 01407 01408 01409 public void mouseExited(MouseEvent e) { checkCaret(); }; 01410 public void mouseEntered(MouseEvent e) { checkCaret(); }; 01411 public void mouseClicked(MouseEvent e) { checkCaret(); }; 01412 public void mousePressed(MouseEvent e) { checkCaret(); }; 01413 public void mouseReleased(MouseEvent e) { checkCaret(); }; 01414 01415 //public void focusGained(FocusEvent e) { /* Todo.doActions(); */ }; 01416 //public void focusLost(FocusEvent e) { /* Todo.doActions(); */ }; 01417 01418 public void textWindow(String text) { 01419 try { 01420 URL url; 01421 try { 01422 url = new URL(context.getDocumentBase(), 01423 "reflect/"+InputManager.urlEncode(text)); 01424 } catch (MalformedURLException e) { 01425 e.printStackTrace(); 01426 throw new RuntimeException(e.getMessage()); 01427 } 01428 System.out.println("Text: "+text); 01429 System.out.println("URL: "+url); 01430 context.showDocument(url,false); 01431 } catch (UnsupportedOperationException e) { 01432 showMessage("Copying impossible: "+e.getMessage()); 01433 } 01434 } 01435 private void initClipboard() { 01436 if (noSystemClipboard) return; 01437 01438 try { 01439 clipboard = getToolkit().getSystemClipboard(); 01440 } catch (SecurityException e) { 01441 noSystemClipboard = true; 01442 clipboard = new Clipboard("local"); 01443 } 01444 } 01445 public String copyText(boolean dontUseTextWindow) { 01446 initClipboard(); 01447 String text = getSelected(); 01448 clipboard.setContents(new StringSelection(text),null); 01449 if (noSystemClipboard && !dontUseTextWindow) textWindow(text); 01450 return text; 01451 } 01456 public void setClipboardContent(String data) { 01457 initClipboard(); 01458 clipboard.setContents(new StringSelection(data),null); 01459 } 01460 01461 public void pasteText(boolean temporary) { 01462 initClipboard(); 01463 String text; 01464 Transferable data = clipboard.getContents(clipboard); 01465 if (data==null) { 01466 showMessage(noSystemClipboard? 01467 "Local clipboard is empty (system clipboard not accessible)": 01468 "Clipboard is empty"); 01469 return; } 01470 01471 try { 01472 text = (String)data.getTransferData 01473 (DataFlavor.stringFlavor); 01474 } catch (UnsupportedFlavorException ee) { 01475 showMessage("Clipboard not readable: "+ee); 01476 return; 01477 } catch (IOException ee) { 01478 showMessage("Clipboard not readable: "+ee); 01479 return; 01480 } 01481 01482 if (temporary) { 01483 inputManager.input(InputManager.SOURCE_CLIPBOARD, 01484 text); 01485 } else { 01486 breakComposition(); 01487 inputField.addFinal(text); 01488 } 01489 } 01490 01491 public void keyTyped(KeyEvent e) {}; 01492 public void keyPressed(KeyEvent e) {}; 01493 public void keyReleased(KeyEvent e) { 01494 if (checkFKeyHotKey(e.getKeyCode())) 01495 e.consume(); 01496 if (e.getKeyCode()==KeyEvent.VK_F1) { 01497 showHelp(); e.consume(); } 01498 }; 01499 public void breakComposition() { 01500 inputManager.input(InputManager.SOURCE_KEYBOARD, 01501 InputManager.INPUT_BREAK); 01502 } 01503 void callWebPage(InputManager.WebPage webpage) { 01504 try { 01505 currentDocumentation = webpage; 01506 URL result = webpage.run(getSelected()); 01507 System.out.println("Webpage: "+result); 01508 context.showDocument(result,webpage.getNeedsTopFrame()); 01509 } catch (Exception ex) { 01510 showMessage("Could not create URL: "+ex); 01511 ex.printStackTrace(); 01512 } 01513 } 01514 01524 public String autoSetFont(String str, boolean lazy) { 01525 Font current = getFont(); 01526 if (str==null) str = ""; 01527 int upto = current.canDisplayUpTo(str.replace('\n',' ')); 01528 boolean canDisplayStr = (upto == -1 || upto == str.length()); 01529 //System.out.println(upto+" "+str.length()); 01530 if (canDisplayStr && lazy) return null; 01531 String content = inputField.getText(); 01532 upto = current.canDisplayUpTo(content.replace('\n',' ')); 01533 boolean canDisplayContent = (upto == -1 || upto == content.length()); 01534 if (canDisplayStr && canDisplayContent) return null; 01535 01536 System.out.println("autoSetFont("+str+","+lazy+") searches..."); 01537 String[] fontNames = GraphicsEnvironment.getLocalGraphicsEnvironment(). 01538 getAvailableFontFamilyNames(); 01539 //int fontSize = current.getSize(); 01540 Font[] fonts = new Font[fontNames.length]; 01541 FontRenderContext frc = 01542 ((Graphics2D)getGraphics()).getFontRenderContext(); 01543 for (int i=0; i<fontNames.length; i++) { 01544 if (fontNames[i]==null || fontNames[i].length()==0) continue; 01545 fonts[i] = new Font(fontNames[i],Font.PLAIN,fontSize); 01546 Rectangle2D rect = fonts[i].getStringBounds(content,frc); 01547 //System.out.println(fontNames[i]+": "+rect); 01548 if (rect.getWidth() < 1 || rect.getHeight() < 1) fonts[i] = null; 01549 } 01550 int best0 = -1, best1 = -1, best2 = 0; 01551 String best = current.getFamily(); 01552 //System.out.println("curr: "+best); 01553 for (int fontnum=0; fontnum<fonts.length; fontnum++) { 01554 Font font = fonts[fontnum]; 01555 if (font==null) continue; 01556 int q0 = 0, q1 = 0, q2 = 0; 01557 if (font.getFamily().equals(current.getFamily())) q2 = 1; 01558 for (int i=0; i<str.length(); i++) { 01559 char c = str.charAt(i); 01560 if (c!=' ' && c!='\t' && c!='\n') 01561 if (font.canDisplay(c)) q0++; }; 01562 for (int i=0; i<content.length(); i++) { 01563 char c = content.charAt(i); 01564 if (c!=' ' && c!='\t' && c!='\n') 01565 if (font.canDisplay(c)) q1++; }; 01566 if (q0>best0 || 01567 (q0==best0 && (q1>best1 || 01568 (q1==best1 && q2>best2)))) { 01569 best = font.getFamily(); 01570 best0 = q0; best1 = q1; best2 = q2; 01571 } 01572 } 01573 // System.out.println("BEST: "+best); 01574 if (best.equals(current.getFamily())) return null; 01575 setInputFont(best); 01576 return best; 01577 } 01578 01579 public void setAutoSetFont(boolean on) { 01580 autoSetFont = on; 01581 if (autoSetFont) autoSetFont(inputField.temporaryInput,true); 01582 } 01586 public void setFontSize(int size) { 01587 fontSize = size; 01588 inputField.setFont(inputField.getFont().deriveFont(Font.PLAIN,size)); 01589 selectSizeItem(size); 01590 }; 01591 01594 public int getFontSize() { 01595 return fontSize; }; 01596 01600 public void setInputFont(String fontName) { 01601 Font oldFont = inputField.getFont(); 01602 Font newFont = new Font(fontName,Font.PLAIN,fontSize); 01603 if (!newFont.getFamily().equals(fontName)) { 01604 selectFontItem(oldFont.getFamily()); 01605 throw new IllegalArgumentException 01606 ("No such font: "+fontName); } 01607 System.out.println("New font: "+newFont); 01608 inputField.setFont(newFont); 01609 selectFontItem(fontName); 01610 } 01611 01612 public void clearText() { 01613 inputManager.input(InputManager.SOURCE_GUI, 01614 InputManager.INPUT_BREAK); 01615 try { 01616 inputField.document.remove 01617 (0,inputField.document.getLength()); 01618 } catch (BadLocationException e) { 01619 inputField.setText(""); 01620 } 01621 }; 01622 01623 private static final Hashtable iconify_iconHash = new Hashtable(); 01624 Icon iconify_getIcon(int cp) { 01625 //System.out.println("iconify_getStyle("+Integer.toHexString(cp).toUpperCase()+")"); 01626 Icon icon = 01627 (Icon)iconify_iconHash.get(new Integer(cp)); 01628 if (icon!=null) return icon; 01629 String name; 01630 switch (cp) { 01631 case 0x1B: name = "ESC"; break; 01632 case 0x200E: name = "LRM"; break; 01633 case 0x200F: name = "RLM"; break; 01634 case 0x200B: name = "ZWSP"; break; 01635 case 0x200C: name = "ZWNJ"; break; 01636 case 0x200D: name = "ZWJ"; break; 01637 case 0x2028: name = "LSEP"; break; 01638 case 0x2029: name = "PSEP"; break; 01639 case 0x202A: name = "LRE"; break; 01640 case 0x202B: name = "RLE"; break; 01641 case 0x202C: name = "PDF"; break; 01642 case 0x202D: name = "LRO"; break; 01643 case 0x202E: name = "RLO"; break; 01644 case 0xFFFD: name = "?"; break; 01645 01646 default: 01647 name = "U+"+Integer.toHexString(cp).toUpperCase(); 01648 } 01649 01650 icon = new TextIcon(name,this,new Color(165,42,42)); 01651 iconify_iconHash.put(new Integer(cp),icon); 01652 return icon; 01653 } 01654 01655 01656 /* 01657 private static final Hashtable iconify_styleHash = new Hashtable(); 01658 SimpleAttributeSet iconify_getStyle(int cp) { 01659 //System.out.println("iconify_getStyle("+Integer.toHexString(cp).toUpperCase()+")"); 01660 SimpleAttributeSet style = 01661 (SimpleAttributeSet)iconify_styleHash.get(new Integer(cp)); 01662 if (style!=null) return style; 01663 String name; 01664 switch (cp) { 01665 case 0x200E: name = "LRM"; break; 01666 case 0x200F: name = "RLM"; break; 01667 case 0x200B: name = "ZWSP"; break; 01668 case 0x200C: name = "ZWNJ"; break; 01669 case 0x200D: name = "ZWJ"; break; 01670 case 0x2028: name = "LSEP"; break; 01671 case 0x2029: name = "PSEP"; break; 01672 case 0x202A: name = "LRE"; break; 01673 case 0x202B: name = "RLE"; break; 01674 case 0x202C: name = "PDF"; break; 01675 case 0x202D: name = "LRO"; break; 01676 case 0x202E: name = "RLO"; break; 01677 case 0xFFFD: name = "?"; break; 01678 01679 default: 01680 name = "U+"+Integer.toHexString(cp).toUpperCase(); 01681 } 01682 style = new SimpleAttributeSet(); 01683 StyleConstants.setIcon 01684 (style, 01685 new TextIcon(name,this,new Color(165,42,42)) 01686 ); 01687 iconify_styleHash.put(new Integer(cp),style); 01688 return style; 01689 } 01690 */ 01691 01692 public void keyStroke(ActionEvent e) { 01693 checkCaret(); 01694 String stroke = e.getActionCommand(); 01695 char c = '\000'; 01696 if (stroke.length()==1) c = stroke.charAt(0); 01697 switch (c+'A'-1) { 01698 // Passing: ^J = ENTER 01699 case 'A': case 'B': case 'C': case 'D': case 'E': 01700 case 'F': case 'H': case 'I': case 'K': 01701 case 'L': case 'M': case 'N': case 'O': case 'P': 01702 case 'Q': case 'R': case 'S': case 'T': case 'U': 01703 case 'V': case 'W': case 'X': case 'Z': 01704 System.out.println("^"+(char)(c+'A'-1)+" pressed, ignoring."); 01705 return; 01706 case 'G': 01707 stroke = InputManager.INPUT_BREAK; 01708 break; 01709 default: 01710 switch (c) { 01711 case '\377': // DEL 01712 System.out.println("DEL pressed, ignoring."); 01713 return; 01714 } 01715 } 01716 inputManager.input(InputManager.SOURCE_KEYBOARD,stroke); 01717 } 01718 public void backSpace() { 01719 inputManager.input(InputManager.SOURCE_KEYBOARD, 01720 InputManager.INPUT_BACKSPACE); 01721 } 01722 01723 void normalize() { 01724 try { 01725 normalize(0,inputField.getText().length()); 01726 } catch (BadLocationException e) { 01727 e.printStackTrace(); 01728 throw new RuntimeException("Internal error: "+e); 01729 }} 01730 01731 int normalize(int from, int upto) throws BadLocationException { 01732 try { 01733 String preCaret = inputField.getText(0,upto); 01734 //System.out.println("String: "+preCaret); 01735 StringBuffer target = new StringBuffer(); 01736 from = Normalizer.normalize(Normalizer.C,preCaret,from,upto,target); 01737 //System.out.println("Normal: "+normal); 01738 if (target.length()!=0) 01739 inputField.replaceRange(target.toString(),from,upto); 01740 } catch (IOException e) { 01741 System.out.println("Normalization not possible: "+e); 01742 } 01743 return from; 01744 } 01745 01746 01747 void iconify() { 01748 try { 01749 iconify(0,inputField.document.getLength()); 01750 } catch (BadLocationException e) { 01751 e.printStackTrace(); 01752 throw new RuntimeException("Internal error: "+e); 01753 } 01754 }; 01755 01756 int iconify_tempColor = 0; 01757 void iconify(int from, int upto) throws BadLocationException { 01758 //System.out.println("iconify("+from+","+upto+")"); 01759 int len = upto-from; 01760 String str = inputField.document.getText(from,len); 01761 SimpleAttributeSet noStyle = new SimpleAttributeSet(); 01762 StringBuffer normalText = new StringBuffer(); 01763 int doneUpto = 0; 01764 try { 01765 inputField.document.remove(from,len); 01766 } catch (BadLocationException e) { 01767 e.printStackTrace(); return; } 01768 for (int i=0; i<len; i++) { 01769 char c = str.charAt(i); 01770 boolean isControl = false; 01771 //System.out.println("Type of "+Integer.toHexString(c).toUpperCase() 01772 // +" is "+Character.getType(c)); 01773 switch (Character.getType(c)) { 01774 case Character.CONTROL: 01775 case Character.FORMAT: 01776 case Character.LINE_SEPARATOR: 01777 case Character.SPACE_SEPARATOR: 01778 case Character.PARAGRAPH_SEPARATOR: 01779 //case Character.SURROGATE: 01780 isControl = true; 01781 } 01782 switch (c) { 01783 case '\n': case ' ': 01784 isControl = false; break; 01785 case 0xFFFD: 01786 isControl = true; break; 01787 } 01788 if (isControl) { 01789 try { 01790 inputField.document.insertString(from+doneUpto,normalText.toString(),noStyle); 01791 normalText.setLength(0); doneUpto = i+1; 01792 //inputField.document.insertString(from+i,""+c,iconify_getStyle(c)); 01793 SimpleAttributeSet style = new SimpleAttributeSet(); 01794 StyleConstants.setIcon(style,iconify_getIcon(c)); 01795 // Hack: Otherwise styles will be identical 01796 // and thus give adjoining identical icons will collapse: 01797 StyleConstants.setForeground 01798 (style,new Color(iconify_tempColor++)); 01799 inputField.document.insertString(from+i,""+c,style); 01800 } catch (BadLocationException e) { 01801 e.printStackTrace(); } 01802 } else { 01803 normalText.append(c); 01804 } 01805 } 01806 try { 01807 inputField.document.insertString(from+doneUpto,normalText.toString(),noStyle); 01808 } catch (BadLocationException e) { 01809 e.printStackTrace(); } 01810 } 01811 01812 01813 void checkCaret() { 01814 if (noCaretCheck) return; 01815 noCaretCheck = true; 01816 int newCaret = inputField.getCaretPosition(); 01817 if (newCaret != lastCaret) 01818 inputManager.input(InputManager.SOURCE_KEYBOARD, 01819 InputManager.INPUT_BREAK); 01820 if (newCaret>inputField.getText().length()) 01821 newCaret = inputField.getText().length(); 01822 if (newCaret!=inputField.getCaretPosition()) 01823 inputField.setCaretPosition(newCaret); 01824 lastCaret = newCaret; 01825 noCaretCheck = false; 01826 } 01827 01828 void saveFile(File file, String encoding, boolean selection) { 01829 Writer writer = null; 01830 currentFile = file; 01831 try { 01832 inputManager.input(InputManager.SOURCE_GUI, 01833 InputManager.INPUT_BREAK); 01834 writer = 01835 new OutputStreamWriter(new FileOutputStream(file),encoding); 01836 String text = selection?getSelected():inputField.getText(); 01837 writer.write(text); 01838 writer.close(); 01839 showMessage("File "+file+" written."); 01840 try { context.setTitleInfo(file.getName()); } 01841 catch (UnsupportedOperationException e) {}; 01842 } catch (IOException e) { 01843 e.printStackTrace(); 01844 showMessage("Could not write to "+file+": "+e); 01845 try { if (writer!=null) writer.close(); } 01846 catch (IOException e1) {}; 01847 } 01848 } 01849 01850 void openFile(File file, String encoding, boolean insert, boolean temporary) { 01851 Reader reader = null; 01852 currentFile = file; 01853 try { 01854 reader = 01855 new InputStreamReader(new FileInputStream(file),encoding); 01856 if (!temporary) inputManager.input(InputManager.SOURCE_GUI, 01857 InputManager.INPUT_BREAK); 01858 if (!insert) clearText(); 01859 char buff[] = new char[4096]; 01860 while (true) { 01861 int numread = reader.read(buff); 01862 01863 if (numread==-1) break; 01864 01865 String sbuff = new String(buff,0,numread); 01866 if (temporary) { 01867 inputManager.input(InputManager.SOURCE_FILE,sbuff); 01868 } else { 01869 breakComposition(); 01870 inputField.addFinal(sbuff); 01871 } 01872 } 01873 reader.close(); 01874 showMessage("File "+file+" loaded."); 01875 try { context.setTitleInfo(file.getName()); } 01876 catch (UnsupportedOperationException e) {}; 01877 } catch (IOException e) { 01878 e.printStackTrace(); 01879 showMessage("Could not read from "+file+": "+e); 01880 try { if (reader!=null) reader.close(); } 01881 catch (IOException e1) {}; 01882 } 01883 } 01884 }

Generated on Sun Aug 15 11:56:53 2004 for International Input by doxygen 1.3.7