package com.openfin.desktop.demo; import com.openfin.desktop.*; import com.openfin.desktop.win32.ExternalWindowObserver; import info.clearthought.layout.TableLayout; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.swing.*; import java.awt.*; import java.awt.event.ActionListener; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; /** * This app works with OpenFinDockingDemo as another dockable Java window * * Created by wche on 3/9/2016. */ public class DockingDemo2 extends JPanel implements ActionListener, WindowListener { private final static Logger logger = LoggerFactory.getLogger(DockingDemo2.class.getName()); protected String javaParentAppUuid = "Java Parent App"; // Its value must match OpenFinDockingDemo. Please see OpenFinDockingDemo for comments protected String appUuid = "AnotherJavaDocking"; // UUID for desktopConnection protected String javaWindowName = "Another Java Dock Window"; protected DesktopConnection desktopConnection; protected ExternalWindowObserver externalWindowObserver; private static JFrame jFrame; protected JButton undockButton; protected JTextField dockStatus; // show Ready to dock message public DockingDemo2() { try { this.desktopConnection = new DesktopConnection(appUuid); startOpenFinRuntime(); } catch (DesktopException desktopError) { desktopError.printStackTrace(); } setLayout(new BorderLayout()); add(layoutCenterPanel(), BorderLayout.CENTER); add(layoutLeftPanel(), BorderLayout.WEST); setBorder(BorderFactory.createEmptyBorder(20,20,20,20)); } private JPanel layoutLeftPanel() { JPanel panel = new JPanel(); double size[][] = {{410}, {120, 30, TableLayout.FILL}}; panel.setLayout(new TableLayout(size)); panel.add(layoutActionButtonPanel(), "0,0,0,0"); panel.add(layoutDockStatus(), "0,1,0,1"); return panel; } private JTextField layoutDockStatus() { this.dockStatus = new JTextField(); return this.dockStatus; } private JPanel layoutActionButtonPanel() { JPanel buttonPanel = new JPanel(); JPanel topPanel = new JPanel(); double size[][] = {{10, 190, 20, 190, 10}, {25, 10, 25, 10}}; topPanel.setLayout(new TableLayout(size)); topPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createBevelBorder(2), "Desktop")); undockButton = new JButton("Undock"); undockButton.setActionCommand("undock-window"); undockButton.setEnabled(false); topPanel.add(undockButton, "1,0,1,0"); undockButton.addActionListener(this); buttonPanel.add(topPanel, "0,0"); return buttonPanel; } private JPanel layoutCenterPanel() { JPanel panel = new JPanel(); double size[][] = {{TableLayout.FILL}, {150, 150, TableLayout.FILL}}; panel.setLayout(new TableLayout(size)); return panel; } private void undockFromOtherWindows() { try { // send message to Docking Manager to undock me JSONObject msg = new JSONObject(); msg.put("applicationUuid", javaParentAppUuid); msg.put("windowName", javaWindowName); desktopConnection.getInterApplicationBus().publish("undock-window", msg); } catch (Exception e) { e.printStackTrace(); } undockButton.setEnabled(false); } private void startOpenFinRuntime() { try { DesktopStateListener listener = new DesktopStateListener() { @Override public void onReady() { onRuntimeReady(); } @Override public void onClose(String error) { } @Override public void onError(String reason) { logger.error("Connection failed: " + reason); java.lang.System.exit(0); } @Override public void onMessage(String message) { } @Override public void onOutgoingMessage(String message) { } }; desktopConnection.setAdditionalRuntimeArguments(" --v=1"); // enable additional logging from Runtime String desktopVersion = java.lang.System.getProperty("com.openfin.demo.version"); if (desktopVersion == null) { desktopVersion = "stable"; } desktopConnection.connectToVersion(desktopVersion, listener, 60); // 5.44.10.26 has fix for cross-app docking, which is required for windowsInShameGroupMoveTogether } catch (Exception e) { e.printStackTrace(); } } private void onRuntimeReady() { try { this.desktopConnection.getInterApplicationBus().subscribe("*", "window-docked", (uuid, topic, data) -> { JSONObject event = (JSONObject) data; String appUuid = event.getString("applicationUuid"); String windowName = event.getString("windowName"); if (javaParentAppUuid.equals(appUuid) && javaWindowName.equals(windowName)) { updateUndockButton(true); } }); this.desktopConnection.getInterApplicationBus().subscribe("*", "window-undocked", (uuid, topic, data) -> { JSONObject event = (JSONObject) data; String appUuid = event.getString("applicationUuid"); String windowName = event.getString("windowName"); if (javaParentAppUuid.equals(appUuid) && javaWindowName.equals(windowName)) { updateUndockButton(false); } }); registerJavaWindow(); Application javaParentApp = Application.wrap(javaParentAppUuid, desktopConnection); javaParentApp.addEventListener("closed", actionEvent -> { shutdown(); }, null); } catch (Exception e) { logger.error("Error creating DockingManager", e); } } private void registerJavaWindow() { try { externalWindowObserver = new ExternalWindowObserver(desktopConnection.getPort(), javaParentAppUuid, javaWindowName, jFrame, new AckListener() { @Override public void onSuccess(Ack ack) { try { if (ack.isSuccessful()) { JSONObject request = new JSONObject(); request.put("applicationUuid", javaParentAppUuid); request.put("windowName", javaWindowName); desktopConnection.getInterApplicationBus().publish("register-docking-window", request); } } catch (Exception ex) { logger.error("Error registering window", ex); } } @Override public void onError(Ack ack) { logger.error("Error registering java window ", ack.getReason()); } }); } catch (Exception e) { logger.error("Error registering external window", e); } } public void actionPerformed(java.awt.event.ActionEvent e) { if ("undock-window".equals(e.getActionCommand())) { undockFromOtherWindows(); } } private void updateUndockButton(boolean enabled) { this.undockButton.setEnabled(enabled); if (enabled) { this.dockStatus.setText("Docked. Click Unlock button to undock"); } else { this.dockStatus.setText(""); } } private static void createAndShowGUI() { //Create and set up the window. jFrame = new JFrame("Another Java Docking Demo"); jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Create and set up the content pane. DockingDemo2 newContentPane = new DockingDemo2(); newContentPane.setOpaque(true); //content panes must be opaque jFrame.setContentPane(newContentPane); jFrame.addWindowListener(newContentPane); //Display the window. jFrame.pack(); jFrame.setSize(470, 300); jFrame.setLocation(600, 400); // jFrame.setLocationRelativeTo(null); jFrame.setResizable(false); jFrame.setVisible(true); } private void shutdown() { logger.debug("shutting down"); if (externalWindowObserver != null) { logger.debug("Closing"); try { JSONObject request = new JSONObject(); request.put("applicationUuid", javaParentAppUuid); request.put("windowName", javaWindowName); desktopConnection.getInterApplicationBus().publish("unregister-docking-window", request); Thread.sleep(2000); // give time to flush messages to Runtime externalWindowObserver.dispose(); desktopConnection.disconnect(); Thread.sleep(1000); // give time to flush messages to Runtime } catch (Exception ex) { logger.error("Error existing", ex); } } } /** * * @param args */ public static void main(String[] args) { javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); } @Override public void windowOpened(WindowEvent e) { } @Override public void windowClosing(WindowEvent e) { shutdown(); } @Override public void windowClosed(WindowEvent e) { } @Override public void windowIconified(WindowEvent e) { } @Override public void windowDeiconified(WindowEvent e) { } @Override public void windowActivated(WindowEvent e) { } @Override public void windowDeactivated(WindowEvent e) { } }