/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2012 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 3 for more details. * * You should have received a copy of the GNU General Public License version 3 * along with this work; if not, see http://www.gnu.org/licenses/ * * * Please visit http://neilcsmith.net if you need additional information or * have any questions. */ package net.neilcsmith.praxis.live.pxr.gui; import java.awt.Dimension; import java.awt.LayoutManager; import java.awt.event.ContainerEvent; import java.awt.event.ContainerListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.HashMap; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import net.miginfocom.swing.MigLayout; import net.neilcsmith.praxis.core.ControlAddress; import net.neilcsmith.praxis.core.IllegalRootStateException; import net.neilcsmith.praxis.core.Lookup; import net.neilcsmith.praxis.gui.BindingContext; import net.neilcsmith.praxis.gui.ControlBinding.Adaptor; import net.neilcsmith.praxis.gui.GuiContext; import net.neilcsmith.praxis.gui.Keys; import net.neilcsmith.praxis.impl.AbstractSwingRoot; import net.neilcsmith.praxis.impl.InstanceLookup; import net.neilcsmith.praxis.impl.RootState; /** * * @author Neil C Smith */ public class DockableGuiRoot extends AbstractSwingRoot { private final static Map<String, DockableGuiRoot> REGISTRY = new HashMap<String, DockableGuiRoot>(); private JFrame frame; // private JScrollPane scrollPane; private JPanel container; private MigLayout layout; private LayoutChangeListener layoutListener; private Bindings bindings; private Context context; private Lookup lookup; private GuiEditor activeEditor; public DockableGuiRoot() { // bindingCache = new HashMap<ControlAddress, DefaultBindingControl>(); } @Override protected void setup() { frame = new JFrame(); frame.setTitle("PraxisLIVE: " + getAddress()); // frame.setSize(150, 50); frame.setMinimumSize(new Dimension(150, 50)); frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { try { if (activeEditor == null) { setIdle(); } } catch (IllegalRootStateException ex) { Logger.getLogger(DockableGuiRoot.class.getName()).log(Level.SEVERE, null, ex); } } }); // frame.getContentPane().setLayout(new MigLayout("fill", "[fill, grow]")); layout = new MigLayout("", "[fill]"); container = new JPanel(layout); container.addContainerListener(new ChildrenListener()); container.putClientProperty(Keys.Address, getAddress()); layoutListener = new LayoutChangeListener(); // frame.getContentPane().add(new JScrollPane(container), "grow, push"); frame.getContentPane().add(new JScrollPane(container)); REGISTRY.put(getAddress().getRootID(), this); } @Override public Lookup getLookup() { if (lookup == null) { bindings = new Bindings(); context = new Context(); lookup = InstanceLookup.create(super.getLookup(), bindings, context); } return lookup; } @Override protected void starting() { super.starting(); Utils.enableAll(container); if (activeEditor == null) { frame.pack(); frame.setVisible(true); } } @Override protected void stopping() { super.stopping(); Utils.disableAll(container); if (activeEditor == null) { frame.setVisible(false); } } @Override protected void dispose() { super.dispose(); if (activeEditor != null) { activeEditor.removeRootPanel(container); activeEditor = null; } frame.setVisible(false); frame.dispose(); REGISTRY.values().remove(this); } void requestConnect(GuiEditor editor) { if (editor == activeEditor) { return; } if (activeEditor != null) { activeEditor.removeRootPanel(container); activeEditor = null; } else { frame.setVisible(false); container.getParent().remove(container); frame.getContentPane().removeAll(); } activeEditor = editor; editor.addRootPanel(container); if (getState() != RootState.ACTIVE_RUNNING) { Utils.disableAll(container); } } void requestDisconnect(GuiEditor editor) { if (activeEditor == editor) { editor.removeRootPanel(container); activeEditor = null; frame.getContentPane().add(new JScrollPane(container)); if (getState() == RootState.ACTIVE_RUNNING) { frame.pack(); frame.setVisible(true); frame.requestFocus(); frame.toFront(); } } } static DockableGuiRoot find(String id) { return REGISTRY.get(id); } private class Bindings extends BindingContext { @Override public void bind(ControlAddress address, Adaptor adaptor) { GuiHelper.getDefault().bind(address, adaptor); } @Override public void unbind(Adaptor adaptor) { GuiHelper.getDefault().unbind(adaptor); } } private class Context extends GuiContext { @Override public JComponent getContainer() { return container; } } private void updateLayout(JComponent child) { if (child != null) { layout.setComponentConstraints(child, child.getClientProperty(Keys.LayoutConstraint)); } container.revalidate(); container.repaint(); } private class ChildrenListener implements ContainerListener { @Override public void componentAdded(ContainerEvent e) { if (e.getChild() instanceof JComponent) { JComponent child = (JComponent) e.getChild(); child.addPropertyChangeListener( Keys.LayoutConstraint, layoutListener); updateLayout(child); } } @Override public void componentRemoved(ContainerEvent e) { if (e.getChild() instanceof JComponent) { ((JComponent) e.getChild()).removePropertyChangeListener( Keys.LayoutConstraint, layoutListener); } updateLayout(null); } } private class LayoutChangeListener implements PropertyChangeListener { public void propertyChange(PropertyChangeEvent evt) { if (evt.getSource() instanceof JComponent) { JComponent comp = (JComponent) evt.getSource(); LayoutManager lm = container.getLayout(); if (lm instanceof MigLayout) { ((MigLayout) lm).setComponentConstraints(comp, evt.getNewValue()); container.revalidate(); } } } } }