1 31 32 package org.antlr.xjlib.appkit.frame; 33 34 import org.antlr.xjlib.appkit.XJControl; 35 import org.antlr.xjlib.appkit.app.XJApplication; 36 import org.antlr.xjlib.appkit.app.XJPreferences; 37 import org.antlr.xjlib.appkit.menu.*; 38 import org.antlr.xjlib.appkit.undo.XJUndo; 39 import org.antlr.xjlib.appkit.undo.XJUndoDelegate; 40 import org.antlr.xjlib.appkit.undo.XJUndoEngine; 41 import org.antlr.xjlib.appkit.utils.XJLocalizable; 42 import org.antlr.xjlib.foundation.XJSystem; 43 44 import javax.swing.*; 45 import javax.swing.event.InternalFrameAdapter ; 46 import javax.swing.event.InternalFrameEvent ; 47 import javax.swing.text.DefaultEditorKit ; 48 import java.awt.*; 49 import java.awt.event.WindowAdapter ; 50 import java.awt.event.WindowEvent ; 51 import java.beans.PropertyVetoException ; 52 import java.util.ArrayList ; 53 import java.util.HashMap ; 54 import java.util.List ; 55 import java.util.Map ; 56 57 public class XJFrame extends XJControl implements XJFrameInterface, XJMenuBarCustomizer, XJMenuBarDelegate { 58 59 private static final String PROPERTY_WINDOW_MODIFIED = "windowModified"; 60 private static final String PREF_DESKTOP_BOUNDS = "xjdesktop_bounds"; 61 62 private static final boolean useDesktop = XJApplication.shared().useDesktopMode(); 63 64 private static JFrame desktopFrame; 65 private static JDesktopPane desktop; 66 private static XJMainMenuBar desktopDefaultMenuBar; 67 68 private JInternalFrame jInternalFrame; 69 private JFrame jFrame; 70 71 protected XJMainMenuBar mainMenuBar; 72 protected XJFrameDelegate delegate; 73 protected XJUndoEngine undoEngine; 74 protected boolean alreadyBecomeVisible = false; 75 protected boolean dirty = false; 76 77 private class InternalFrameHandling implements XJMenuBarDelegate { 78 79 public InternalFrameHandling() { 80 desktopDefaultMenuBar = XJMainMenuBar.createInstance(); 81 desktopDefaultMenuBar.createMenuBar(); 82 desktopDefaultMenuBar.setDelegate(this); 83 desktopDefaultMenuBar.refreshState(); 84 } 85 86 public void menuItemState(XJMenuItem item) { 87 int tag = item.getTag(); 88 switch(tag) { 89 case XJMainMenuBar.MI_NEW: 90 item.setTitle(XJLocalizable.getXJString("New")+((XJApplication.shared().getDocumentExtensions().size()>1)?"...":"")); 91 92 case XJMainMenuBar.MI_OPEN: 93 case XJMainMenuBar.MI_RECENT_FILES: 94 case XJMainMenuBar.MI_CLEAR_RECENT_FILES: 95 item.setEnabled(true); 96 break; 97 98 default: 99 if(XJMainMenuBar.isRecentFilesItem(item)) 100 item.setEnabled(true); 101 else 102 item.setEnabled(false); 103 break; 104 } 105 } 106 107 public void handleMenuEvent(XJMenu menu, XJMenuItem item) { 108 109 } 110 111 public void handleMenuSelected(XJMenu menu) { 112 113 } 114 } 115 116 private static class FrameManager { 117 118 private static List <XJFrame> frames = new ArrayList <XJFrame>(); 119 private static XJFrame activated = null; 120 121 public static void removeFrame(XJFrame f) { 122 frames.remove(f); 123 } 124 125 public static void frameActivated(XJFrame f) { 126 frames.remove(f); 127 frames.add(f); 128 activated = f; 129 } 130 131 public static void frameDeactivated(final XJFrame f) { 132 if(activated == f) { 133 activated = null; 134 } 135 136 int index = frames.indexOf(f); 137 if(index == -1) return; 138 139 SwingUtilities.invokeLater(new Runnable () { 140 public void run() { 141 selectNextFrame(f); 142 } 143 }); 144 } 145 146 public static XJFrame getNextFrame(XJFrame f) { 147 for(int i=frames.size()-1; i>=0; i--) { 148 if(frames.get(i).equals(f)) continue; 149 return frames.get(i); 150 } 151 return null; 152 } 153 154 public static void selectNextFrame(XJFrame f) { 155 if(XJSystem.isMacOS()) return; 158 159 if(activated == f) return; 160 161 XJFrame nf = getNextFrame(f); 162 if(nf != null) { 163 nf.bringToFront(); 164 } else if(frames.isEmpty() || frames.size() == 1 && frames.get(0).equals(f) && desktopFrame != null) { 165 desktopFrame.setJMenuBar(desktopDefaultMenuBar.getJMenuBar()); 166 desktopFrame.toFront(); 167 } 168 } 169 } 170 171 private static void restoreDesktopBounds() { 172 Rectangle r = (Rectangle) XJApplication.shared().getPreferences().getObject(PREF_DESKTOP_BOUNDS, null); 173 if(r != null) { 174 desktopFrame.setLocation(r.x, r.y); 175 desktopFrame.setSize(r.width, r.height); 176 } 177 } 178 179 private static void saveDesktopBounds() { 180 Point pos = desktopFrame.getLocation(); 181 Dimension s = desktopFrame.getSize(); 182 Rectangle r = new Rectangle(pos.x, pos.y, s.width, s.height); 183 XJPreferences prefs = XJApplication.shared().getPreferences(); 184 prefs.setObject(PREF_DESKTOP_BOUNDS, r); 185 } 186 187 public static void closeDesktop() { 188 if(useDesktop) { 189 saveDesktopBounds(); 190 } 191 } 192 193 public XJFrame() { 194 if(useDesktop) { 195 if(desktopFrame == null) { 196 desktopFrame = new JFrame(); 197 desktopFrame.setTitle(XJApplication.shared().getApplicationName()); 198 desktopFrame.addWindowListener(new WindowAdapter () { 199 200 @Override 201 public void windowActivated(WindowEvent e) { 202 XJFrame.this.windowActivated(); 203 FrameManager.frameActivated(XJFrame.this); 204 } 205 206 @Override 207 public void windowClosing(WindowEvent e) { 208 XJApplication.shared().performQuit(); 209 } 210 211 }); 212 213 Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); 214 dim = new Dimension((int)(dim.width*0.9), (int)(dim.height*0.9)); 215 desktopFrame.setSize(dim); 216 desktopFrame.setPreferredSize(dim); 217 desktopFrame.setLocationRelativeTo(null); 218 restoreDesktopBounds(); 219 220 desktop = new JDesktopPane(); 221 desktopFrame.getContentPane().add(desktop, BorderLayout.CENTER); 222 desktopFrame.setVisible(true); 223 224 new InternalFrameHandling(); 225 } 226 227 jInternalFrame = new JInternalFrame(); 228 jInternalFrame.setResizable(true); 229 jInternalFrame.setClosable(true); 230 jInternalFrame.setMaximizable(true); 231 jInternalFrame.setIconifiable(true); 232 233 desktop.add(jInternalFrame); 234 235 jInternalFrame.addInternalFrameListener(new InternalFrameAdapter () { 236 public void internalFrameActivated(InternalFrameEvent e) { 237 XJMainMenuBar mb = getMainMenuBar(); 238 if(mb != null) { 239 desktopFrame.setJMenuBar(mb.getJMenuBar()); 240 } 241 XJFrame.this.windowActivated(); 242 FrameManager.frameActivated(XJFrame.this); 243 } 244 245 public void internalFrameDeactivated(InternalFrameEvent e) { 246 if(jInternalFrame != null) 250 XJFrame.this.windowDeactivated(); 251 252 FrameManager.frameDeactivated(XJFrame.this); 253 } 254 255 public void internalFrameClosing(InternalFrameEvent e) { 256 if(desktopFrame != null && jInternalFrame.isSelected()) { 257 desktopFrame.setJMenuBar(desktopDefaultMenuBar.getJMenuBar()); 258 } 259 windowIsClosing(); 260 } 261 262 }); 263 } else { 264 jFrame = new JFrame(); 265 jFrame.addWindowListener(new WindowAdapter () { 266 public void windowActivated(WindowEvent e) { 267 XJFrame.this.windowActivated(); 268 FrameManager.frameActivated(XJFrame.this); 269 } 270 271 public void windowDeactivated(WindowEvent e) { 272 if(jFrame != null) 276 XJFrame.this.windowDeactivated(); 277 FrameManager.frameDeactivated(XJFrame.this); 278 } 279 280 public void windowClosing(WindowEvent e) { 281 windowIsClosing(); 282 } 283 284 }); 285 } 286 setDefaultSize(); 287 undoEngine = new XJUndoEngine(); 288 } 289 290 public void awake() { 291 if(shouldDisplayMainMenuBar()) { 292 mainMenuBar = XJMainMenuBar.createInstance(); 293 mainMenuBar.setCustomizer(this); 294 mainMenuBar.setDelegate(this); 295 mainMenuBar.createMenuBar(); 296 setMainMenuBar(mainMenuBar); 297 undoEngine.setMainMenuBar(mainMenuBar); 298 } 299 } 300 301 public void setDelegate(XJFrameDelegate delegate) { 302 this.delegate = delegate; 303 } 304 305 public XJFrameDelegate getDelegate() { 306 return delegate; 307 } 308 309 public void setDefaultCloseOperation(int operation) { 310 if(useDesktop) { 311 jInternalFrame.setDefaultCloseOperation(operation); 312 } else { 313 jFrame.setDefaultCloseOperation(operation); 314 } 315 } 316 317 public Container getContentPane() { 318 if(useDesktop) { 319 return jInternalFrame.getContentPane(); 320 } else { 321 return jFrame.getContentPane(); 322 } 323 } 324 325 public JRootPane getRootPane() { 326 if(useDesktop) { 327 return jInternalFrame.getRootPane(); 328 } else { 329 return jFrame.getRootPane(); 330 } 331 } 332 333 public JLayeredPane getLayeredPane() { 334 if(useDesktop) { 335 return jInternalFrame.getLayeredPane(); 336 } else { 337 return jFrame.getLayeredPane(); 338 } 339 } 340 341 public Component getGlassPane() { 342 if(useDesktop) { 343 return jInternalFrame.getGlassPane(); 344 } else { 345 return jFrame.getGlassPane(); 346 } 347 } 348 349 public void setMainMenuBar(XJMainMenuBar menubar) { 350 this.mainMenuBar = menubar; 351 if(useDesktop) { 352 if(jInternalFrame.isSelected()) { 353 desktopFrame.setJMenuBar(mainMenuBar.getJMenuBar()); 354 } 355 } else { 356 jFrame.setJMenuBar(mainMenuBar.getJMenuBar()); 357 } 358 } 359 360 public XJMainMenuBar getMainMenuBar() { 361 return mainMenuBar; 362 } 363 364 public void menuItemStatusChanged(int tag) { 365 if(mainMenuBar == null) 366 return; 367 368 XJMainMenuBar.refreshAllMenuBars(); 369 mainMenuBar.refreshState(); 370 } 371 372 private String title; 373 374 public void setTitle(String title) { 375 this.title = title; 376 if(useDesktop) { 377 jInternalFrame.setTitle(customizeWindowTitle(title)); 378 } else { 379 jFrame.setTitle(customizeWindowTitle(title)); 380 } 381 } 382 383 public String getTitle() { 384 return title; 385 390 } 391 392 public void updateTitle() { 393 setTitle(title); 394 } 395 396 protected String customizeWindowTitle(String title) { 397 if(dirty() && !XJSystem.isMacOS()) { 398 return title+" [modified]"; 399 } else { 400 return title; 401 } 402 } 403 404 public void setLocation(Point loc) { 405 if(useDesktop) { 406 jInternalFrame.setLocation(loc); 407 } else { 408 jFrame.setLocation(loc); 409 } 410 } 411 412 public Point getLocation() { 413 if(useDesktop) { 414 return jInternalFrame.getLocation(); 415 } else { 416 return jFrame.getLocation(); 417 } 418 } 419 420 public void setSize(int dx, int dy) { 421 if(useDesktop) { 422 jInternalFrame.setSize(dx, dy); 423 } else { 424 jFrame.setSize(dx, dy); 425 } 426 } 427 428 public void setSize(Dimension size) { 429 if(useDesktop) { 430 jInternalFrame.setSize(size); 431 } else { 432 jFrame.setSize(size); 433 } 434 } 435 436 public Dimension getSize() { 437 if(useDesktop) { 438 return jInternalFrame.getSize(); 439 } else { 440 return jFrame.getSize(); 441 } 442 } 443 444 public void setDefaultSize() { 445 if(useDesktop) { 446 Dimension dim = desktop.getSize(); 447 setSize((int) (dim.width*0.8), (int) (dim.height*0.8)); 448 } else { 449 Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); 450 setSize((int)(dim.width*0.5), (int)(dim.height*0.5)); 451 } 452 } 453 454 public void setResizable(boolean flag) { 455 if(useDesktop) { 456 jInternalFrame.setResizable(flag); 457 } else { 458 jFrame.setResizable(flag); 459 } 460 } 461 462 public void setMaximizable(boolean flag) { 463 if(useDesktop) { 464 jInternalFrame.setMaximizable(flag); 465 } else { 466 } 468 } 469 470 public boolean isMaximized() { 471 return useDesktop && jInternalFrame.isMaximum(); 472 } 473 474 public void pack() { 475 if(useDesktop) { 476 jInternalFrame.pack(); 477 } else { 478 jFrame.pack(); 479 } 480 } 481 482 public void bringToFront() { 483 if(useDesktop) { 484 if(jInternalFrame == null) return; 485 486 jInternalFrame.moveToFront(); 487 try { 488 jInternalFrame.setSelected(true); 489 } catch (PropertyVetoException e) { 490 e.printStackTrace(); 491 } 492 } else { 493 jFrame.toFront(); 494 } 495 } 496 497 public void setVisible(boolean flag) { 498 if(flag && !alreadyBecomeVisible) { 499 alreadyBecomeVisible = true; 500 restoreWindowBounds(); 501 ensureVisibility(); 502 becomingVisibleForTheFirstTime(); 503 } 504 if(useDesktop) { 505 jInternalFrame.setVisible(flag); 506 } else { 507 jFrame.setVisible(flag); 508 } 509 bringToFront(); 510 } 511 512 516 public void ensureVisibility() { 517 if(!isVisibleOnScreen()) { 518 center(); 519 } 520 } 521 522 public void becomingVisibleForTheFirstTime() { 523 524 } 525 526 public String autosaveName() { 527 return null; 528 } 529 530 public boolean isVisible() { 531 if(useDesktop) { 532 return jInternalFrame.isVisible(); 533 } else { 534 return jFrame.isVisible(); 535 } 536 } 537 538 public boolean isActive() { 539 if(useDesktop) { 540 return jInternalFrame.isSelected(); 541 } else { 542 return jFrame.isActive(); 543 } 544 } 545 546 public void show() { 547 setVisible(true); 548 } 549 550 public void showModal() { 551 setVisible(true); 552 } 553 554 public void hide() { 555 setVisible(false); 556 } 557 558 public void triggerClose() { 559 if(FrameManager.activated != null && FrameManager.activated != this) { 560 FrameManager.activated.triggerClose(); 561 } else { 562 if(useDesktop) { 563 try { 564 jInternalFrame.setClosed(true); 565 } catch (PropertyVetoException e) { 566 e.printStackTrace(); 567 } 568 } else { 569 windowIsClosing(); 570 } 571 } 572 } 573 574 private void windowIsClosing() { 575 this.windowClosing(); 576 FrameManager.removeFrame(this); 577 } 578 579 public boolean isCompletelyOnScreen() { 580 return isVisibleOnScreen(); 581 } 582 583 public boolean isVisibleOnScreen() { 584 GraphicsEnvironment ge = 585 GraphicsEnvironment.getLocalGraphicsEnvironment(); 586 GraphicsDevice[] gs = ge.getScreenDevices(); 587 588 Rectangle fr = (useDesktop?jInternalFrame.getBounds():jFrame.getBounds()); 589 for (GraphicsDevice g : gs) { 590 GraphicsConfiguration dc = g.getDefaultConfiguration(); 591 if (fr.intersects(dc.getBounds())) { 592 return true; 593 } 594 } 595 596 return false; 597 } 598 599 public void center() { 600 if(useDesktop) { 601 Dimension s = desktopFrame.getSize(); 602 Dimension id = jInternalFrame.getSize(); 603 jInternalFrame.setLocation(s.width/2 - id.width/2, s.height/2 - id.height/2); 604 } else { 605 jFrame.setLocationRelativeTo(null); 606 } 607 } 608 609 public void setPosition(int x, int y) { 610 setLocation(new Point(x, y)); 611 } 612 613 public void offsetPosition(int dx, int dy) { 614 Point p = getLocation(); 615 setPosition(p.x+dx, p.y+dy); 616 } 617 618 public void close() { 619 XJMainMenuBar.removeInstance(mainMenuBar); 620 if(mainMenuBar != null) { 621 mainMenuBar.setDelegate(null); 622 mainMenuBar = null; 623 } 624 625 saveWindowBounds(); 626 627 if(useDesktop) { 628 jInternalFrame.dispose(); 629 jInternalFrame = null; 630 } else { 631 jFrame.dispose(); 632 jFrame = null; 633 } 634 635 if(delegate != null) 636 delegate.frameDidClose(this); 637 } 638 639 public void setDirty() { 640 if(!XJApplication.shared().supportsPersistence()) 641 return; 642 643 if(!dirty) { 645 dirty = true; 646 getRootPane().putClientProperty(PROPERTY_WINDOW_MODIFIED, Boolean.TRUE); 647 menuItemStatusChanged(XJMainMenuBar.MI_SAVE); 648 updateTitle(); 649 } 650 } 651 652 public void resetDirty() { 653 if(!XJApplication.shared().supportsPersistence()) 654 return; 655 656 if(dirty) { 657 dirty = false; 658 getRootPane().putClientProperty(PROPERTY_WINDOW_MODIFIED, Boolean.FALSE); 659 menuItemStatusChanged(XJMainMenuBar.MI_SAVE); 660 updateTitle(); 661 } 662 } 663 664 public boolean dirty() { 665 if(!XJApplication.shared().supportsPersistence()) 666 return false; 667 668 Boolean b = (Boolean ) getRootPane().getClientProperty(PROPERTY_WINDOW_MODIFIED); 669 return b != null && b; 670 } 671 672 public void registerUndo(XJUndoDelegate delegate, JTextPane textPane) { 673 undoEngine.registerUndo(new XJUndo(undoEngine, delegate), textPane); 674 } 675 676 public void performUndo() { 677 XJUndo undo = getCurrentUndo(); 678 if(undo != null) { 679 undo.performUndo(); 680 } 681 } 682 683 public void performRedo() { 684 XJUndo undo = getCurrentUndo(); 685 if(undo != null) { 686 undo.performRedo(); 687 } 688 } 689 690 public XJUndo getUndo(JTextPane textPane) { 691 return undoEngine.getUndo(textPane); 692 } 693 694 public XJUndo getCurrentUndo() { 695 return undoEngine.getCurrentUndo(); 696 } 697 698 public boolean shouldDisplayMainMenuBar() { 699 return true; 700 } 701 702 public boolean shouldAppearsInWindowMenu() { 703 return false; 704 } 705 706 public void windowActivated() { 707 708 } 709 710 public void windowDeactivated() { 711 712 } 713 714 public void windowClosing() { 715 716 } 717 718 public void customizeFileMenu(XJMenu menu) { 719 720 } 721 722 public void customizeEditMenu(XJMenu menu) { 723 724 } 725 726 public void customizeWindowMenu(XJMenu menu) { 727 728 } 729 730 public void customizeHelpMenu(XJMenu menu) { 731 732 } 733 734 public void customizeMenuBar(XJMainMenuBar menubar) { 735 736 } 737 738 public void menuItemState(XJMenuItem item) { 739 switch(item.getTag()) { 740 case XJMainMenuBar.MI_NEW: 741 item.setTitle(XJLocalizable.getXJString("New")+((XJApplication.shared().getDocumentExtensions().size()>1)?"...":"")); 742 break; 743 case XJMainMenuBar.MI_UNDO: 744 case XJMainMenuBar.MI_REDO: 745 getMainMenuBar().menuUndoRedoItemState(undoEngine.getCurrentUndo()); 746 break; 747 } 748 } 749 750 public void handleMenuEvent(XJMenu menu, XJMenuItem item) { 751 switch(item.getTag()) { 752 case XJMainMenuBar.MI_UNDO: 753 performUndo(); 754 break; 755 case XJMainMenuBar.MI_REDO: 756 performRedo(); 757 break; 758 case XJMainMenuBar.MI_CUT: 759 performActionOnFocusedJComponent(DefaultEditorKit.cutAction); 760 break; 761 case XJMainMenuBar.MI_COPY: 762 performActionOnFocusedJComponent(DefaultEditorKit.copyAction); 763 break; 764 case XJMainMenuBar.MI_PASTE: 765 performActionOnFocusedJComponent(DefaultEditorKit.pasteAction); 766 break; 767 case XJMainMenuBar.MI_SELECT_ALL: 768 performActionOnFocusedJComponent(DefaultEditorKit.selectAllAction); 769 break; 770 } 771 } 772 773 public void handleMenuSelected(XJMenu menu) { 774 } 775 776 public static void performActionOnFocusedJComponent(String action) { 777 JComponent c = getFocusedJComponent(); 778 if(c != null) 779 c.getActionMap().get(action).actionPerformed(null); 780 } 781 782 public static JComponent getFocusedJComponent() { 783 Component c = KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner(); 784 if(c instanceof JComponent) 785 return (JComponent)c; 786 else 787 return null; 788 } 789 790 public Container getJavaContainer() { 791 if(useDesktop) { 792 return jInternalFrame; 793 } else { 794 return jFrame; 795 } 796 } 797 798 private void restoreWindowBounds() { 799 String name = autosaveName(); 800 if(name == null) return; 801 802 Rectangle r = restoreWindowBoundsNewWay(name); 803 if(r == null) { 804 r = (Rectangle) XJApplication.shared().getPreferences().getObject(name, null); 805 } 806 807 if(r != null) { 808 setPosition(r.x, r.y); 809 setSize(r.width, r.height); 810 } 811 } 812 813 public static final String PREF_WINDOWS_BOUNDS = "xjframe_bounds"; 814 815 private Rectangle restoreWindowBoundsNewWay(String name) { 816 Map m = (Map ) XJApplication.shared().getPreferences().getObject(PREF_WINDOWS_BOUNDS, null); 817 if(m == null) return null; 818 819 return (Rectangle) m.get(name); 820 } 821 822 protected void saveWindowBounds() { 823 String name = autosaveName(); 824 if(name == null) 825 return; 826 827 Point pos = getLocation(); 828 Dimension s = getSize(); 829 Rectangle r = new Rectangle(pos.x, pos.y, s.width, s.height); 830 XJPreferences prefs = XJApplication.shared().getPreferences(); 831 Map <String ,Rectangle> docs = (Map <String ,Rectangle>) prefs.getObject(PREF_WINDOWS_BOUNDS, null); 832 if(docs == null) { 833 docs = new HashMap <String , Rectangle>(); 834 } 835 docs.put(name, r); 836 prefs.setObject(PREF_WINDOWS_BOUNDS, docs); 837 } 838 839 } 840 | Popular Tags |