/** * */ package cz.cuni.mff.peckam.java.origamist.gui.common; import java.awt.Component; import java.awt.Container; import java.awt.Frame; import java.awt.GridLayout; import java.awt.event.ContainerEvent; import java.awt.event.ContainerListener; import java.awt.event.KeyListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.text.MessageFormat; import java.util.Locale; import java.util.ResourceBundle; import java.util.concurrent.Callable; import java.util.prefs.BackingStoreException; import javax.swing.ImageIcon; import javax.swing.JApplet; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.transform.TransformerConfigurationException; import org.apache.log4j.BasicConfigurator; import org.apache.log4j.Level; import org.apache.log4j.Logger; import cz.cuni.mff.peckam.java.origamist.configuration.Configuration; import cz.cuni.mff.peckam.java.origamist.configuration.ConfigurationManagerImpl; import cz.cuni.mff.peckam.java.origamist.jaxb.BindingsManager; import cz.cuni.mff.peckam.java.origamist.jaxb.ObjectFactoryConfigurator; import cz.cuni.mff.peckam.java.origamist.jaxb.SchemaInfo; import cz.cuni.mff.peckam.java.origamist.logging.GUIAppender; import cz.cuni.mff.peckam.java.origamist.model.ObjectFactory; import cz.cuni.mff.peckam.java.origamist.services.HashCodeAndEqualsHelperImpl; import cz.cuni.mff.peckam.java.origamist.services.JAXBListingHandler; import cz.cuni.mff.peckam.java.origamist.services.JAXBOrigamiHandler; import cz.cuni.mff.peckam.java.origamist.services.ServiceLocator; import cz.cuni.mff.peckam.java.origamist.services.TooltipFactory; import cz.cuni.mff.peckam.java.origamist.services.interfaces.ConfigurationManager; import cz.cuni.mff.peckam.java.origamist.services.interfaces.HashCodeAndEqualsHelper; import cz.cuni.mff.peckam.java.origamist.services.interfaces.ListingHandler; import cz.cuni.mff.peckam.java.origamist.services.interfaces.OrigamiHandler; /** * Common GUI elements for both the viewer and editor. * * Provided properties: * appMessages (protected property) * * @author Martin Pecka */ public abstract class CommonGui extends JApplet { private static final long serialVersionUID = -9021667515698972438L; /** * The localized messages for the common GUI classes. */ protected ResourceBundle appMessages = null; /** * The common message formater that can be used over the GUI. It has its locale set to the configured one */ protected MessageFormat format = null; @Override public void init() { // make the frame resizable if the applet is run using JWS/JNLP (because at default it is run as a fixed-size // window) Component parent = getTopmostComponent(); if (parent instanceof Frame) { Frame frame = ((Frame) parent); if (!frame.isResizable()) { frame.setResizable(true); // see http://forums.oracle.com/forums/thread.jspa?threadID=2152885&stqc=true frame.setLayout(new GridLayout()); } frame.setIconImage(new ImageIcon(getClass().getResource("/resources/images/icon_64.png")).getImage()); } super.init(); // to allow transparent JCanvas3D background System.setProperty("j3d.transparentOffScreen", "true"); setupLoggersBeforeServices(); registerServices(); setupLoggers(); final Configuration config = ServiceLocator.get(ConfigurationManager.class).get(); final String bundleName = "application"; appMessages = ResourceBundle.getBundle(bundleName, config.getLocale()); format = new MessageFormat("", config.getLocale()); config.addPropertyChangeListener("locale", new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { if (!appMessages.getLocale().equals(evt.getNewValue())) { ResourceBundle oldMessages = appMessages; appMessages = ResourceBundle.getBundle(bundleName, (Locale) evt.getNewValue()); CommonGui.this.firePropertyChange("appMessages", oldMessages, appMessages); MessageFormat oldFormat = format; format = new MessageFormat("", (Locale) evt.getNewValue()); CommonGui.this.firePropertyChange("format", oldFormat, format); UIManager.getDefaults().setDefaultLocale((Locale) evt.getNewValue()); } } }); UIManager.getDefaults().addResourceBundle("application"); try { SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { createComponents(); buildLayout(); registerServicesAfterComponentsAreCreated(); } }); } catch (InterruptedException e) { Logger.getLogger("application").l7dlog(Level.FATAL, "guiInitializationInterrupted", e); } catch (InvocationTargetException e) { Logger.getLogger("application").l7dlog(Level.FATAL, "guiInitializationException", e.getCause()); } } /** * Create and setup all the form components. */ protected abstract void createComponents(); /** * Setup the form layout. */ protected abstract void buildLayout(); /** * Register all common services. */ protected void registerServices() { ServiceLocator.add(OrigamiHandler.class, new Callable<JAXBOrigamiHandler>() { @Override public JAXBOrigamiHandler call() throws Exception { return new JAXBOrigamiHandler(getDocumentBase()); } }); ServiceLocator.add(ListingHandler.class, new Callable<JAXBListingHandler>() { @Override public JAXBListingHandler call() throws Exception { return new JAXBListingHandler(); } }); ServiceLocator.add(ConfigurationManager.class, new Callable<ConfigurationManagerImpl>() { @Override public ConfigurationManagerImpl call() throws Exception { return new ConfigurationManagerImpl(); } }); ServiceLocator.add(HashCodeAndEqualsHelper.class, new Callable<HashCodeAndEqualsHelperImpl>() { @Override public HashCodeAndEqualsHelperImpl call() throws Exception { return new HashCodeAndEqualsHelperImpl(); } }); ServiceLocator.add(TooltipFactory.class, new Callable<TooltipFactory>() { @Override public TooltipFactory call() throws Exception { return new TooltipFactory(); } }); // setup JAXB bindings Callable<BindingsManager> callback = new Callable<BindingsManager>() { @Override public BindingsManager call() throws Exception { BindingsManager manager = null; try { manager = new BindingsManager(JAXBContext.newInstance( "cz.cuni.mff.peckam.java.origamist.model.jaxb:cz.cuni.mff.peckam.java.origamist.files.jaxb:" + "cz.cuni.mff.peckam.java.origamist.common.jaxb", getClass().getClassLoader())); @SuppressWarnings("unused") SchemaInfo c1 = manager.addSchema("http://www.mff.cuni.cz/~peckam/java/origamist/common/v1", "resources/schemata/common_v1.xsd", true); SchemaInfo d1 = manager.addSchema("http://www.mff.cuni.cz/~peckam/java/origamist/diagram/v1", "resources/schemata/diagram_v1.xsd", true); SchemaInfo d2 = manager.addSchema("http://www.mff.cuni.cz/~peckam/java/origamist/diagram/v2", "resources/schemata/diagram_v2.xsd", true); manager.addTransform(d1, d2, "resources/schemata/diagram_v1_to_v2.xsl", null); manager.addUnmarshallerConfigurator(d2, new ObjectFactoryConfigurator(new ObjectFactory())); SchemaInfo f1 = manager.addSchema("http://www.mff.cuni.cz/~peckam/java/origamist/files/v1", "resources/schemata/files_v1.xsd", true); manager.addUnmarshallerConfigurator(f1, new ObjectFactoryConfigurator( new cz.cuni.mff.peckam.java.origamist.files.ObjectFactory())); } catch (JAXBException e) { Logger.getLogger(getClass()).error("Couldn't initialize JAXB: " + e); } catch (IOException e) { Logger.getLogger(getClass()).error("Couldn't initialize JAXB: " + e); } catch (TransformerConfigurationException e) { Logger.getLogger(getClass()).error("Couldn't initialize Transform: " + e); } return manager; } }; ServiceLocator.add(BindingsManager.class, callback); } /** * Register services after the components are created. */ protected void registerServicesAfterComponentsAreCreated() { } /** * Setup the loggers used by the application. Count that no services are registered at this time. */ protected void setupLoggersBeforeServices() { BasicConfigurator.configure(); final Logger l = Logger.getLogger("application"); l.setResourceBundle(appMessages); addPropertyChangeListener("appMessages", new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { l.setResourceBundle(appMessages); } }); l.setLevel(Level.ALL); } /** * Setup the loggers used by the application. */ protected void setupLoggers() { BasicConfigurator.resetConfiguration(); BasicConfigurator.configure(new GUIAppender(this)); } /** * Add the key listener in such a way that it reacts to the keypresses not depending on what is focused. * * @param listener The listener to be added globally. */ protected void addGlobalKeyListener(final KeyListener listener) { // new GlobalKeyListenerContainerListner(listener).add(getContentPane()); new GlobalKeyListenerContainerListner(listener).add(getTopmostComponent()); } /** * A container listener which adds/removes the given KeyListener to/from all added/removed components. * * @author Martin Pecka */ protected class GlobalKeyListenerContainerListner implements ContainerListener { /** The key listener to be added to all the components. */ protected KeyListener listener; /** * @param listener The key listener to be added to all the components. */ public GlobalKeyListenerContainerListner(KeyListener listener) { this.listener = listener; } @Override public void componentRemoved(ContainerEvent e) { this.remove(e.getChild()); } @Override public void componentAdded(ContainerEvent e) { this.add(e.getChild()); } /** * Make the given component (and all of its children, if it is a {@link Container}) listen by the listener. * * @param c */ public void add(Component c) { c.addKeyListener(listener); if (c instanceof Container) { Container cont = (Container) c; cont.addContainerListener(this); for (Component cc : cont.getComponents()) this.add(cc); } } /** * Make the given component (and all of its children, if it is a {@link Container}) not listen by the listener. * * @param c */ public void remove(Component c) { c.removeKeyListener(listener); if (c instanceof Container) { Container cont = (Container) c; cont.addContainerListener(this); for (Component cc : cont.getComponents()) this.remove(cc); } } }; @Override public void start() { super.start(); } @Override public void stop() { try { ServiceLocator.get(ConfigurationManager.class).persist(); } catch (BackingStoreException e) { Logger.getLogger("application").l7dlog(Level.ERROR, "ConfigurationManager.persist.failed", e); } super.stop(); } @Override public void destroy() { try { ServiceLocator.get(ConfigurationManager.class).persist(); } catch (BackingStoreException e) { Logger.getLogger("application").l7dlog(Level.ERROR, "ConfigurationManager.persist.failed", e); } super.destroy(); } /** * The component that is the highest in the component hierarchy. Will be either JApplet or a Frame. */ protected abstract Component getTopmostComponent(); }