diff --git a/dockingcore/pom.xml b/dockingcore/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..183b542861c10662106cd0f1eac8070181eace0a --- /dev/null +++ b/dockingcore/pom.xml @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" + xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <artifactId>super-pom-java</artifactId> + <groupId>fr.soleil</groupId> + <version>RELEASE</version> + </parent> + + <groupId>fr.soleil.lib</groupId> + <artifactId>DockingCore</artifactId> + <version>0.0.1-SNAPSHOT</version> + + <name>Docking Core</name> + <description>A project that defines some common abstractions in docking</description> + + <developers> + <developer> + <id>girardot</id> + <name>Raphaël GIRARDOT</name> + <email>raphael.girardot@synchrotron-soleil.fr</email> + <organization>SOLEIL</organization> + <organizationUrl>http://www.synchrotron-soleil.fr</organizationUrl> + <roles> + <role>Manager</role> + </roles> + <timezone>1</timezone> + </developer> + <developer> + <id>viguier</id> + <name>Grégory VIGUIER</name> + <email>gregory.viguier@synchrotron-soleil.fr</email> + <organization>SOLEIL</organization> + <organizationUrl>http://www.synchrotron-soleil.fr</organizationUrl> + <roles> + <role>Java Developer</role> + </roles> + <timezone>1</timezone> + </developer> + </developers> + + <scm> + <connection>scm:svn:https://svn.code.sf.net/p/comete/code/trunk/DockingCore</connection> + <developerConnection>scm:svn:https://svn.code.sf.net/p/comete/code/trunk/DockingCore</developerConnection> + <url>https://svn.code.sf.net/p/comete/code/trunk/DockingCore</url> + </scm> + + <build> + <plugins> + <plugin> + <artifactId>maven-resources-plugin</artifactId> + <configuration> + <encoding>UTF-8</encoding> + </configuration> + </plugin> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <encoding>UTF-8</encoding> + </configuration> + </plugin> + </plugins> + </build> + + <dependencies> + <dependency> + <groupId>org.swinglabs</groupId> + <artifactId>swingx</artifactId> + </dependency> + </dependencies> + +</project> diff --git a/dockingcore/src/main/java/fr/soleil/docking/ADockingManager.java b/dockingcore/src/main/java/fr/soleil/docking/ADockingManager.java new file mode 100644 index 0000000000000000000000000000000000000000..38790bdacbcc6e22fd526c0aaf5a5ea4dd76832e --- /dev/null +++ b/dockingcore/src/main/java/fr/soleil/docking/ADockingManager.java @@ -0,0 +1,179 @@ +package fr.soleil.docking; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.File; +import java.util.List; +import java.util.prefs.Preferences; + +import javax.swing.Action; +import javax.swing.JComponent; + +import fr.soleil.docking.action.SaveDefaultPerspertiveAction; +import fr.soleil.docking.exception.DockingException; +import fr.soleil.docking.perspective.IPerspective; +import fr.soleil.docking.perspective.IPerspectiveFactory; +import fr.soleil.docking.view.IViewFactory; + +/** + * A class that prepares docking. Obtain your RootWindow from this class. + * + * @author HARDION + * @author GIRARDOT + */ +public abstract class ADockingManager implements PropertyChangeListener { + + private boolean automaticallySavePerspective = true; + + public boolean isAutomaticallySavePerspective() { + return automaticallySavePerspective; + } + + public void setAutomaticallySavePerspective(boolean automaticallySavePerspective) { + this.automaticallySavePerspective = automaticallySavePerspective; + } + + protected IPerspectiveFactory perspectiveFactory = null; + protected IViewFactory viewFactory = null; + + public ADockingManager(IViewFactory viewFactory, IPerspectiveFactory perspectiveFactory) { + this.viewFactory = viewFactory; + this.viewFactory.addPropertyChangeListener(this); + this.perspectiveFactory = perspectiveFactory; + this.perspectiveFactory.addPropertyChangeListener(this); + this.getDockingArea(); + try { + this.resetLayout(); + } catch (DockingException e) { + e.printStackTrace(); + } + } + + public List<Action> getActionList() { + List<Action> result = null; + if (viewFactory != null) { + result = viewFactory.getActionList(); + } + if (Boolean.getBoolean("DEBUG")) { + result.add(new SaveDefaultPerspertiveAction(this)); + } + return result; + } + + /** + * Returns this {@link ADockingManager}'s main docking area + * + * @return A {@link JComponent} + */ + public abstract JComponent getDockingArea(); + + /** + * Creates a new docking area + * + * @return A {@link JComponent} + */ + public abstract JComponent createNewDockingArea(); + + /** + * Returns the perspective factory + * + * @return The perspective factory + */ + public IPerspectiveFactory getPerspectiveFactory() { + return perspectiveFactory; + } + + /** + * Returns the view factory + * + * @return The view factory + */ + public IViewFactory getViewFactory() { + return viewFactory; + } + + public void loadPreferences(Preferences prefs) throws DockingException { + this.perspectiveFactory.loadPreferences(prefs); + this.viewFactory.loadPreferences(prefs); + this.loadPerspective(perspectiveFactory.getSelectedPerspective()); + } + + public void resetLayout() throws DockingException { + loadPerspective(perspectiveFactory.getDefault()); + } + + /** + * @param is + */ + public abstract void loadPerspective(IPerspective perspective) throws DockingException; + + public void savePreferences(Preferences prefs) throws DockingException { + // Save current Perspective + this.savePerspective(this.perspectiveFactory.getSelectedPerspective()); + + // Save Preferences of perspective Factory + this.perspectiveFactory.savePreferences(prefs); + + // Save Preferences of Views + this.viewFactory.savePreferences(prefs); + + } + + /** + * @param perspective + * @param out + * @throws DockingException + */ + protected abstract void savePerspective(IPerspective perspective) throws DockingException; + + public void saveDefault(File file) throws DockingException { + this.savePerspective(this.perspectiveFactory.getSelectedPerspective()); + this.perspectiveFactory.saveSelected(file); + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getSource().equals(perspectiveFactory)) { + if (evt.getPropertyName().equals(IPerspectiveFactory.SELECTED_PERSPECTIVE)) { + IPerspective oldd = (IPerspective) evt.getOldValue(); + IPerspective neww = (IPerspective) evt.getNewValue(); + try { + if (automaticallySavePerspective) { + this.savePerspective(oldd); + } + this.loadPerspective(neww); + } catch (DockingException e) { + e.printStackTrace(); + } + } + } else if (evt.getSource().equals(viewFactory)) { + if (evt.getPropertyName().equals(IViewFactory.VIEWS)) { + this.updateViews(evt); + } + } + + } + + protected abstract void updateViews(PropertyChangeEvent evt); + + public void saveSelectedPerspective() throws DockingException { + this.savePerspective(this.perspectiveFactory.getSelectedPerspective()); + } + + /** + * Enable the docking or not If the docking is disable, the inherit class must disable all + * functionality of the docking. I must be comparable to a JPanel composed by JtabbedPane, + * JSplitPane etc... + * + * @param enabledDocking + */ + public abstract void setEnabledDocking(boolean enabledDocking); + + /** + * Get the Enabled Docking property + * + * @return true if the docking is enabled + */ + public abstract boolean isEnabledDocking(); + +} diff --git a/dockingcore/src/main/java/fr/soleil/docking/action/NewPerspectiveAction.java b/dockingcore/src/main/java/fr/soleil/docking/action/NewPerspectiveAction.java new file mode 100644 index 0000000000000000000000000000000000000000..eabdf290600b619818572a03e2131a08eb10451f --- /dev/null +++ b/dockingcore/src/main/java/fr/soleil/docking/action/NewPerspectiveAction.java @@ -0,0 +1,67 @@ +/* + * Created on 10 juin 2005 + * with Eclipse + */ +package fr.soleil.docking.action; + +import java.awt.event.ActionEvent; + +import javax.swing.AbstractAction; +import javax.swing.JOptionPane; +import javax.swing.KeyStroke; + +import fr.soleil.docking.perspective.IPerspective; +import fr.soleil.docking.perspective.IPerspectiveFactory; + +public class NewPerspectiveAction extends AbstractAction { + + private static final long serialVersionUID = -3295304363885371351L; + + private final IPerspectiveFactory factory; + + public NewPerspectiveAction(IPerspectiveFactory factory) { + super(); + + this.factory = factory; + + // This is an instance initializer; it is executed just after the + // constructor of the superclass is invoked + + // The following values are completely optional + putValue(NAME, "New"); + // Set tool tip text + putValue(SHORT_DESCRIPTION, "New Perspective"); + + // This text is not directly used by any Swing component; + // however, this text could be used in a help system + putValue(LONG_DESCRIPTION, "Adding a new perspective"); + + // Set an icon + // Icon icon = new ImageIcon("icon.gif"); + // putValue(Action.SMALL_ICON, icon); + + // Set a mnemonic character. In most look and feels, this causes the + // specified character to be underlined This indicates that if the component + // using this action has the focus and In some look and feels, this causes + // the specified character in the label to be underlined and + putValue(MNEMONIC_KEY, new Integer(java.awt.event.KeyEvent.VK_N)); + + // Set an accelerator key; this value is used by menu items + putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("ctrl shift N")); + + } + + @Override + public void actionPerformed(ActionEvent e) { + IPerspective current = factory.getSelectedPerspective(); + String result = JOptionPane.showInputDialog("Enter the name of the new perspective"); + if (!result.equals("")) { + IPerspective p = factory.createPerspective(result); + byte[] array = current.getByteArray(); + byte[] copy = (array == null ? null : array.clone()); + p.setByteArray(copy); + factory.setSelectedPerspective(p); + } + } + +} \ No newline at end of file diff --git a/dockingcore/src/main/java/fr/soleil/docking/action/RemovePerspectiveAction.java b/dockingcore/src/main/java/fr/soleil/docking/action/RemovePerspectiveAction.java new file mode 100644 index 0000000000000000000000000000000000000000..7ac13e42707acdc45534681ec4d1cfdb50161b54 --- /dev/null +++ b/dockingcore/src/main/java/fr/soleil/docking/action/RemovePerspectiveAction.java @@ -0,0 +1,64 @@ +/* + * Created on 10 juin 2005 + * with Eclipse + */ +package fr.soleil.docking.action; + +import java.awt.event.ActionEvent; + +import javax.swing.AbstractAction; +import javax.swing.JOptionPane; +import javax.swing.KeyStroke; + +import fr.soleil.docking.perspective.IPerspective; +import fr.soleil.docking.perspective.IPerspectiveFactory; + +public class RemovePerspectiveAction extends AbstractAction { + + private static final long serialVersionUID = 4431356413525394103L; + + private final IPerspectiveFactory factory; + + public RemovePerspectiveAction(IPerspectiveFactory factory) { + super(); + + this.factory = factory; + + // This is an instance initializer; it is executed just after the + // constructor of the superclass is invoked + + // The following values are completely optional + putValue(NAME, "Remove"); + // Set tool tip text + putValue(SHORT_DESCRIPTION, "Remove Perspective"); + + // This text is not directly used by any Swing component; + // however, this text could be used in a help system + putValue(LONG_DESCRIPTION, "Removing a perspective"); + + // Set an icon + // Icon icon = new ImageIcon("icon.gif"); + // putValue(Action.SMALL_ICON, icon); + + // Set a mnemonic character. In most look and feels, this causes the + // specified character to be underlined This indicates that if the component + // using this action has the focus and In some look and feels, this causes + // the specified character in the label to be underlined and + putValue(MNEMONIC_KEY, new Integer(java.awt.event.KeyEvent.VK_R)); + + // Set an accelerator key; this value is used by menu items + putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("ctrl shift R")); + + } + + @Override + public void actionPerformed(ActionEvent e) { + IPerspective result = (IPerspective) JOptionPane.showInputDialog(null, "Select the perspective to remove", + "Remove perspective", JOptionPane.PLAIN_MESSAGE, null, factory.getPerspectives(), + factory.getSelectedPerspective()); + if (result != null) { + factory.removePerspective(result); + } + } + +} \ No newline at end of file diff --git a/dockingcore/src/main/java/fr/soleil/docking/action/SaveDefaultPerspertiveAction.java b/dockingcore/src/main/java/fr/soleil/docking/action/SaveDefaultPerspertiveAction.java new file mode 100644 index 0000000000000000000000000000000000000000..2f95f56e2f00998f09c1d4ff0ed4662451b7a932 --- /dev/null +++ b/dockingcore/src/main/java/fr/soleil/docking/action/SaveDefaultPerspertiveAction.java @@ -0,0 +1,74 @@ +/* + * Created on 10 juin 2005 + * with Eclipse + */ +package fr.soleil.docking.action; + +import java.awt.event.ActionEvent; +import java.io.File; + +import javax.swing.AbstractAction; +import javax.swing.JFileChooser; + +import org.jdesktop.swingx.JXErrorPane; + +import fr.soleil.docking.ADockingManager; + +public class SaveDefaultPerspertiveAction extends AbstractAction { + + private static final long serialVersionUID = -5058889377558638684L; + + private final ADockingManager dockingManager; + + public SaveDefaultPerspertiveAction(ADockingManager manager) { + super(); + this.dockingManager = manager; + // This is an instance initializer; it is executed just after the + // constructor of the superclass is invoked + + // The following values are completely optional + putValue(NAME, "Save Default"); + // Set tool tip text + putValue(SHORT_DESCRIPTION, "Save this perspective to file system"); + + // This text is not directly used by any Swing component; + // however, this text could be used in a help system + putValue(LONG_DESCRIPTION, "Save this perspective to file system"); + + // Set an icon + // Icon icon = new ImageIcon("icon.gif"); + // putValue(Action.SMALL_ICON, view.getIcon()); + + // Set a mnemonic character. In most look and feels, this causes the + // specified character to be underlined This indicates that if the component + // using this action has the focus and In some look and feels, this causes + // the specified character in the label to be underlined and + // putValue(Action.MNEMONIC_KEY, new Integer(java.awt.event.KeyEvent.VK_N)); + + // Set an accelerator key; this value is used by menu items + // putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("alt shift N")); + + } + + @Override + public void actionPerformed(ActionEvent evt) { + JFileChooser chooser = new JFileChooser(); + + if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { + File file = chooser.getSelectedFile(); + try { + if (!file.exists()) + file.createNewFile(); + dockingManager.saveDefault(file); + } catch (Exception e) { + JXErrorPane.showDialog(e); + } + } + } + + @Override + public boolean isEnabled() { + return true; + } + +} \ No newline at end of file diff --git a/dockingcore/src/main/java/fr/soleil/docking/action/SelectPerspectiveAction.java b/dockingcore/src/main/java/fr/soleil/docking/action/SelectPerspectiveAction.java new file mode 100644 index 0000000000000000000000000000000000000000..ecbf614ebdff858f99eee9c01f089ae9bc330343 --- /dev/null +++ b/dockingcore/src/main/java/fr/soleil/docking/action/SelectPerspectiveAction.java @@ -0,0 +1,77 @@ +/* + * Created on 10 juin 2005 + * with Eclipse + */ +package fr.soleil.docking.action; + +import java.awt.event.ActionEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.AbstractAction; +import javax.swing.KeyStroke; + +import fr.soleil.docking.perspective.IPerspective; +import fr.soleil.docking.perspective.IPerspectiveFactory; + +public class SelectPerspectiveAction extends AbstractAction implements PropertyChangeListener { + + private static final long serialVersionUID = 6402682388656946588L; + + private final IPerspectiveFactory factory; + private final IPerspective perspective; + + public SelectPerspectiveAction(IPerspectiveFactory factory, IPerspective perspective) { + super(); + + this.factory = factory; + this.factory.addPropertyChangeListener(this); + this.perspective = perspective; + + // This is an instance initializer; it is executed just after the + // constructor of the superclass is invoked + + // The following values are completely optional + putValue(NAME, perspective.getName()); + // Set tool tip text + putValue(SHORT_DESCRIPTION, "Select " + perspective.getName()); + + // This text is not directly used by any Swing component; + // however, this text could be used in a help system + putValue(LONG_DESCRIPTION, "Select " + perspective.getName() + " as current perspective"); + + // Set an icon + // Icon icon = new ImageIcon("icon.gif"); + // putValue(Action.SMALL_ICON, icon); + + // Set a mnemonic character. In most look and feels, this causes the + // specified character to be underlined This indicates that if the component + // using this action has the focus and In some look and feels, this causes + // the specified character in the label to be underlined and + putValue(MNEMONIC_KEY, new Integer(java.awt.event.KeyEvent.VK_N)); + + // Set an accelerator key; this value is used by menu items + putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("ctrl shift N")); + + // Set selected + putValue(SELECTED_KEY, this.factory.getSelectedPerspective() == this.perspective); + + } + + @Override + public void actionPerformed(ActionEvent e) { + factory.setSelectedPerspective(perspective); + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getPropertyName().equals(IPerspectiveFactory.SELECTED_PERSPECTIVE)) { + if (evt.getNewValue().equals(this.perspective)) { + putValue(SELECTED_KEY, true); + } else { + putValue(SELECTED_KEY, false); + } + } + } + +} \ No newline at end of file diff --git a/dockingcore/src/main/java/fr/soleil/docking/action/ViewAction.java b/dockingcore/src/main/java/fr/soleil/docking/action/ViewAction.java new file mode 100644 index 0000000000000000000000000000000000000000..803c79318bc946fc9c50e8253ad8dfc58c783f2f --- /dev/null +++ b/dockingcore/src/main/java/fr/soleil/docking/action/ViewAction.java @@ -0,0 +1,59 @@ +package fr.soleil.docking.action; + +import java.awt.event.ActionEvent; + +import javax.swing.AbstractAction; + +import fr.soleil.docking.view.IView; + +public class ViewAction extends AbstractAction { + + private static final long serialVersionUID = 2102313023512752659L; + + private final IView view; + + public ViewAction(IView view) { + super(); + this.view = view; + // This is an instance initializer; it is executed just after the + // constructor of the superclass is invoked + + // The following values are completely optional + putValue(NAME, view.getTitle()); + // Set tool tip text + putValue(SHORT_DESCRIPTION, view.getTitle()); + + // This text is not directly used by any Swing component; + // however, this text could be used in a help system + putValue(LONG_DESCRIPTION, view.getTitle()); + + // Set an icon + // Icon icon = new ImageIcon("icon.gif"); + putValue(SMALL_ICON, view.getIcon()); + + // Set a mnemonic character. In most look and feels, this causes the + // specified character to be underlined This indicates that if the component + // using this action has the focus and In some look and feels, this causes + // the specified character in the label to be underlined and + // putValue(Action.MNEMONIC_KEY, new Integer(java.awt.event.KeyEvent.VK_N)); + + // Set an accelerator key; this value is used by menu items + // putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("alt shift N")); + + } + + @Override + public void actionPerformed(ActionEvent e) { + if (!view.isVisible()) { + view.setVisible(true); + } else { + view.setVisible(false); + } + } + + @Override + public boolean isEnabled() { + return view.isEnabled(); + } + +} \ No newline at end of file diff --git a/dockingcore/src/main/java/fr/soleil/docking/component/PerspectiveMenu.java b/dockingcore/src/main/java/fr/soleil/docking/component/PerspectiveMenu.java new file mode 100644 index 0000000000000000000000000000000000000000..bba0fbb221e29b9edc87391631d4e176dfecaaa7 --- /dev/null +++ b/dockingcore/src/main/java/fr/soleil/docking/component/PerspectiveMenu.java @@ -0,0 +1,82 @@ +package fr.soleil.docking.component; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.List; + +import javax.swing.Action; +import javax.swing.JButton; +import javax.swing.JMenuItem; +import javax.swing.JRadioButtonMenuItem; + +import fr.soleil.docking.action.NewPerspectiveAction; +import fr.soleil.docking.perspective.IPerspectiveFactory; + +public class PerspectiveMenu extends javax.swing.JMenu implements PropertyChangeListener { + + private static final long serialVersionUID = -6492472049072385936L; + + protected IPerspectiveFactory factory; + + public PerspectiveMenu(IPerspectiveFactory factory) { + super(); + this.setText("Perspective"); + this.factory = factory; + factory.addPropertyChangeListener(this); + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getSource() instanceof IPerspectiveFactory) { + if (evt.getPropertyName().equals(IPerspectiveFactory.PERSPECTIVES)) { + + } + } + } + + @Override + public JMenuItem add(Action a) { + if (a instanceof NewPerspectiveAction) { + this.addSeparator(); + } + return super.add(a); + } + + @Override + public void setPopupMenuVisible(boolean flag) { + if (flag) { + this.removeAll(); + List<Action> actions = factory.getActionList(); + for (Action action : actions) { + add(action); + // JRadioButtonMenuItem item = (JRadioButtonMenuItem) this.add(action); + // Boolean b = (Boolean) action.getValue("SELECTED_KEY"); + // if (b != null) { + // item.setSelected(b); + // } + } + } + super.setPopupMenuVisible(flag); + } + + @Override + protected JMenuItem createActionComponent(Action a) { + JMenuItem mi = new JRadioButtonMenuItem() { + private static final long serialVersionUID = -3334691946468856486L; + + @Override + protected PropertyChangeListener createActionPropertyChangeListener(Action a) { + PropertyChangeListener pcl = createActionChangeListener(this); + if (pcl == null) { + pcl = super.createActionPropertyChangeListener(a); + } + return pcl; + } + + }; + mi.setHorizontalTextPosition(JButton.TRAILING); + mi.setVerticalTextPosition(JButton.CENTER); + return mi; + } + +} diff --git a/dockingcore/src/main/java/fr/soleil/docking/exception/DockingException.java b/dockingcore/src/main/java/fr/soleil/docking/exception/DockingException.java new file mode 100644 index 0000000000000000000000000000000000000000..87db8a8be43d9ea3df3251e1a76a1fabc5f3d91a --- /dev/null +++ b/dockingcore/src/main/java/fr/soleil/docking/exception/DockingException.java @@ -0,0 +1,28 @@ +package fr.soleil.docking.exception; + +/** + * An Exception thrown in case of problems with docking + * + * @author girardot + */ +public class DockingException extends Exception { + + private static final long serialVersionUID = 5753611012723925293L; + + public DockingException() { + super(); + } + + public DockingException(String message) { + super(message); + } + + public DockingException(Throwable cause) { + super(cause); + } + + public DockingException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/dockingcore/src/main/java/fr/soleil/docking/perspective/FilePerspective.java b/dockingcore/src/main/java/fr/soleil/docking/perspective/FilePerspective.java new file mode 100644 index 0000000000000000000000000000000000000000..7de39dbe7db800185a3913586db785202804c752 --- /dev/null +++ b/dockingcore/src/main/java/fr/soleil/docking/perspective/FilePerspective.java @@ -0,0 +1,20 @@ +package fr.soleil.docking.perspective; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +public class FilePerspective extends Perspective { + + public FilePerspective(String name, File file) throws IOException { + super(name); + if ((file != null) && (file.isFile())) { + InputStream in = new FileInputStream(file); + if (in != null) { + byteArray = readByteArray(in); + } + } + } + +} diff --git a/dockingcore/src/main/java/fr/soleil/docking/perspective/IPerspective.java b/dockingcore/src/main/java/fr/soleil/docking/perspective/IPerspective.java new file mode 100644 index 0000000000000000000000000000000000000000..a45cd31a407904f58be869a73665b516d8311442 --- /dev/null +++ b/dockingcore/src/main/java/fr/soleil/docking/perspective/IPerspective.java @@ -0,0 +1,22 @@ +package fr.soleil.docking.perspective; + +/** + * Objects that implement this interface should know where to put each dockable component. + * + * @author Hardion + * @author GIRARDOT + */ +public interface IPerspective { + + public String getName(); + + /** + * @return the byteArray + */ + public byte[] getByteArray(); + + /** + * @param byteArray the byteArray to set + */ + public void setByteArray(byte[] byteArray); +} diff --git a/dockingcore/src/main/java/fr/soleil/docking/perspective/IPerspectiveFactory.java b/dockingcore/src/main/java/fr/soleil/docking/perspective/IPerspectiveFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..2b2b389d3e7f28f1c0815be443a9b49c206cd806 --- /dev/null +++ b/dockingcore/src/main/java/fr/soleil/docking/perspective/IPerspectiveFactory.java @@ -0,0 +1,67 @@ +package fr.soleil.docking.perspective; + +import java.beans.PropertyChangeListener; +import java.io.File; +import java.util.List; +import java.util.prefs.Preferences; + +import javax.swing.Action; + +import fr.soleil.docking.exception.DockingException; + +/** + * Factory that manages Perspectives + * + * @author Hardion + * @author GIRARDOT + */ +public interface IPerspectiveFactory { + + public static final String SELECTED_PERSPECTIVE = "selectedPerspective"; + public static final String PERSPECTIVES = "perspectives"; + + /** + * Returns the Perspective associated with this id. + * + * @param id The id of the desired Perspective. + * @return The Perspective associated with this id. + */ + public IPerspective getPerspective(Object id); + + /** + * Returns the selected IPerspective + * + * @return The selected IPerspective + */ + public IPerspective getSelectedPerspective(); + + /** + * Sets the selected IPerspective + * + * @param selectedPerspective The IPerspective to set as selected + */ + public void setSelectedPerspective(IPerspective selectedPerspective); + + public void setSelectedPerspective(String perspective); + + public void loadPreferences(Preferences prefs); + + public void savePreferences(Preferences prefs); + + public List<Action> getActionList(); + + public void saveSelected(File file) throws DockingException; + + public void addPropertyChangeListener(PropertyChangeListener propertyChangeListener); + + public void removePropertyChangeListener(PropertyChangeListener propertyChangeListener); + + public IPerspective getDefault(); + + public IPerspective createPerspective(final String name); + + public IPerspective removePerspective(IPerspective perspective); + + public IPerspective[] getPerspectives(); + +} diff --git a/dockingcore/src/main/java/fr/soleil/docking/perspective/Perspective.java b/dockingcore/src/main/java/fr/soleil/docking/perspective/Perspective.java new file mode 100644 index 0000000000000000000000000000000000000000..8fb7f952d6489c89c4188ebf66439e0a7afdd048 --- /dev/null +++ b/dockingcore/src/main/java/fr/soleil/docking/perspective/Perspective.java @@ -0,0 +1,57 @@ +/** + * + */ +package fr.soleil.docking.perspective; + +import java.io.IOException; +import java.io.InputStream; + +public class Perspective implements IPerspective { + private final String name; + protected byte[] byteArray; + + public Perspective(String name) { + this.name = name; + byteArray = new byte[0]; + } + + @Override + public byte[] getByteArray() { + return byteArray; + } + + @Override + public String getName() { + return name; + } + + @Override + public void setByteArray(byte[] byteArray) { + this.byteArray = byteArray; + } + + @Override + public String toString() { + return this.name; + } + + /** + * Reads a <code>byte</code> array from an {@link InputStream} and returns it + * + * @param in The {@link InputStream} + * @return A <code>byte[]</code> + * @throws IOException If a problem occurred while trying to read the {@link InputStream} + */ + protected byte[] readByteArray(InputStream in) throws IOException { + byte[] result = null; + if (in != null) { + result = new byte[in.available()]; + int length = in.read(result); + if (length != result.length) { + result = null; + } + } + return result; + } + +} \ No newline at end of file diff --git a/dockingcore/src/main/java/fr/soleil/docking/perspective/PerspectiveFactory.java b/dockingcore/src/main/java/fr/soleil/docking/perspective/PerspectiveFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..84d207898b540624ff51f6c7531939a332e5e2de --- /dev/null +++ b/dockingcore/src/main/java/fr/soleil/docking/perspective/PerspectiveFactory.java @@ -0,0 +1,235 @@ +package fr.soleil.docking.perspective; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.File; +import java.io.FileOutputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.prefs.BackingStoreException; +import java.util.prefs.Preferences; + +import javax.swing.Action; + +import fr.soleil.docking.action.NewPerspectiveAction; +import fr.soleil.docking.action.RemovePerspectiveAction; +import fr.soleil.docking.action.SelectPerspectiveAction; +import fr.soleil.docking.exception.DockingException; + +public class PerspectiveFactory implements IPerspectiveFactory { + + private static final String DEFAULT_PERSPECTIVE_NAME = "Default"; + + protected PropertyChangeSupport support; + private final List<IPerspective> perspectives; + private IPerspective selectedPerspective; + private final String defaultPerspectiveName; + + public PerspectiveFactory() { + this(new Perspective(DEFAULT_PERSPECTIVE_NAME)); + } + + public PerspectiveFactory(IPerspective defaultt) { + perspectives = new ArrayList<IPerspective>(1); + defaultPerspectiveName = defaultt.getName(); + perspectives.add(defaultt); + selectedPerspective = defaultt; + support = new PropertyChangeSupport(this); + } + + @Override + public IPerspective createPerspective(final String name) { + IPerspective result = this.getPerspective(name); + if (result == null) { + result = new Perspective(name); + this.add(result); + } + + return result; + } + + /** + * @param e + * @return + * @see java.util.ArrayList#add(java.lang.Object) + */ + public boolean add(IPerspective e) { + boolean result = perspectives.add(e); + if (result) { + support.fireIndexedPropertyChange(PERSPECTIVES, perspectives.indexOf(result), null, result); + } + + return result; + } + + @Override + public IPerspective getPerspective(Object name) { + IPerspective result = null; + for (IPerspective perspective : perspectives) { + if (perspective.getName().equalsIgnoreCase((String) name)) { + result = perspective; + break; + } + } + return result; + } + + @Override + public IPerspective getSelectedPerspective() { + return selectedPerspective; + } + + @Override + public void setSelectedPerspective(IPerspective selectedPerspective) { + if (!this.selectedPerspective.equals(selectedPerspective) && this.perspectives.contains(selectedPerspective)) { + IPerspective old = this.selectedPerspective; + this.selectedPerspective = selectedPerspective; + support.firePropertyChange(SELECTED_PERSPECTIVE, old, this.selectedPerspective); + } + } + + @Override + public void setSelectedPerspective(String perspective) { + setSelectedPerspective(getPerspective(perspective)); + } + + @Override + public void loadPreferences(Preferences prefs) { + Preferences factoryPrefs = prefs.node("PerspectiveFactory"); + Preferences perspectivesPrefs = factoryPrefs.node("Perspectives"); + + String[] keys = new String[0]; + try { + keys = perspectivesPrefs.keys(); + } catch (BackingStoreException e1) { + e1.printStackTrace(); + } + + byte[] ko = new byte[0]; + byte[] layout = null; + IPerspective perspective = null; + for (int i = 0; i < keys.length; i++) { + perspective = this.getPerspective(keys[i]); + if (perspective == null) { + perspective = this.createPerspective(keys[i]); + } + layout = perspectivesPrefs.getByteArray(keys[i], ko); + if (layout != ko) { + perspective.setByteArray(layout); + } + } + + // get the value of + String selected = factoryPrefs.get("selected", selectedPerspective.getName()); + this.setSelectedPerspective(this.getPerspective(selected)); + + } + + @Override + public void savePreferences(Preferences prefs) { + Preferences factoryPrefs = prefs.node("PerspectiveFactory"); + Preferences perspectivesPrefs = factoryPrefs.node("Perspectives"); + + try { + factoryPrefs.clear(); + perspectivesPrefs.clear(); + } catch (BackingStoreException e1) { + e1.printStackTrace(); + } + factoryPrefs.put("selected", selectedPerspective.getName()); + for (IPerspective perspective : perspectives) { + + perspectivesPrefs.putByteArray(perspective.getName(), perspective.getByteArray()); + } + } + + @Override + public List<Action> getActionList() { + List<Action> result = new ArrayList<Action>(1); + + for (IPerspective perspective : perspectives) { + result.add(new SelectPerspectiveAction(this, perspective)); + } + + result.add(new NewPerspectiveAction(this)); + result.add(new RemovePerspectiveAction(this)); + + return result; + } + + @Override + public void saveSelected(File file) throws DockingException { + DockingException dockingException = null; + FileOutputStream out = null; + try { + out = new FileOutputStream(file); + try { + out.write(selectedPerspective.getByteArray()); + } catch (Exception e) { + if (dockingException == null) { + dockingException = new DockingException("Error during file writing", e); + } + } finally { + try { + out.close(); + } catch (Exception e) { + if (dockingException == null) { + dockingException = new DockingException("Error while releasing file access", e); + } + } + } + } catch (Exception e) { + if (dockingException == null) { + dockingException = new DockingException("Error during file access", e); + } + } + if (dockingException != null) { + throw dockingException; + } + } + + /** + * @param listener + * @see java.beans.PropertyChangeSupport#addPropertyChangeListener(java.beans.PropertyChangeListener) + */ + @Override + public void addPropertyChangeListener(PropertyChangeListener listener) { + support.addPropertyChangeListener(listener); + } + + /** + * @param listener + * @see java.beans.PropertyChangeSupport#removePropertyChangeListener(java.beans.PropertyChangeListener) + */ + @Override + public void removePropertyChangeListener(PropertyChangeListener listener) { + support.removePropertyChangeListener(listener); + } + + @Override + public IPerspective getDefault() { + + return this.getPerspective(defaultPerspectiveName); + } + + @Override + public IPerspective[] getPerspectives() { + return perspectives.toArray(new IPerspective[perspectives.size()]); + } + + @Override + public IPerspective removePerspective(final IPerspective p) { + int index = perspectives.indexOf(p); + if (index != -1 && !(p instanceof ResourcePerspective) && !p.getName().equals(defaultPerspectiveName)) { + // Exist and it's not the default perspective + perspectives.remove(index); + support.fireIndexedPropertyChange(PERSPECTIVES, index, p, null); + } + return p; + } + + public IPerspective removePerspective(final String name) { + return this.removePerspective(this.getPerspective(name)); + } + +} diff --git a/dockingcore/src/main/java/fr/soleil/docking/perspective/ResourcePerspective.java b/dockingcore/src/main/java/fr/soleil/docking/perspective/ResourcePerspective.java new file mode 100644 index 0000000000000000000000000000000000000000..bf2d5b641bc6053e17d43ff6a10eb366f36c1a33 --- /dev/null +++ b/dockingcore/src/main/java/fr/soleil/docking/perspective/ResourcePerspective.java @@ -0,0 +1,16 @@ +package fr.soleil.docking.perspective; + +import java.io.IOException; +import java.io.InputStream; + +public class ResourcePerspective extends Perspective { + + public ResourcePerspective(String name, String resource) throws IOException { + super(name); + InputStream in = ResourcePerspective.this.getClass().getResourceAsStream(resource); + if (in != null) { + byteArray = readByteArray(in); + } + } + +} diff --git a/dockingcore/src/main/java/fr/soleil/docking/view/IView.java b/dockingcore/src/main/java/fr/soleil/docking/view/IView.java new file mode 100644 index 0000000000000000000000000000000000000000..a69fbb55b250c6c438cfbf61ebbde1dd772d98d1 --- /dev/null +++ b/dockingcore/src/main/java/fr/soleil/docking/view/IView.java @@ -0,0 +1,100 @@ +package fr.soleil.docking.view; + +import java.awt.Color; +import java.awt.Component; + +import javax.swing.Icon; + +/** + * A dynamically created view containing an id. + * + * @author Hardion + * @author GIRARDOT + */ +public interface IView { + + /** + * Returns the view id. + * + * @return the view id + */ + public Object getId(); + + /** + * @return the enabled + */ + public boolean isEnabled(); + + /** + * @param enabled the enabled to set + */ + public void setEnabled(boolean enabled); + + /** + * @return the enabled + */ + public boolean isVisible(); + + /** + * @param enabled the enabled to set + */ + public void setVisible(boolean visible); + + /** + * @return the title + */ + public String getTitle(); + + /** + * @return the icon + */ + public Icon getIcon(); + + /** + * @return the component + */ + public Component getComponent(); + + /** + * Returns this {@link IView}'s background {@link Color} + * + * @return A {@link Color} + */ + public Color getViewBackground(); + + /** + * Sets the background {@link Color} of this {@link IView} + * + * @param bg The background {@link Color} to set + */ + public void setViewBackground(Color bg); + + /** + * Returns this {@link IView}'s foreground {@link Color} + * + * @return A {@link Color} + */ + public Color getViewForeground(); + + /** + * Sets the foreground {@link Color} of this {@link IView} + * + * @param fg The foreground {@link Color} to set + */ + public void setViewForeground(Color fg); + + /** + * Sets the {@link IView} closable or not. + * + * @param closable The boolean to set. + */ + public void setClosable(boolean closable); + + /** + * Add an {@link IViewListener} to the view.. + * + * @param listener The {@link IViewListener} to add. + */ + public void addViewListener(IViewListener listener); + +} diff --git a/dockingcore/src/main/java/fr/soleil/docking/view/IViewFactory.java b/dockingcore/src/main/java/fr/soleil/docking/view/IViewFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..d2baff9e081ac55f0fc87e9a08896c36d538b7d6 --- /dev/null +++ b/dockingcore/src/main/java/fr/soleil/docking/view/IViewFactory.java @@ -0,0 +1,89 @@ +package fr.soleil.docking.view; + +import java.beans.PropertyChangeListener; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Collection; +import java.util.List; +import java.util.prefs.Preferences; + +import javax.swing.Action; + +/** + * A factory that takes care of initializing dockable components and transmitting models. + * + * @author Hardion + * @author GIRARDOT + */ +public interface IViewFactory { + + public static final String VIEWS = "views"; + + /** + * Returns the DynamicView associated with this id (creates the + * DynamicView). + * + * @param id + * The id of the desired DynamicView + * @return The DynamicView associated with this id + */ + public IView getView(Object id); + + public Collection<IView> getViews(); + + /** + * Returns the ActionList + * + * @param id + * The id of the desired DynamicView + * @return The DynamicView associated with this id + */ + public List<Action> getActionList(); + + /** + * Saves preferences + * + * @param prefs preferences in which to save + */ + public void savePreferences(Preferences prefs); + + /** + * Loads preferences + * + * @param prefs preferences to load + */ + public void loadPreferences(Preferences prefs); + + public int size(); + + /** + * @param listener + * @see java.beans.PropertyChangeSupport#addPropertyChangeListener(java.beans.PropertyChangeListener) + */ + public void addPropertyChangeListener(PropertyChangeListener listener); + + /** + * @param listener + * @see java.beans.PropertyChangeSupport#removePropertyChangeListener(java.beans.PropertyChangeListener) + */ + public void removePropertyChangeListener(PropertyChangeListener listener); + + public Object readViewId(ObjectInputStream in) throws IOException; + + public void writeViewId(Object id, ObjectOutputStream out) throws IOException; + + public IView addView(IView view); + + public boolean removeView(IView view); + + /** + * Removes an {@link IView}, determined by an id, from list and from the + * docking area. + * + * @param id The id of the {@link IView} to remove. + * @return The removed {@link IView} if such an {@link IView} existed and + * was successfully removed, <code>null</code> otherwise. + */ + public IView removeView(Object id); +} diff --git a/dockingcore/src/main/java/fr/soleil/docking/view/IViewListener.java b/dockingcore/src/main/java/fr/soleil/docking/view/IViewListener.java new file mode 100644 index 0000000000000000000000000000000000000000..25dd4eb17c1fb4bdf8c0ff62c74ee1fe9ef7f37d --- /dev/null +++ b/dockingcore/src/main/java/fr/soleil/docking/view/IViewListener.java @@ -0,0 +1,7 @@ +package fr.soleil.docking.view; + +public interface IViewListener { + + public void viewClosed(); + +} diff --git a/dockingcore/src/main/java/fr/soleil/docking/view/ViewFactory.java b/dockingcore/src/main/java/fr/soleil/docking/view/ViewFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..513458f8ff71d98583f30bc2bb6fed0fa3217d74 --- /dev/null +++ b/dockingcore/src/main/java/fr/soleil/docking/view/ViewFactory.java @@ -0,0 +1,152 @@ +package fr.soleil.docking.view; + +import java.awt.Component; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.prefs.Preferences; + +import javax.swing.Action; + +import fr.soleil.docking.action.ViewAction; + +public class ViewFactory implements IViewFactory { + + protected final Collection<IView> views; + protected final PropertyChangeSupport support; + + public ViewFactory() { + super(); + views = Collections.newSetFromMap(new ConcurrentHashMap<IView, Boolean>()); + support = new PropertyChangeSupport(this); + } + + @Override + public IView getView(Object id) { + IView result = null; + for (IView view : views) { + if (view.getId().equals(id)) { + result = view; + break; + } + } + return result; + } + + public Component getViewComponent(Object id) { + Component component; + IView view = getView(id); + if (view == null) { + component = null; + } else { + component = view.getComponent(); + } + return component; + } + + protected void setViewEnabled(Object id, boolean enabled) { + IView view = getView(id); + if (view != null) { + view.setVisible(enabled); + view.setEnabled(enabled); + } + } + + @Override + public void loadPreferences(Preferences prefs) { + // Does nothing in particular. If you expect something to be done, you should extend this class and override + // this method + } + + @Override + public void savePreferences(Preferences prefs) { + // Does nothing in particular. If you expect something to be done, you should extend this class and override + // this method + } + + @Override + public IView addView(IView view) { + if (views.add(view)) { + support.firePropertyChange(VIEWS, null, view); + } else { + view = null; + } + return view; + } + + @Override + public IView removeView(Object id) { + IView toRemove = getView(id); + if (!removeView(toRemove)) { + toRemove = null; + } + return toRemove; + } + + @Override + public boolean removeView(IView view) { + boolean result; + if (view == null) { + result = false; + } else { + result = views.remove(view); + if (result) { + support.firePropertyChange(VIEWS, view, null); + } + } + return result; + } + + @Override + public List<Action> getActionList() { + List<Action> result = new ArrayList<Action>(views.size()); + for (IView view : views) { + result.add(new ViewAction(view)); + } + return result; + } + + @Override + public int size() { + return views.size(); + } + + @Override + public Collection<IView> getViews() { + return views; + } + + @Override + public void addPropertyChangeListener(PropertyChangeListener listener) { + support.addPropertyChangeListener(listener); + } + + @Override + public void removePropertyChangeListener(PropertyChangeListener listener) { + support.removePropertyChangeListener(listener); + } + + @Override + public Object readViewId(ObjectInputStream in) throws IOException { + Object id = null; + try { + id = in.readObject(); + } catch (ClassNotFoundException e) { + throw new IOException(e); + } + return id; + } + + @Override + public void writeViewId(Object id, ObjectOutputStream out) throws IOException { + out.writeObject(id); + } + +} \ No newline at end of file