Skip to content

Commit 0f850c0

Browse files
author
Wenjun Che
committed
ADAP-42: snap and dock
1 parent 7349fcd commit 0f850c0

File tree

2 files changed

+87
-93
lines changed

2 files changed

+87
-93
lines changed
0 Bytes
Binary file not shown.

src/main/java/com/openfin/desktop/demo/OpenFinDockingDemo.java

Lines changed: 87 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.openfin.desktop.*;
44
import com.openfin.desktop.ActionEvent;
5+
import com.openfin.desktop.EventListener;
56
import com.openfin.desktop.System;
67
import com.openfin.desktop.Window;
78
import com.openfin.desktop.win32.ExternalWindowObserver;
@@ -13,10 +14,8 @@
1314
import javax.swing.*;
1415
import java.awt.*;
1516
import 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

Comments
 (0)