001/* 002 * Copyright 2010-2015 Institut Pasteur. 003 * 004 * This file is part of Icy. 005 * 006 * Icy is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * Icy is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with Icy. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package icy.gui.util; 020 021import icy.common.listener.weak.WeakComponentListener; 022import icy.common.listener.weak.WeakIcyFrameListener; 023import icy.common.listener.weak.WeakWindowListener; 024import icy.gui.component.ExternalizablePanel; 025import icy.gui.component.ExternalizablePanel.StateListener; 026import icy.gui.component.ExternalizablePanel.WeakStateListener; 027import icy.gui.frame.IcyFrame; 028import icy.gui.frame.IcyFrameAdapter; 029import icy.gui.frame.IcyFrameEvent; 030import icy.gui.main.MainFrame; 031import icy.preferences.IcyPreferences; 032import icy.preferences.XMLPreferences; 033 034import java.awt.Dimension; 035import java.awt.Point; 036import java.awt.event.ComponentAdapter; 037import java.awt.event.ComponentEvent; 038import java.awt.event.WindowAdapter; 039import java.awt.event.WindowEvent; 040 041import javax.swing.JComponent; 042import javax.swing.JFrame; 043 044/** 045 * Load and Save you window position in the registry 046 * 047 * @author fab & stephane 048 */ 049public class WindowPositionSaver 050{ 051 final private static String ID_EXTERNALIZED = "Externalized"; 052 final private static String ID_PANELIZED = "Panelized"; 053 054 final private static String ID_XC = "XC"; 055 final private static String ID_YC = "YC"; 056 final private static String ID_WC = "WidthC"; 057 final private static String ID_HC = "HeightC"; 058 059 final private static String ID_XI = "XI"; 060 final private static String ID_YI = "YI"; 061 final private static String ID_WI = "WidthI"; 062 final private static String ID_HI = "HeightI"; 063 final private static String ID_MAXIMIZEDI = "MaximizedI"; 064 065 final private static String ID_XE = "XE"; 066 final private static String ID_YE = "YE"; 067 final private static String ID_WE = "WidthE"; 068 final private static String ID_HE = "HeightE"; 069 final private static String ID_MAXIMIZEDE = "MaximizedE"; 070 071 final XMLPreferences preferences; 072 073 final private MainFrame mainFrame; 074 final private IcyFrame icyFrame; 075 final private ExternalizablePanel extPanel; 076 final private JFrame jFrame; 077 final private JComponent component; 078 079 final private boolean hasLoc; 080 final private boolean hasDim; 081 082 final WindowAdapter windowAdapter; 083 final IcyFrameAdapter icyFrameAdapter; 084 final ComponentAdapter componentAdapter; 085 final StateListener stateListener; 086 087 private WindowPositionSaver(final MainFrame mainFrame, final IcyFrame icyFrame, final ExternalizablePanel extPanel, 088 final JFrame jFrame, final JComponent component, final String key, final Point defLoc, 089 final Dimension defDim) 090 { 091 preferences = IcyPreferences.root().node(key); 092 093 this.mainFrame = mainFrame; 094 this.icyFrame = icyFrame; 095 this.extPanel = extPanel; 096 this.jFrame = jFrame; 097 this.component = component; 098 099 hasLoc = defLoc != null; 100 hasDim = defDim != null; 101 102 // directly load location and dimension 103 if (hasLoc) 104 loadLocation(defLoc); 105 if (hasDim) 106 loadDimension(defDim); 107 loadState(); 108 109 // keep hard reference on it 110 componentAdapter = new ComponentAdapter() 111 { 112 @Override 113 public void componentResized(ComponentEvent e) 114 { 115 // event comes from panel itself 116 if ((extPanel == null) || (e.getSource() == extPanel)) 117 saveAll(); 118 } 119 120 @Override 121 public void componentMoved(ComponentEvent e) 122 { 123 // event comes from panel itself 124 if ((extPanel == null) || (e.getSource() == extPanel)) 125 saveAll(); 126 } 127 128 @Override 129 public void componentShown(ComponentEvent e) 130 { 131 // correctly save internalized / externalized state 132 saveAll(); 133 } 134 135 @Override 136 public void componentHidden(ComponentEvent e) 137 { 138 // correctly save internalized / externalized state 139 saveAll(); 140 } 141 }; 142 143 // keep hard reference on it 144 windowAdapter = new WindowAdapter() 145 { 146 @Override 147 public void windowClosing(WindowEvent e) 148 { 149 saveAll(); 150 } 151 }; 152 153 // keep hard reference on it 154 icyFrameAdapter = new IcyFrameAdapter() 155 { 156 @Override 157 public void icyFrameClosing(IcyFrameEvent e) 158 { 159 saveAll(); 160 } 161 }; 162 163 // keep hard reference on it 164 stateListener = new StateListener() 165 { 166 @Override 167 public void stateChanged(ExternalizablePanel source, boolean externalized) 168 { 169 saveAll(); 170 } 171 }; 172 173 if (mainFrame != null) 174 { 175 mainFrame.addWindowListener(new WeakWindowListener(windowAdapter)); 176 mainFrame.addComponentListener(new WeakComponentListener(componentAdapter)); 177 } 178 else if (icyFrame != null) 179 { 180 icyFrame.addFrameListener(new WeakIcyFrameListener(icyFrameAdapter)); 181 icyFrame.addComponentListener(new WeakComponentListener(componentAdapter)); 182 } 183 else if (extPanel != null) 184 { 185 extPanel.addComponentListener(new WeakComponentListener(componentAdapter)); 186 extPanel.addStateListener(new WeakStateListener(stateListener)); 187 extPanel.getFrame().addFrameListener(new WeakIcyFrameListener(icyFrameAdapter)); 188 extPanel.getFrame().addComponentListener(new WeakComponentListener(componentAdapter)); 189 } 190 else if (jFrame != null) 191 { 192 jFrame.addWindowListener(new WeakWindowListener(windowAdapter)); 193 jFrame.addComponentListener(new WeakComponentListener(componentAdapter)); 194 } 195 else if (component != null) 196 { 197 component.addComponentListener(new WeakComponentListener(componentAdapter)); 198 } 199 200 checkVisibility(); 201 } 202 203 public WindowPositionSaver(MainFrame frame, String key, Point defLoc, Dimension defDim) 204 { 205 this(frame, null, null, null, null, key, defLoc, defDim); 206 } 207 208 public WindowPositionSaver(MainFrame frame, String key, Point defLoc) 209 { 210 this(frame, null, null, null, null, key, defLoc, null); 211 } 212 213 public WindowPositionSaver(MainFrame frame, String key, Dimension defDim) 214 { 215 this(frame, null, null, null, null, key, null, defDim); 216 } 217 218 public WindowPositionSaver(IcyFrame frame, String key, Point defLoc, Dimension defDim) 219 { 220 this(null, frame, null, null, null, key, defLoc, defDim); 221 } 222 223 public WindowPositionSaver(IcyFrame frame, String key, Point defLoc) 224 { 225 this(null, frame, null, null, null, key, defLoc, null); 226 } 227 228 public WindowPositionSaver(IcyFrame frame, String key, Dimension defDim) 229 { 230 this(null, frame, null, null, null, key, null, defDim); 231 } 232 233 public WindowPositionSaver(ExternalizablePanel extPanel, String key, Point defLoc, Dimension defDim) 234 { 235 this(null, null, extPanel, null, null, key, defLoc, defDim); 236 } 237 238 public WindowPositionSaver(ExternalizablePanel extPanel, String key, Point defLoc) 239 { 240 this(null, null, extPanel, null, null, key, defLoc, null); 241 } 242 243 public WindowPositionSaver(ExternalizablePanel extPanel, String key, Dimension defDim) 244 { 245 this(null, null, extPanel, null, null, key, null, defDim); 246 } 247 248 public WindowPositionSaver(JFrame frame, String key, Point defLoc, Dimension defDim) 249 { 250 this(null, null, null, frame, null, key, defLoc, defDim); 251 } 252 253 public WindowPositionSaver(JFrame frame, String key, Point defLoc) 254 { 255 this(null, null, null, frame, null, key, defLoc, null); 256 } 257 258 public WindowPositionSaver(JFrame frame, String key, Dimension defDim) 259 { 260 this(null, null, null, frame, null, key, null, defDim); 261 } 262 263 public WindowPositionSaver(JComponent component, String key, Point defLoc, Dimension defDim) 264 { 265 this(null, null, null, null, component, key, defLoc, defDim); 266 } 267 268 public WindowPositionSaver(JComponent component, String key, Point defLoc) 269 { 270 this(null, null, null, null, component, key, defLoc, null); 271 } 272 273 public WindowPositionSaver(JComponent component, String key, Dimension defDim) 274 { 275 this(null, null, null, null, component, key, null, defDim); 276 } 277 278 // void checkPosition() 279 // { 280 // final Rectangle rect; 281 // 282 // ComponentUtil.fixPosition(rect, rect); 283 // 284 // // only for frame 285 // if (mainFrame != null) 286 // ComponentUtil.fixP 287 // rect = mainFrame.getBounds(); 288 // else if (icyFrame != null) 289 // rect = icyFrame.getBounds(); 290 // // check position only for frame 291 // else if ((extPanel != null) && extPanel.isExternalized()) 292 // rect = extPanel.getFrame().getBounds(); 293 // else if (jFrame != null) 294 // rect = jFrame.getBounds(); 295 // else 296 // return; 297 // 298 // if (fixPosition(rect)) 299 // { 300 // if (mainFrame != null) 301 // mainFrame.setBounds(rect); 302 // else if (icyFrame != null) 303 // icyFrame.setBounds(rect); 304 // // check position only for frame 305 // else if ((extPanel != null) && extPanel.isExternalized()) 306 // extPanel.getFrame().setBounds(rect); 307 // else if (jFrame != null) 308 // jFrame.setBounds(rect); 309 // } 310 // } 311 // 312 // public static boolean fixPosition(Rectangle rect) 313 // { 314 // Rectangle desktopRect = SystemUtil.getDesktopBounds(); 315 // boolean result = false; 316 // int limit; 317 // 318 // limit = (int) (desktopRect.getMaxX() - DESKTOP_MARGIN); 319 // if (rect.x >= limit) 320 // { 321 // rect.x = limit; 322 // result = true; 323 // } 324 // else 325 // { 326 // limit = (int) desktopRect.getMinX(); 327 // if (((rect.x + rect.width) - DESKTOP_MARGIN) < limit) 328 // { 329 // rect.x = DESKTOP_MARGIN - rect.width; 330 // result = true; 331 // } 332 // } 333 // limit = (int) (desktopRect.getMaxY() - DESKTOP_MARGIN); 334 // if (rect.y >= limit) 335 // { 336 // rect.y = limit; 337 // result = true; 338 // } 339 // else 340 // { 341 // limit = (int) desktopRect.getMinY(); 342 // if (rect.y < limit) 343 // { 344 // rect.y = limit; 345 // result = true; 346 // } 347 // } 348 // 349 // return result; 350 // } 351 352 public XMLPreferences getPreferences() 353 { 354 return preferences; 355 } 356 357 public void loadLocation(Point defaultPos) 358 { 359 final int x, y; 360 361 if (defaultPos == null) 362 { 363 x = 0; 364 y = 0; 365 } 366 else 367 { 368 x = defaultPos.x; 369 y = defaultPos.y; 370 } 371 372 final Point positionC = new Point(preferences.getInt(ID_XC, x), preferences.getInt(ID_YC, y)); 373 final Point positionI = new Point(preferences.getInt(ID_XI, x), preferences.getInt(ID_YI, y)); 374 final Point positionE = new Point(preferences.getInt(ID_XE, x), preferences.getInt(ID_YE, y)); 375 376 if (mainFrame != null) 377 { 378 mainFrame.setLocation(positionE); 379 } 380 else if (icyFrame != null) 381 { 382 icyFrame.setLocationInternal(positionI); 383 icyFrame.setLocationExternal(positionE); 384 } 385 else if (extPanel != null) 386 { 387 extPanel.setLocation(positionC); 388 389 // get the panel frame 390 final IcyFrame f = extPanel.getFrame(); 391 392 f.setLocationInternal(positionI); 393 f.setLocationExternal(positionE); 394 } 395 else if (jFrame != null) 396 { 397 jFrame.setLocation(positionE); 398 } 399 else if (component != null) 400 { 401 component.setLocation(positionC); 402 } 403 } 404 405 public void loadDimension(Dimension defaultDim) 406 { 407 final int w, h; 408 409 if (defaultDim == null) 410 { 411 w = 300; 412 h = 300; 413 } 414 else 415 { 416 w = defaultDim.width; 417 h = defaultDim.height; 418 } 419 420 // minimum size is 10 pixels 421 int widthC = Math.max(preferences.getInt(ID_WC, w), 10); 422 int heightC = Math.max(preferences.getInt(ID_HC, h), 10); 423 int widthI = Math.max(preferences.getInt(ID_WI, w), 10); 424 int heightI = Math.max(preferences.getInt(ID_HI, h), 10); 425 int widthE = Math.max(preferences.getInt(ID_WE, w), 10); 426 int heightE = Math.max(preferences.getInt(ID_HE, h), 10); 427 428 final Dimension dimC = new Dimension(widthC, heightC); 429 final Dimension dimI = new Dimension(widthI, heightI); 430 final Dimension dimE = new Dimension(widthE, heightE); 431 432 if (mainFrame != null) 433 { 434 // set size only else we cannot pack anymore the frame for detached mode 435 mainFrame.setSize(dimE); 436 } 437 else if (icyFrame != null) 438 { 439 icyFrame.setPreferredSizeExternal(dimE); 440 icyFrame.setSizeExternal(dimE); 441 icyFrame.setPreferredSizeInternal(dimI); 442 icyFrame.setSizeInternal(dimI); 443 } 444 else if (extPanel != null) 445 { 446 extPanel.setPreferredSize(dimC); 447 448 // get the panel frame 449 final IcyFrame f = extPanel.getFrame(); 450 451 f.setPreferredSizeExternal(dimE); 452 f.setSizeExternal(dimE); 453 f.setPreferredSizeInternal(dimI); 454 f.setSizeInternal(dimI); 455 } 456 else if (jFrame != null) 457 { 458 jFrame.setPreferredSize(dimE); 459 jFrame.setSize(dimE); 460 } 461 else if (component != null) 462 { 463 component.setPreferredSize(dimC); 464 } 465 } 466 467 public void loadState() 468 { 469 // default is internalized and panelized 470 final boolean externalized = preferences.getBoolean(ID_EXTERNALIZED, false); 471 final boolean panelized = preferences.getBoolean(ID_PANELIZED, true); 472 final boolean maximizedE = preferences.getBoolean(ID_MAXIMIZEDE, false); 473 final boolean maximizedI = preferences.getBoolean(ID_MAXIMIZEDI, false); 474 475 if (mainFrame != null) 476 { 477 ComponentUtil.setMaximized(mainFrame, maximizedE); 478 } 479 else if (icyFrame != null) 480 { 481 if (externalized) 482 icyFrame.externalize(); 483 else 484 icyFrame.internalize(); 485 icyFrame.setMaximizedExternal(maximizedE); 486 icyFrame.setMaximizedInternal(maximizedI); 487 } 488 else if (extPanel != null) 489 { 490 // get the panel frame 491 final IcyFrame f = extPanel.getFrame(); 492 493 if (externalized) 494 f.externalize(); 495 else 496 f.internalize(); 497 f.setMaximizedExternal(maximizedE); 498 f.setMaximizedInternal(maximizedI); 499 500 if (panelized) 501 extPanel.internalize(); 502 else 503 extPanel.externalize(); 504 } 505 else if (jFrame != null) 506 { 507 ComponentUtil.setMaximized(jFrame, maximizedE); 508 } 509 } 510 511 public void checkVisibility() 512 { 513 if (!hasLoc) 514 return; 515 516 if (icyFrame != null) 517 { 518 // not visible ? 519 if (icyFrame.getVisibleRect().isEmpty()) 520 { 521 final Point location = icyFrame.getLocation(); 522 523 // potentially outside visible area ? --> reset its position 524 if ((location.x < 0) || (location.x > 700) || (location.y < 0) || (location.y > 500)) 525 icyFrame.setLocation(100, 100); 526 } 527 } 528 else if (extPanel != null) 529 { 530 // not visible ? reset its position 531 if (extPanel.getVisibleRect().isEmpty()) 532 { 533 final Point location = extPanel.getLocation(); 534 535 // potentially outside visible area ? --> reset its position 536 if ((location.x < 0) || (location.x > 500) || (location.y < 0) || (location.y > 300)) 537 extPanel.setLocation(100, 100); 538 } 539 } 540 else if (component != null) 541 { 542 // not visible ? reset its position 543 if (component.getVisibleRect().isEmpty()) 544 { 545 final Point location = component.getLocation(); 546 547 // potentially outside visible area ? --> reset its position 548 if ((location.x < 0) || (location.x > 500) || (location.y < 0) || (location.y > 300)) 549 component.setLocation(100, 100); 550 } 551 } 552 } 553 554 public void saveLocation() 555 { 556 if (mainFrame != null) 557 { 558 if (!(ComponentUtil.isMaximized(mainFrame) || ComponentUtil.isMinimized(mainFrame))) 559 { 560 preferences.putInt(ID_XE, mainFrame.getX()); 561 preferences.putInt(ID_YE, mainFrame.getY()); 562 } 563 } 564 else if (icyFrame != null) 565 { 566 if (!(icyFrame.isMaximizedExternal() || icyFrame.isMinimizedExternal())) 567 { 568 preferences.putInt(ID_XE, icyFrame.getXExternal()); 569 preferences.putInt(ID_YE, icyFrame.getYExternal()); 570 } 571 if (!(icyFrame.isMaximizedInternal() || icyFrame.isMinimizedInternal())) 572 { 573 preferences.putInt(ID_XI, icyFrame.getXInternal()); 574 preferences.putInt(ID_YI, icyFrame.getYInternal()); 575 } 576 } 577 else if (extPanel != null) 578 { 579 preferences.putInt(ID_XC, extPanel.getX()); 580 preferences.putInt(ID_YC, extPanel.getY()); 581 582 // get the panel frame 583 final IcyFrame f = extPanel.getFrame(); 584 585 if (!(f.isMaximizedExternal() || f.isMinimizedExternal())) 586 { 587 preferences.putInt(ID_XE, f.getXExternal()); 588 preferences.putInt(ID_YE, f.getYExternal()); 589 } 590 if (!(f.isMaximizedInternal() || f.isMinimizedInternal())) 591 { 592 preferences.putInt(ID_XI, f.getXInternal()); 593 preferences.putInt(ID_YI, f.getYInternal()); 594 } 595 } 596 else if (jFrame != null) 597 { 598 if (!(ComponentUtil.isMaximized(jFrame) || ComponentUtil.isMinimized(jFrame))) 599 { 600 preferences.putInt(ID_XE, jFrame.getX()); 601 preferences.putInt(ID_YE, jFrame.getY()); 602 } 603 } 604 else if (component != null) 605 { 606 preferences.putInt(ID_XC, component.getX()); 607 preferences.putInt(ID_YC, component.getY()); 608 } 609 } 610 611 public void saveDimension() 612 { 613 if (mainFrame != null) 614 { 615 if (!(ComponentUtil.isMaximized(mainFrame) || ComponentUtil.isMinimized(mainFrame))) 616 { 617 final Dimension dim; 618 619 if (mainFrame.isDetachedMode()) 620 dim = new Dimension(mainFrame.getWidth(), mainFrame.getPreviousHeight()); 621 else 622 dim = mainFrame.getSize(); 623 624 preferences.putInt(ID_WE, dim.width); 625 preferences.putInt(ID_HE, dim.height); 626 } 627 } 628 else if (icyFrame != null) 629 { 630 if (!(icyFrame.isMaximizedExternal() || icyFrame.isMinimizedExternal())) 631 { 632 preferences.putInt(ID_WE, icyFrame.getWidthExternal()); 633 preferences.putInt(ID_HE, icyFrame.getHeightExternal()); 634 } 635 if (!(icyFrame.isMaximizedInternal() || icyFrame.isMinimizedInternal())) 636 { 637 preferences.putInt(ID_WI, icyFrame.getWidthInternal()); 638 preferences.putInt(ID_HI, icyFrame.getHeightInternal()); 639 } 640 } 641 else if (extPanel != null) 642 { 643 preferences.putInt(ID_WC, extPanel.getWidth()); 644 preferences.putInt(ID_HC, extPanel.getHeight()); 645 646 // get the panel frame 647 final IcyFrame f = extPanel.getFrame(); 648 649 if (!(f.isMaximizedExternal() || f.isMinimizedExternal())) 650 { 651 preferences.putInt(ID_WE, f.getWidthExternal()); 652 preferences.putInt(ID_HE, f.getHeightExternal()); 653 } 654 if (!(f.isMaximizedInternal() || f.isMinimizedInternal())) 655 { 656 preferences.putInt(ID_WI, f.getWidthInternal()); 657 preferences.putInt(ID_HI, f.getHeightInternal()); 658 } 659 } 660 else if (jFrame != null) 661 { 662 if (!(ComponentUtil.isMaximized(jFrame) || ComponentUtil.isMinimized(jFrame))) 663 { 664 preferences.putInt(ID_WE, jFrame.getWidth()); 665 preferences.putInt(ID_HE, jFrame.getHeight()); 666 } 667 } 668 else if (component != null) 669 { 670 preferences.putInt(ID_WC, component.getWidth()); 671 preferences.putInt(ID_HC, component.getHeight()); 672 } 673 } 674 675 public void saveState() 676 { 677 if (mainFrame != null) 678 { 679 final boolean b; 680 681 if (mainFrame.isDetachedMode()) 682 b = mainFrame.getPreviousMaximized(); 683 else 684 b = ComponentUtil.isMaximized(mainFrame); 685 686 preferences.putBoolean(ID_MAXIMIZEDE, b); 687 } 688 if (icyFrame != null) 689 { 690 preferences.putBoolean(ID_EXTERNALIZED, icyFrame.isExternalized()); 691 preferences.putBoolean(ID_MAXIMIZEDI, icyFrame.isMaximizedInternal()); 692 preferences.putBoolean(ID_MAXIMIZEDE, icyFrame.isMaximizedExternal()); 693 } 694 else if (extPanel != null) 695 { 696 preferences.putBoolean(ID_PANELIZED, extPanel.isInternalized()); 697 698 // get the panel frame 699 final IcyFrame f = extPanel.getFrame(); 700 701 preferences.putBoolean(ID_EXTERNALIZED, f.isExternalized()); 702 preferences.putBoolean(ID_MAXIMIZEDI, f.isMaximizedInternal()); 703 preferences.putBoolean(ID_MAXIMIZEDE, f.isMaximizedExternal()); 704 } 705 else if (jFrame != null) 706 { 707 preferences.putBoolean(ID_MAXIMIZEDE, ComponentUtil.isMaximized(jFrame)); 708 } 709 } 710 711 public void saveAll() 712 { 713 if (hasLoc) 714 saveLocation(); 715 if (hasDim) 716 saveDimension(); 717 saveState(); 718 } 719}