package org.chesmapper.view.gui; import java.awt.Dimension; import java.awt.KeyEventDispatcher; import java.awt.KeyboardFocusManager; import java.awt.Point; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.KeyEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.io.PrintStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPopupMenu; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; import org.chesmapper.map.data.ClusteringData; import org.chesmapper.map.main.ScreenSetup; import org.chesmapper.map.main.Settings; import org.chesmapper.view.cluster.ClusterController; import org.chesmapper.view.cluster.Clustering; import org.chesmapper.view.gui.swing.ComponentFactory; import org.jmol.util.DefaultLogger; import org.jmol.util.Logger; import org.mg.javalib.gui.BlockableFrame; import org.mg.javalib.gui.property.IntegerProperty; import org.mg.javalib.gui.property.Property; import org.mg.javalib.util.ColorUtil; import org.mg.javalib.util.ScreenUtil; import org.mg.javalib.util.SwingUtil; import org.mg.javalib.util.ThreadUtil; public class CheSViewer implements GUIControler { static { Logger.setLogger(new DefaultLogger() { @Override protected void log(PrintStream out, int level, String txt, Throwable e) { super.log(out, level, txt != null ? "Jmol > " + txt : null, e); } }); } // static // { // Settings.LOGGER.warn(JmolConstants.version); // } BlockableFrame frame; ClusterPanel clusterPanel; Clustering clustering; MenuBar menuBar; boolean undecorated = false; Dimension oldSize; Point oldLocation; boolean messagesBlocked; List<PropertyChangeListener> listeners = new ArrayList<PropertyChangeListener>(); private static CheSViewer instance; public static interface PostStartModifier { public void modify(GUIControler gui, ViewControler view, ClusterController clusterControler, Clustering clustering); } public static void show(ClusteringData clusteringData, final PostStartModifier mod) { if (!SwingUtilities.isEventDispatchThread()) throw new IllegalStateException("GUI updates only in event dispatch thread plz"); // if (instance == null) instance = new CheSViewer(clusteringData); // else // { // instance.clusterPanel.init(clusteringData); // if (!instance.isFullScreen() && !instance.frame.isVisible()) // instance.frame.setVisible(true); // } if (mod != null) { Thread th = new Thread(new Runnable() { @Override public void run() { SwingUtil.waitForAWTEventThread(); ThreadUtil.sleep(2000); mod.modify(instance, instance.clusterPanel.getViewControler(), instance.clusterPanel.getClusterControler(), CheSViewer.getClustering()); } }); th.start(); } } private CheSViewer(ClusteringData clusteredDataset) { oldSize = ScreenSetup.INSTANCE.getViewerSize(); if (oldSize == null) throw new Error(); oldLocation = null; clusterPanel = new ClusterPanel(this); // oldSize = new Dimension(1024, 768); //oldLocation = new Point(0, 0); clusterPanel.init(clusteredDataset); clustering = clusterPanel.getClustering(); menuBar = new MenuBar(this, clusterPanel.getViewControler(), clusterPanel.getClusterControler(), clustering); KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager(); kfm.addKeyEventDispatcher(new KeyEventDispatcher() { @Override public boolean dispatchKeyEvent(KeyEvent e) { KeyStroke keyStroke = KeyStroke.getKeyStrokeForEvent(e); return Actions.instance().performAction(e.getSource(), keyStroke, !frame.isUndecorated()); } }); for (IntegerProperty integerProperty : ComponentSize.MAX_WIDTH) { integerProperty.addPropertyChangeListener(new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { fireEvent(PROPERTY_VIEWER_SIZE_CHANGED); } }); } setFullScreen(false, true); } @Override public void setFullScreen(boolean b) { setFullScreen(b, false); } private void setFullScreen(boolean b, boolean force) { if (force || frame.isUndecorated() != b) { if (frame != null) { frame.dispose(); // f.removeAll(); frame.setVisible(false); } if (b) { oldSize = frame.getSize(); oldLocation = frame.getLocation(); show(b, ScreenSetup.INSTANCE.getFullScreenSize(), new Point(0, 0)); } else { show(b, oldSize, oldLocation); } fireEvent(PROPERTY_FULLSCREEN_CHANGED); } } @Override public boolean isFullScreen() { if (frame == null) return false; else return frame.isUndecorated(); } public void updateTitle(Clustering c) { if (frame != null) frame.setTitle((c.getName() == null ? "" : (c.getName() + " - ")) + Settings.TITLE + " (" + Settings.VERSION_STRING + ")"); } private void show(boolean undecorated, Dimension size, Point location) { // Settings.LOGGER.info("showing - size: " + size); if (clustering == null) throw new Error("clustering is null"); boolean showMsg = true; if (frame == null) { frame = new BlockableFrame(true); Settings.TOP_LEVEL_FRAME = frame; frame.addComponentListener(new ComponentAdapter() { public void componentMoved(ComponentEvent e) { Settings.TOP_LEVEL_FRAME_SCREEN = ScreenUtil.getScreen(frame); } public void componentResized(ComponentEvent e) { ComponentFactory.updateComponents(); fireEvent(PROPERTY_VIEWER_SIZE_CHANGED); } }); frame.getContentPane().add(clusterPanel); frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { super.windowClosing(e); LaunchCheSMapper.exit(frame); }; }); frame.setIconImage(Settings.CHES_MAPPER_IMAGE.getImage()); showMsg = false; } updateTitle(clustering); frame.setUndecorated(undecorated); frame.setJMenuBar(undecorated ? null : menuBar); if (undecorated) { frame.setSize(size);//the fullscreen size was just derived from the current screen (if not overriden manually) ScreenUtil.getGraphicsDevice(Settings.TOP_LEVEL_FRAME_SCREEN).setFullScreenWindow(frame); frame.setResizable(false); frame.setAlwaysOnTop(true); } else { frame.setSize(size); if (location == null) ScreenSetup.INSTANCE.centerOnScreen(frame); else frame.setLocation(location); frame.setResizable(true); frame.setAlwaysOnTop(false); } frame.setVisible(true); Settings.TOP_LEVEL_FRAME_SCREEN = ScreenUtil.getScreen(frame); if (showMsg) { if (frame.isUndecorated()) showMessage("Press 'ESCAPE' to leave fullscreen mode"); else showMessage("Press 'ALT+ENTER' for fullscreen mode"); } SwingUtilities.invokeLater(new Runnable() { @Override public void run() { frame.toFront(); } }); } public void showMessage(String msg) { if (!messagesBlocked && clusterPanel != null && clusterPanel.isVisible()) clusterPanel.showMessage(msg); Settings.LOGGER.debug(msg); } @Override public JPopupMenu getPopup() { return menuBar.getPopup(); } // @Override // public void handleKeyEvent(KeyEvent e) // { // menuBar.handleKeyEvent(e); // } @Override public void addPropertyChangeListener(PropertyChangeListener l) { listeners.add(l); } private void fireEvent(String prop) { for (PropertyChangeListener ll : listeners) ll.propertyChange(new PropertyChangeEvent(this, prop, false, true)); } @Override public void block(String blocker) { if (frame != null) frame.block(blocker); } @Override public boolean isBlocked() { return frame.isBlocked(); } @Override public boolean isVisible() { return frame != null && frame.isVisible(); } @Override public void unblock(String blocker) { if (frame != null) { frame.unblock(blocker); } } @Override public int getComponentMaxWidth(double pct) { int w; if (frame != null) w = frame.getWidth(); else w = oldSize.width; return getComponentMaxSize(w, pct); } @Override public int getComponentMaxHeight(double pct) { int h; if (frame != null) h = frame.getHeight(); else h = oldSize.height; return getComponentMaxSize(h, pct); } private int getComponentMaxSize(int size, double pct) { int s = (int) (size * pct); if (ScreenSetup.INSTANCE.isFontSizeLarge()) s = (int) Math.min(size, s * 1.1); // allow a bit larger components when font size is large return s; } public static JFrame getFrame() { if (instance == null) return null; else return instance.frame; } public static Clustering getClustering() { if (instance == null) return null; else return instance.clustering; } @Override public void blockMessages() { messagesBlocked = true; } @Override public void unblockMessages() { messagesBlocked = false; } String selectedString; @Override public String getSelectedString() { return selectedString; } @Override public void setSelectedString(String s) { selectedString = s; } HashMap<Property, JComponent> propComps = new HashMap<Property, JComponent>(); HashMap<Property, Boolean> propHideComp = new HashMap<Property, Boolean>(); boolean accentuate = false; @Override public void registerSizeComponent(Property p, JComponent c) { propComps.put(p, c); } @Override public boolean isAccentuateComponents() { return accentuate; } @Override public void setAccentuateSizeComponents(boolean b) { for (Property p : propComps.keySet()) { JComponent c = propComps.get(p); if (b == true) { accentuate = true; if (!c.isVisible()) { c.setVisible(true); propHideComp.put(p, true); } else propHideComp.put(p, false); // SwingUtil.setDebugBorder(c, p.getHighlightColor()); c.setOpaque(true); c.setBackground(ColorUtil.transparent(p.getHighlightColor(), 100)); } else { accentuate = false; // SwingUtil.removeDebugBorder(c); c.setOpaque(false); if (propHideComp.get(p)) { c.setVisible(false); propHideComp.put(p, false); } } } fireEvent(PROPERTY_VIEWER_SIZE_CHANGED); } }