22
33import com .openfin .desktop .*;
44import com .openfin .desktop .ActionEvent ;
5+ import com .openfin .desktop .EventListener ;
56import com .openfin .desktop .System ;
67import com .openfin .desktop .Window ;
78import com .openfin .desktop .win32 .ExternalWindowObserver ;
1314import javax .swing .*;
1415import java .awt .*;
1516import java .awt .event .*;
16- import java .util .ArrayList ;
17- import java .util .HashMap ;
18- import java .util .Iterator ;
19- import java .util .Map ;
17+ import java .util .*;
18+ import java .util .List ;
2019
2120/**
2221 * Example of docking Java window with OpenFin html5 window
@@ -35,7 +34,7 @@ public class OpenFinDockingDemo extends JPanel implements ActionListener, Window
3534 protected JButton launch ;
3635 protected JButton close ;
3736
38- protected JButton dockButtom , undockButton ;
37+ protected JButton undockButton ;
3938
4039 protected ExternalWindowObserver externalWindowObserver ;
4140 protected String javaWindowName = "Java Dock Window" ;
@@ -93,19 +92,13 @@ private JPanel layoutActionButtonPanel() {
9392 topPanel .add (launch , "1,0,1,0" );
9493 topPanel .add (close , "3,0,3,0" );
9594
96- dockButtom = new JButton ("Dock to HTML5 app" );
97- dockButtom .setActionCommand ("dock-window" );
98- dockButtom .setEnabled (false );
99- topPanel .add (dockButtom , "1,2,1,2" );
100-
10195 undockButton = new JButton ("Undock from HTML5 app" );
10296 undockButton .setActionCommand ("undock-window" );
10397 undockButton .setEnabled (false );
104- topPanel .add (undockButton , "3 ,2,3 ,2" );
98+ topPanel .add (undockButton , "1 ,2,1 ,2" );
10599
106100 close .addActionListener (this );
107101 launch .addActionListener (this );
108- dockButtom .addActionListener (this );
109102 undockButton .addActionListener (this );
110103
111104 buttonPanel .add (topPanel , "0,0" );
@@ -220,18 +213,6 @@ public void run() {
220213 }
221214 }
222215
223- private void dockToStartupApp () {
224- try {
225- createNotification ("Docking Java and HTML5" );
226- Window w = Window .wrap (startupUuid , javaWindowName , desktopConnection );
227- w .joinGroup (Window .wrap (startupUuid , startupUuid , desktopConnection ));
228- dockButtom .setEnabled (false );
229- undockButton .setEnabled (true );
230- } catch (Exception e ) {
231- e .printStackTrace ();
232- }
233- }
234-
235216 private void createNotification (String text ) throws Exception {
236217 NotificationOptions options = new NotificationOptions ("http://demoappdirectory.openf.in/desktop/config/apps/OpenFin/HelloOpenFin/views/notification.html" );
237218 options .setTimeout (5000 );
@@ -277,7 +258,6 @@ private void undockFromStartupApp() {
277258 } catch (Exception e ) {
278259 e .printStackTrace ();
279260 }
280- dockButtom .setEnabled (true );
281261 undockButton .setEnabled (false );
282262 }
283263
@@ -321,8 +301,6 @@ public void actionPerformed(java.awt.event.ActionEvent e) {
321301 runStartAction ();
322302 } else if ("close" .equals (e .getActionCommand ())) {
323303 closeDesktop ();
324- } else if ("dock-window" .equals (e .getActionCommand ())) {
325- dockToStartupApp ();
326304 } else if ("undock-window" .equals (e .getActionCommand ())) {
327305 undockFromStartupApp ();
328306 }
@@ -345,8 +323,8 @@ private void registerJavaWindow() {
345323 public void onSuccess (Ack ack ) {
346324 if (ack .isSuccessful ()) {
347325 try {
348- dockButtom .setEnabled (true );
349326 undockButton .setEnabled (false );
327+ simpleDockingManager .registerWindow (Window .wrap (startupUuid , javaWindowName , desktopConnection ));
350328 } catch (Exception e ) {
351329 e .printStackTrace ();
352330 }
@@ -382,10 +360,13 @@ private void launchHelloOpenFin() {
382360 public void onSuccess (Ack ack ) {
383361 Application application = (Application ) ack .getSource ();
384362 try {
385- application .run ();
386-
387- simpleDockingManager .registerWindow (Window .wrap (startupUuid , javaWindowName , desktopConnection ));
388- simpleDockingManager .registerWindow (Window .wrap (startupUuid , startupUuid , desktopConnection ));
363+ application .run (new AckListener () {
364+ public void onSuccess (Ack ack ) {
365+ simpleDockingManager .registerWindow (Window .wrap (startupUuid , startupUuid , desktopConnection ));
366+ }
367+ public void onError (Ack ack ) {
368+ }
369+ });
389370 } catch (Exception e ) {
390371 e .printStackTrace ();
391372 }
@@ -397,10 +378,12 @@ public void onError(Ack ack) {
397378 }
398379
399380 private void showReadyToDockMessage (Window anchorWindow ) {
381+ this .dockStatus .setForeground (Color .red );
400382 this .dockStatus .setText (String .format ("Close to %s, release mouse to dock" , anchorWindow .getName ()));
401383 }
402384 private void clearReadyToDockMessage () {
403- this .dockStatus .setText ("" );
385+ this .dockStatus .setForeground (Color .black );
386+ this .dockStatus .setText ("Move windows close to each other to dock" );
404387 }
405388 private void updateUndockButton (boolean enabled ) {
406389 this .undockButton .setEnabled (enabled );
@@ -448,7 +431,6 @@ class SimpleDockingManager {
448431 private DesktopConnection desktopConnection ;
449432 private Map <String , WindowInfo > infoMap = new HashMap <String , WindowInfo >(); // stores bounds for all windows
450433 private boolean movingDuringDocking = false ;
451- private boolean delaySnap = false ; // if true, snap the windows on bounce-changed event (mouse release).
452434 private java .util .List <WindowInfo > dockCandidates = new ArrayList <WindowInfo >(); // stores 2 windows that are close enough to dock. Used when delaySnap is true
453435 private static final int DOCKING_DISTANCE = 20 ; // defines what's "close enough"
454436
@@ -469,7 +451,7 @@ public void registerWindow(final Window window) {
469451 public void onSuccess (WindowBounds result ) {
470452 WindowInfo info = infoMap .get (key );
471453 info .bounds = result ;
472- logger .debug ("Got initial bounds for " + window .getName ());
454+ logger .debug (String . format ( "Got initial bounds for %s %d %d %d %d" , window .getName (), result . getTop (), result . getLeft (), result . getHeight (), result . getWidth () ));
473455 }
474456 }, null );
475457 window .addEventListener ("bounds-changing" , new EventListener () {
@@ -532,7 +514,7 @@ private void boundsChanging(String windowKey, WindowBounds bounds) {
532514 logger .debug ("Bounds changing " + windowKey );
533515 WindowInfo windowInfo = this .infoMap .get (windowKey );
534516 windowInfo .bounds = bounds ;
535- if (windowInfo .anchorWindow == null ) {
517+ if (! windowInfo .isDocked ) {
536518 if (!movingDuringDocking ) {
537519 this .dockCandidates .clear ();
538520 clearReadyToDockMessage ();
@@ -542,20 +524,16 @@ private void boundsChanging(String windowKey, WindowBounds bounds) {
542524 if (!another .equals (windowInfo )) {
543525 WindowBounds movingBounds = shouldDock (windowInfo , another );
544526 if (movingBounds != null ) {
545- if (delaySnap ) {
546- this .dockCandidates .add (windowInfo ); // actual docking happens in boundsChanged
547- this .dockCandidates .add (another );
548- showReadyToDockMessage (another .window );
549- } else {
550- dock (windowInfo , another , movingBounds );
551- }
527+ this .dockCandidates .add (windowInfo ); // actual docking happens in boundsChanged
528+ this .dockCandidates .add (another );
529+ showReadyToDockMessage (another .window );
552530 break ;
553531 }
554532 }
555533 }
556534 }
557535 } else {
558- // already docked
536+ logger . debug ( "Bounds changing already docked " + windowKey );
559537 }
560538 }
561539
@@ -586,62 +564,61 @@ private void boundsChanged(String windowKey, WindowBounds bounds) {
586564 */
587565 private WindowBounds shouldDock (WindowInfo movingInfo , WindowInfo anchorInfo ) {
588566 logger .debug (String .format ("Checking shouldDock %s to %s" , movingInfo .window .getName (), anchorInfo .window .getName ()));
589- WindowBounds movingBounds = null ;
590- if (movingInfo .anchorWindow == null || anchorInfo .anchorWindow == null ) {
591- WindowBounds bounds1 = movingInfo .bounds ;
592- WindowBounds bounds2 = anchorInfo .bounds ;
593- if (bounds1 != null && bounds2 != null ) {
594- int bottom1 = bounds1 .getTop () + bounds1 .getHeight ();
595- int bottom2 = bounds2 .getTop () + bounds2 .getHeight ();
596- int right1 = bounds1 .getLeft () + bounds1 .getWidth ();
597- int right2 = bounds2 .getLeft () + bounds2 .getWidth ();
598- if (bounds1 .getLeft () < right2 && bounds2 .getLeft () < right1 ) {
599- // two are in top-bottom relationship
600- if (Math .abs (bounds1 .getTop () - bottom2 ) < DOCKING_DISTANCE ) {
601- movingBounds = new WindowBounds (movingInfo .bounds .getTop (), movingInfo .bounds .getLeft (), 0 , 0 );
602- movingBounds .setTop (bottom2 );
567+ WindowBounds newBounds = null ;
568+ if (! movingInfo .isDocked || ! anchorInfo .isDocked ) {
569+ WindowBounds movingBounds = movingInfo .bounds ;
570+ WindowBounds anchorBounds = anchorInfo .bounds ;
571+ if (movingBounds != null && anchorBounds != null ) {
572+ int bottom1 = movingBounds .getTop () + movingBounds .getHeight ();
573+ int bottom2 = anchorBounds .getTop () + anchorBounds .getHeight ();
574+ int right1 = movingBounds .getLeft () + movingBounds .getWidth ();
575+ int right2 = anchorBounds .getLeft () + anchorBounds .getWidth ();
576+ if (movingBounds .getLeft () < right2 && anchorBounds .getLeft () < right1 ) {
577+ // vertical docking
578+ if (Math .abs (movingBounds .getTop () - bottom2 ) < DOCKING_DISTANCE ) {
579+ newBounds = new WindowBounds (movingInfo .bounds .getTop (), movingInfo .bounds .getLeft (), 0 , 0 );
580+ newBounds .setTop (bottom2 );
603581 logger .debug (String .format ("Detecting bottom-top docking %s to %s" , movingInfo .window .getName (), anchorInfo .window .getName ()));
604582 }
605- else if (Math .abs (bounds2 .getTop () - bottom1 ) < DOCKING_DISTANCE ) {
606- movingBounds = new WindowBounds (movingInfo .bounds .getTop (), movingInfo .bounds .getLeft (), 0 , 0 );
607- movingBounds .setTop (bounds2 .getTop () - bounds1 .getHeight ());
583+ else if (Math .abs (anchorBounds .getTop () - bottom1 ) < DOCKING_DISTANCE ) {
584+ newBounds = new WindowBounds (movingInfo .bounds .getTop (), movingInfo .bounds .getLeft (), 0 , 0 );
585+ newBounds .setTop (anchorBounds .getTop () - movingBounds .getHeight ());
608586 logger .debug (String .format ("Detecting top-bottom docking %s to %s" , movingInfo .window .getName (), anchorInfo .window .getName ()));
609587 } else {
610588 logger .debug (String .format ("shouldDock %s to %s too far top-bottom" , movingInfo .window .getName (), anchorInfo .window .getName ()));
611589 }
612- } else if (bounds1 .getTop () < bottom2 && bounds2 .getTop () < bottom1 ) {
613- // two are in side-by-side relationship
614- if (Math .abs (bounds1 .getLeft () - right2 ) < DOCKING_DISTANCE ) {
615- movingBounds = new WindowBounds (movingInfo .bounds .getTop (), movingInfo .bounds .getLeft (), 0 , 0 );
616- movingBounds .setLeft (right2 );
590+ } else if (movingBounds .getTop () < bottom2 && anchorBounds .getTop () < bottom1 ) {
591+ // horizontal docking
592+ if (Math .abs (movingBounds .getLeft () - right2 ) < DOCKING_DISTANCE ) {
593+ newBounds = new WindowBounds (movingInfo .bounds .getTop (), movingInfo .bounds .getLeft (), 0 , 0 );
594+ newBounds .setLeft (right2 );
617595 logger .debug (String .format ("Detecting right-left docking %s to %s" , movingInfo .window .getName (), anchorInfo .window .getName ()));
618596 }
619- else if (Math .abs (bounds2 .getLeft () - right1 ) < DOCKING_DISTANCE ) {
620- movingBounds = new WindowBounds (movingInfo .bounds .getTop (), movingInfo .bounds .getLeft (), 0 , 0 );
621- movingBounds .setLeft (bounds2 .getLeft () - bounds1 .getWidth ());
597+ else if (Math .abs (right1 - anchorBounds .getLeft ()) < DOCKING_DISTANCE ) {
598+ newBounds = new WindowBounds (movingInfo .bounds .getTop (), movingInfo .bounds .getLeft (), 0 , 0 );
599+ newBounds .setLeft (anchorBounds .getLeft () - movingBounds .getWidth ());
622600 logger .debug (String .format ("Detecting left-right docking %s to %s" , movingInfo .window .getName (), anchorInfo .window .getName ()));
623601 }
624602 } else {
625603 logger .debug (String .format ("shouldDock %s to %s not overlapping" , movingInfo .window .getName (), anchorInfo .window .getName ()));
626604 }
627605 }
628606 }
629- return movingBounds ;
607+ return newBounds ;
630608 }
631609
632610 /**
633- * Dock 2 windows. Snap moving window to still window first
611+ * Dock 2 windows. Snap moving window to anchor window first
612+ *
634613 * @param movingInfo moving window
635- * @param anchorInfo still window
636- * @param newBounds new bounds for moving window
614+ * @param anchorInfo anchor window
615+ * @param newBounds new bounds for moving window to be moved to for docking
637616 */
638617 private void dock (final WindowInfo movingInfo , final WindowInfo anchorInfo , WindowBounds newBounds ) {
639618 logger .debug (String .format ("Docking %s to %s" , movingInfo .window .getName (), anchorInfo .window .getName ()));
640619 // snap moving window
641- if (anchorInfo .anchorWindow == null ) {
642- anchorInfo .anchorWindow = anchorInfo .window ;
643- }
644- movingInfo .anchorWindow = anchorInfo .window ;
620+ anchorInfo .isDocked = true ;
621+ movingInfo .isDocked = true ;
645622 try {
646623 movingDuringDocking = true ;
647624 logger .debug (String .format ("Moving %s to %d %d" , movingInfo .window .getName (), newBounds .getTop (), newBounds .getLeft ()));
@@ -652,14 +629,14 @@ public void onSuccess(Ack ack) {
652629 movingInfo .window .joinGroup (anchorInfo .window , new AckListener () {
653630 public void onSuccess (Ack ack ) {
654631 updateUndockButton (true );
632+ refreshWindowGroupInfo ();
655633 }
656634 public void onError (Ack ack ) {
657635 }
658636 });
659637 }
660638 }
661639 public void onError (Ack ack ) {
662-
663640 }
664641 });
665642 } catch (Exception e ) {
@@ -671,13 +648,14 @@ public void undock(Window window) {
671648 WindowInfo windowInfo = this .infoMap .get (WindowInfo .getInfoKey (window ));
672649 if (windowInfo != null ) {
673650 try {
674- if (windowInfo .anchorWindow != null ) {
675- window .leaveGroup ();
676- if (windowInfo .anchorWindow != null ) {
677- WindowInfo anchorInfo = this .infoMap .get (WindowInfo .getInfoKey (windowInfo .anchorWindow ));
678- anchorInfo .anchorWindow = null ;
679- }
680- windowInfo .anchorWindow = null ;
651+ if (windowInfo .isDocked ) {
652+ window .leaveGroup (new AckListener () {
653+ public void onSuccess (Ack ack ) {
654+ refreshWindowGroupInfo ();
655+ }
656+ public void onError (Ack ack ) {
657+ }
658+ });
681659 updateUndockButton (false );
682660 }
683661 } catch (Exception ex ) {
@@ -687,21 +665,37 @@ public void undock(Window window) {
687665 }
688666
689667 /**
690- * Dock 2 windows with moving them together
691668 *
692- * @param window
693- * @param anchorWindow
669+ * Refresh info on isDocked on all windows. Called whenever a window is docked or undocked
670+ *
694671 */
695- public void dock (Window window , Window anchorWindow ) {
696- registerWindow (window );
697- registerWindow (anchorWindow );
698- dock (this .infoMap .get (WindowInfo .getInfoKey (window )), this .infoMap .get (WindowInfo .getInfoKey (anchorWindow )), null );
672+ private void refreshWindowGroupInfo () {
673+ java .util .List <WindowInfo > dockedWindows = new LinkedList <WindowInfo >();
674+ for (WindowInfo info : this .infoMap .values ()) {
675+ if (info .isDocked ) {
676+ dockedWindows .add (info );
677+ }
678+ }
679+ for (WindowInfo info : dockedWindows ) {
680+ final WindowInfo windowInfo = info ;
681+ windowInfo .window .getGroup (new AsyncCallback <List <Window >>() {
682+ public void onSuccess (List <Window > result ) {
683+ windowInfo .isDocked = result .size () > 0 ;
684+ }
685+ }, new AckListener () {
686+ public void onSuccess (Ack ack ) {
687+ }
688+ public void onError (Ack ack ) {
689+ logger .error (String .format ("Error getGroup %s" , ack .getReason ()));
690+ }
691+ });
692+ }
699693 }
700694 }
701695
702696 private static class WindowInfo {
703697 public Window window ;
704- public Window anchorWindow ; // group leader if this.window is docked
698+ public boolean isDocked ;
705699 public WindowBounds bounds ;
706700
707701 public WindowInfo (Window window ) {
0 commit comments