package org.trianacode.gui.desktop.frames; import org.trianacode.gui.desktop.DesktopView; import org.trianacode.gui.desktop.DesktopViewListener; import org.trianacode.gui.desktop.DesktopViewManager; import org.trianacode.gui.hci.DropDownButton; import org.trianacode.gui.hci.GUIEnv; import org.trianacode.gui.main.TaskGraphPanel; import org.trianacode.taskgraph.TaskGraph; import javax.swing.*; import javax.swing.border.Border; import javax.swing.border.EtchedBorder; import javax.swing.event.InternalFrameEvent; import javax.swing.event.InternalFrameListener; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.beans.PropertyVetoException; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; /** * @author Andrew Harrison * @version 1.0.0 Nov 9, 2010 */ public class FramesManager implements InternalFrameListener, ComponentListener, DesktopViewManager { public static final int MIN_WIDTH = 150; public static final int MIN_HEIGHT = 100; public static final int MIN_D_WIDTH = 500; public static final int MIN_D_HEIGHT = 400; private int offsetX = 20; private int offsetY = 20; private java.util.List<FramesView> frames = new ArrayList<FramesView>(); private FramesView selected = null; private static FramesManager manager = new FramesManager(); private java.util.List<DesktopViewListener> listeners = new ArrayList<DesktopViewListener>(); private Map<FramesView, JButton> buttons = new HashMap<FramesView, JButton>(); public static FramesManager getManager() { return manager; } private JPanel container; private JPanel butpanel; private JButton layout; private int currMaxX = 0; private int currMaxY = 0; private ComponentListener frameListener = new FrameListener(); private JDesktopPane desktop; public FramesManager() { init(); } private void init() { container = new JPanel(new BorderLayout()); this.desktop = new JDesktopPane(); this.desktop.setDesktopManager(new RestrictedDesktopManager()); this.desktop.addComponentListener(this); this.desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE); JPanel topPanel = new JPanel(new BorderLayout()); butpanel = new JPanel(); butpanel.setLayout(new BoxLayout(butpanel, BoxLayout.X_AXIS)); JPopupMenu popup = new JPopupMenu(); popup.add(new JMenuItem(new TileAction(this))); popup.add(new JMenuItem(new CascadeAction(this, offsetX, offsetY))); popup.add(new JMenuItem(new StripeAction(this))); layout = new DropDownButton(GUIEnv.getIcon("layout-dropdown.png"), popup); topPanel.add(layout, BorderLayout.WEST); topPanel.add(butpanel, BorderLayout.CENTER); container.add(topPanel, BorderLayout.NORTH); JScrollPane scroll = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); Border b = new EtchedBorder(EtchedBorder.RAISED, Color.lightGray, Color.gray); scroll.setBorder(b); scroll.setViewportView(desktop); scroll.doLayout(); container.add(scroll, BorderLayout.CENTER); } public JDesktopPane getDesktop() { return desktop; } public void setSize(FramesView frame) { double dy = ((double) desktop.getSize().height); double dx = ((double) desktop.getSize().width); setSize(frame, dx, dy, true); } private void setSize(FramesView frame, double dx, double dy, boolean init) { if (init) { TaskGraph taskgraph = frame.getTaskgraphPanel().getTaskGraph(); if (taskgraph.getTasks(false).length == 0) { frame.setSize(new Dimension((int) Math.max(MIN_WIDTH, dx * 0.6), (int) Math.max(MIN_HEIGHT, dy * 0.6))); } } if (frame.getX() + frame.getWidth() >= dx) { if (frame.getY() + frame.getHeight() >= dy) { frame.setSize(new Dimension((int) Math.max(dx - frame.getX(), MIN_WIDTH), (int) Math.max(dy - frame.getY(), MIN_HEIGHT))); } else { frame.setSize(new Dimension((int) Math.max(dx - frame.getX(), MIN_WIDTH), Math.max(frame.getHeight(), MIN_HEIGHT))); } } else { if (frame.getY() + frame.getHeight() >= dy) { if (frame.getX() + frame.getWidth() >= dx) { frame.setSize(new Dimension((int) Math.max(dx - frame.getX(), MIN_WIDTH), (int) Math.max(MIN_HEIGHT, dy - frame.getY()))); } else { frame.setSize(new Dimension(Math.max(MIN_WIDTH, frame.getWidth()), (int) Math.max(MIN_HEIGHT, dy - frame.getY()))); } } } } @Override public void internalFrameOpened(InternalFrameEvent e) { } @Override public void internalFrameClosing(InternalFrameEvent e) { JInternalFrame frame = e.getInternalFrame(); for (DesktopViewListener listener : listeners) { listener.ViewClosing((DesktopView) frame); } } @Override public void internalFrameClosed(InternalFrameEvent e) { JInternalFrame frame = e.getInternalFrame(); frames.remove(frame); if (frame instanceof FramesView) { JButton b = buttons.remove(frame); butpanel.remove(b); butpanel.revalidate(); butpanel.repaint(); } resizeDesktop(); if (frames.size() > 0) { setSelected(frames.get(frames.size() - 1), true); } for (DesktopViewListener listener : listeners) { listener.ViewClosed((DesktopView) frame); } frame.removeComponentListener(frameListener); frame.removeInternalFrameListener(this); } @Override public void internalFrameIconified(InternalFrameEvent e) { } @Override public void internalFrameDeiconified(InternalFrameEvent e) { } @Override public void internalFrameActivated(InternalFrameEvent e) { JInternalFrame frame = e.getInternalFrame(); if (frame instanceof FramesView) { setSelected((FramesView) frame, true); JButton b = buttons.get(frame); if (b != null) { b.setSelected(true); } } for (DesktopViewListener listener : listeners) { listener.ViewOpened((DesktopView) frame); } } @Override public void internalFrameDeactivated(InternalFrameEvent e) { JInternalFrame frame = e.getInternalFrame(); if (frame instanceof FramesView) { JButton b = buttons.get(frame); if (b != null) { b.setSelected(false); } } } public void componentResized(ComponentEvent e) { resizeDesktop(); } public void componentMoved(ComponentEvent e) { } public void componentShown(ComponentEvent e) { resizeDesktop(); } public void componentHidden(ComponentEvent e) { resizeDesktop(); } @Override public Container getWorkspace() { return container; } @Override public DesktopView newDesktopView(TaskGraphPanel panel) { FramesView frame = new FramesView(panel); frame.addInternalFrameListener(this); frame.setBounds(offsetX * (frames.size() + 1), offsetY * (frames.size() + 1), 400, 300); frame.pack(); setSize(frame); frames.add(frame); String name = panel.getTaskGraph().getToolName(); if (name.length() > 16) { name = name.substring(0, 13) + "..."; } for (JButton button : buttons.values()) { button.setSelected(false); } JButton b = new JButton(name); b.setSelected(true); b.addActionListener(new ButtonListener()); buttons.put(frame, b); butpanel.add(b); resizeDesktop(); frame.addComponentListener(frameListener); desktop.add(frame); frame.setVisible(true); return frame; } private void resizeDesktop() { currMaxX = MIN_D_WIDTH; currMaxY = MIN_D_HEIGHT; if (currMaxX < butpanel.getPreferredSize().width) { currMaxX = butpanel.getPreferredSize().width; } for (FramesView frame : frames) { if (!frame.isMaximum()) { if (frame.getX() + frame.getWidth() > currMaxX) { currMaxX = frame.getX() + frame.getWidth(); } if (frame.getY() + frame.getHeight() > currMaxY) { currMaxY = frame.getY() + frame.getHeight(); } } } desktop.setPreferredSize(new Dimension(currMaxX, currMaxY)); container.revalidate(); } @Override public void remove(DesktopView view) { if (view instanceof FramesView) { ((FramesView) view).doDefaultCloseAction(); desktop.remove((FramesView) view); JButton b = buttons.remove(view); if (b != null) { butpanel.remove(b); butpanel.revalidate(); } resizeDesktop(); } } @Override public DesktopView getTaskgraphViewFor(TaskGraph taskgraph) { for (FramesView frame : frames) { TaskGraphPanel panel = frame.getTaskgraphPanel(); if (panel.getTaskGraph() == taskgraph) { return frame; } } return null; } @Override public void addDesktopViewListener(DesktopViewListener listener) { if (!listeners.contains(listener)) { listeners.add(listener); } } @Override public void removeDesktopViewListener(DesktopViewListener listener) { listeners.remove(listener); } @Override public DesktopView[] getViews() { return frames.toArray(new DesktopView[frames.size()]); } @Override public void setSelected(DesktopView view, boolean sel) { if (view instanceof FramesView) { try { if (sel) { ((FramesView) view).setSelected(true); ((FramesView) view).toFront(); selected = (FramesView) view; } else { // this doesn't change the selected status. ((FramesView) view).setSelected(false); } } catch (PropertyVetoException e) { e.printStackTrace(); } } } @Override public DesktopView getSelected() { return selected; } @Override public DesktopView getDesktopViewFor(TaskGraphPanel panel) { DesktopView[] views = getViews(); for (DesktopView view : views) { if (view.getTaskgraphPanel() == panel) { return view; } } return null; } @Override public String getTitle(DesktopView view) { if (view instanceof FramesView) { return ((FramesView) view).getTitle(); } return null; } @Override public void setTitle(DesktopView view, String title) { if (view instanceof FramesView) { ((FramesView) view).setTitle(title); } } @Override public void desktopRemoved() { for (FramesView frame : frames) { desktop.getDesktopManager().closeFrame(frame); desktop.remove(frame); JButton b = buttons.remove(frame); if (b != null) { butpanel.remove(b); butpanel.revalidate(); } } frames.clear(); listeners.clear(); buttons.clear(); selected = null; } @Override public void desktopAdded() { for (DesktopViewListener listener : listeners) { listener.desktopChanged(this); } } @Override public DesktopView getDropTarget(int x, int y, Component source) { Component target; int landingPosX = x - (desktop.getLocationOnScreen().x - source.getLocationOnScreen().x); int landingPosY = y - (desktop.getLocationOnScreen().y - source.getLocationOnScreen().y); target = desktop.getComponentAt(landingPosX, landingPosY); if (target instanceof DesktopView) { return (DesktopView) target; } return null; } private class ButtonListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { if (e.getSource() instanceof JButton) { for (FramesView frame : buttons.keySet()) { JButton b = buttons.get(frame); if (b == e.getSource()) { setSelected(frame, true); break; } } } } } private class RestrictedDesktopManager extends DefaultDesktopManager { public void dragFrame(JComponent f, int newX, int newY) { if (newX + f.getWidth() > desktop.getWidth()) { newX = desktop.getWidth() - f.getWidth(); } if (newY + f.getHeight() > desktop.getHeight()) { newY = desktop.getHeight() - f.getHeight(); } if (newX < 0) { newX = 0; } if (newY < 0) { newY = 0; } super.dragFrame(f, newX, newY); } public void activateFrame(JInternalFrame f) { if (f == null) { return; } } } private class FrameListener implements ComponentListener { @Override public void componentResized(ComponentEvent e) { } @Override public void componentMoved(ComponentEvent e) { resizeDesktop(); } @Override public void componentShown(ComponentEvent e) { } @Override public void componentHidden(ComponentEvent e) { } } }