package com.openfin.desktop.demo; /** * Example of Java window that can be managed by OpenFin layout service for snap&dock */ import com.openfin.desktop.*; import com.openfin.desktop.Window; import com.openfin.desktop.channel.ChannelAction; import com.openfin.desktop.channel.ChannelClient; import com.openfin.desktop.win32.ExternalWindowObserver; import com.sun.jna.Native; import com.sun.jna.platform.win32.WinDef; import org.json.JSONArray; import org.json.JSONObject; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.lang.System; public class LayoutFrame extends JFrame { private static String LayoutServiceChannelName = "of-layouts-service-v1"; private ExternalWindowObserver externalWindowObserver; private JLabel labelName; private JButton btnUndock; private String windowName; private ChannelClient channelClient; private String appUuid; private boolean frameless; public LayoutFrame(DesktopConnection desktopConnection, String appUuid, String windowName) throws DesktopException { this(desktopConnection, appUuid, windowName, false); } public LayoutFrame(DesktopConnection desktopConnection, String appUuid, String windowName, boolean frameless) throws DesktopException { super(); this.setTitle(windowName); System.out.println(windowName + " being created "); this.appUuid = appUuid; this.windowName = windowName; this.frameless = frameless; this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); this.setPreferredSize(new Dimension(640, 480)); JPanel pnl = new JPanel(); pnl.setLayout(new BoxLayout(pnl, BoxLayout.Y_AXIS)); this.labelName = new JLabel(windowName); pnl.add(labelName); this.btnUndock = new JButton("undock"); this.btnUndock.setEnabled(false); pnl.add(btnUndock); this.getContentPane().add(pnl); if (frameless) { this.setUndecorated(true); JPanel titleBar = new JPanel(new BorderLayout()); titleBar.setBackground(Color.DARK_GRAY); MouseAdapter myListener = new MouseAdapter() { int pressedAtX, pressedAtY; @Override public void mousePressed(MouseEvent e) { pressedAtX = e.getX(); pressedAtY = e.getY(); System.out.println("mouse pressed at x=" + pressedAtX + ", y=" + pressedAtY); LayoutFrame.this.externalWindowObserver.enterSizeMove(); } @Override public void mouseDragged(MouseEvent e) { int distanceX = e.getX() - pressedAtX; int distanceY = e.getY() - pressedAtY; System.out.println("dragged x=" + distanceX + ", y=" + distanceY); Point frameLocation = LayoutFrame.this.getLocation(); Dimension dimension = LayoutFrame.this.getSize(); WindowBounds bounds = new WindowBounds(frameLocation.x + distanceX, frameLocation.y + distanceY, dimension.width, dimension.height); Point point = new Point(e.getX(), e.getY()); if (!LayoutFrame.this.externalWindowObserver.onMoving(bounds, point)) { LayoutFrame.this.setLocation(frameLocation.x + distanceX, frameLocation.y + distanceY); } } @Override public void mouseReleased(MouseEvent e) { LayoutFrame.this.externalWindowObserver.exitSizeMove(); } }; titleBar.addMouseListener(myListener); titleBar.addMouseMotionListener(myListener); JButton btnClose = new JButton("X"); btnClose.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { LayoutFrame.this.dispose(); }}); titleBar.add(btnClose, BorderLayout.EAST); this.getContentPane().add(titleBar, BorderLayout.NORTH); } this.pack(); this.setLocationRelativeTo(null); this.setVisible(true); this.externalWindowObserver = new ExternalWindowObserver(desktopConnection.getPort(), appUuid, windowName, this, new AckListener() { @Override public void onSuccess(Ack ack) { ExternalWindowObserver observer = (ExternalWindowObserver) ack.getSource(); observer.getDesktopConnection().getChannel(LayoutServiceChannelName).connect( new AsyncCallback<ChannelClient>() { @Override public void onSuccess(ChannelClient client) { LayoutFrame.this.channelClient = client; btnUndock.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JSONObject payload = new JSONObject(); payload.put("uuid", appUuid); payload.put("name", windowName); client.dispatch("UNDOCK-WINDOW", payload, null); } }); client.register("event", new ChannelAction() { @Override public JSONObject invoke(String action, JSONObject payload, JSONObject senderIdentity) { System.out.printf("channel event " + action); return null; } }); } }); } @Override public void onError(Ack ack) { System.out.println(windowName + ": unable to register external window, " + ack.getReason()); } }); // this.externalWindowObserver.setUserGesture(!this.frameless); try { // if (this.frameless) { // WindowOptions options = new WindowOptions(); // options.setFrame(false); // this.externalWindowObserver.setWindowOptions(options); // } this.externalWindowObserver.start(); } catch (Exception e) { e.printStackTrace(); } Window w = Window.wrap(appUuid, windowName, desktopConnection); w.addEventListener("group-changed", new EventListener() { @Override public void eventReceived(com.openfin.desktop.ActionEvent actionEvent) { JSONObject eventObj = actionEvent.getEventObject(); w.getGroup(new AsyncCallback<java.util.List<Window>>() { @Override public void onSuccess(java.util.List<Window> result) { if (result.size() > 0) { checkTabbing(); } else { LayoutFrame.this.btnUndock.setEnabled(false); setHasFrame(LayoutFrame.this, true); } } }, null); } }, null); this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { super.windowClosing(e); try { LayoutFrame.this.cleanup(); LayoutFrame.this.dispose(); } catch (Exception e1) { e1.printStackTrace(); } } public void windowClosed(WindowEvent e) { super.windowClosed(e); System.out.println(windowName + " closed "); } }); } private void checkTabbing() { JSONObject payload = new JSONObject(); payload.put("uuid", appUuid); payload.put("name", windowName); channelClient.dispatch("GETTABS", payload, new AckListener() { @Override public void onSuccess(Ack ack) { System.out.printf("channel GETTABS "); JSONObject data = (JSONObject) ack.getData(); Object result = data.get("result"); if (result != null && result instanceof JSONArray) { JSONArray tabs = (JSONArray) result; boolean enabled = !(tabs != null && tabs.length() > 0); LayoutFrame.this.btnUndock.setEnabled(enabled); setHasFrame(LayoutFrame.this, false); } else { LayoutFrame.this.btnUndock.setEnabled(true); setHasFrame(LayoutFrame.this, true); } } @Override public void onError(Ack ack) { System.out.printf("channel GETTABS error " + ack.getReason()); } }); } private void setHasFrame(JFrame frame, boolean hasFrame) { if (!this.frameless) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { System.out.println(windowName + " hasFrame=" + hasFrame); WinDef.HWND hWnd = new WinDef.HWND(); hWnd.setPointer(Native.getComponentPointer(frame)); LayoutFrame.this.externalWindowObserver.setHasFrame(hWnd, hasFrame); frame.setResizable(hasFrame); frame.invalidate(); frame.validate(); frame.repaint(); SwingUtilities.updateComponentTreeUI(frame); } }); } } public String getWindowName() { return windowName; } public void cleanup() { try { System.out.println(windowName + " cleaning up "); this.externalWindowObserver.dispose(); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { final JFrame frame = new JFrame(); frame.setPreferredSize(new Dimension(640, 480)); JPanel pnl = new JPanel(new FlowLayout(FlowLayout.CENTER)); frame.setUndecorated(true); JPanel titleBar = new JPanel(new BorderLayout()); titleBar.setBackground(Color.DARK_GRAY); MouseAdapter myListener = new MouseAdapter() { int pressedAtX, pressedAtY; @Override public void mousePressed(MouseEvent e) { pressedAtX = e.getX(); pressedAtY = e.getY(); System.out.println("mouse pressed at x=" + pressedAtX + ", y=" + pressedAtY); } @Override public void mouseDragged(MouseEvent e) { int distanceX = e.getX() - pressedAtX; int distanceY = e.getY() - pressedAtY; System.out.println("dragged x=" + distanceX + ", y=" + distanceY); Point frameLocation = frame.getLocation(); frame.setLocation(frameLocation.x + distanceX, frameLocation.y + distanceY); } @Override public void mouseReleased(MouseEvent e) { pressedAtX = e.getX(); pressedAtY = e.getY(); System.out.println("mouse released at x=" + pressedAtX + ", y=" + pressedAtY); } }; titleBar.addMouseListener(myListener); titleBar.addMouseMotionListener(myListener); JButton btnClose = new JButton("X"); btnClose.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { frame.dispose(); }}); titleBar.add(btnClose, BorderLayout.EAST); frame.getContentPane().add(titleBar, BorderLayout.NORTH); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }