r2802 - trunk/jaxx-widgets-extra/src/main/java/org/nuiton/jaxx/widgets/extra
Author: tchemit Date: 2014-02-24 15:55:51 +0100 (Mon, 24 Feb 2014) New Revision: 2802 Url: http://nuiton.org/projects/jaxx/repository/revisions/2802 Log: refs #1463 remove SwingSession from widget-extra Removed: trunk/jaxx-widgets-extra/src/main/java/org/nuiton/jaxx/widgets/extra/SwingSession.java Deleted: trunk/jaxx-widgets-extra/src/main/java/org/nuiton/jaxx/widgets/extra/SwingSession.java =================================================================== --- trunk/jaxx-widgets-extra/src/main/java/org/nuiton/jaxx/widgets/extra/SwingSession.java 2014-02-24 14:38:02 UTC (rev 2801) +++ trunk/jaxx-widgets-extra/src/main/java/org/nuiton/jaxx/widgets/extra/SwingSession.java 2014-02-24 14:55:51 UTC (rev 2802) @@ -1,804 +0,0 @@ -/* - * #%L - * JAXX :: Extra Widgets - * %% - * Copyright (C) 2004 - 2010 CodeLutin - * %% - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program 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 Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. - * #L% - */ -package org.nuiton.jaxx.widgets.extra; - - -import java.awt.BorderLayout; -import java.awt.Component; -import java.awt.Container; -import java.awt.Dialog; -import java.awt.Frame; -import java.awt.GraphicsConfiguration; -import java.awt.GraphicsDevice; -import java.awt.GraphicsEnvironment; -import java.awt.Rectangle; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.beans.DefaultPersistenceDelegate; -import java.beans.Encoder; -import java.beans.ExceptionListener; -import java.beans.Expression; -import java.beans.XMLDecoder; -import java.beans.XMLEncoder; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import javax.swing.JButton; -import javax.swing.JFrame; -import javax.swing.JScrollPane; -import javax.swing.JSplitPane; -import javax.swing.JTabbedPane; -import javax.swing.JTable; -import javax.swing.JTextArea; -import javax.swing.table.AbstractTableModel; -import javax.swing.table.TableColumn; -import javax.swing.table.TableModel; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * Use to store and restore position and size of application. Supported widgets - * are: - * <li> java.awt.Window (and subclasses) - * <li> javax.swing.JTabbedPane (and subclasses) - * <li> javax.swing.JSplitPane (and subclasses) - * <li> javax.swing.JTable (and subclasses) - * - * usage: - * <li> create SwingSession object - * <li> add component that you want save - * <li> explicite call to save - * - * You can use same SwingSession for multiple window but in this case you must - * have setName for each window with different name, otherwize there are - * collision between window component and result is undetermisitic - * - * This code is partialy inspired from http://kenai.com/projects/bsaf/pages/Home - * project. This project is under LGPL v2.1 license. We can't reuse directly this - * library because to many fields and methods are private and we can't implements - * it and modify some behavior. - * - * @author poussin - * @version $Revision$ - * - * Last update: $Date$ - * by : $Author$ - */ -public class SwingSession { - - /** to use log facility, just put in your code: log.info(\"...\"); */ - static private Log log = LogFactory.getLog(SwingSession.class); - - protected File file; - protected boolean autoSave; - protected LinkedHashSet<Component> registeredComponent = - new LinkedHashSet<Component>(); - /** State object registered to get and set State. - * key: class of component managed by the state; value: the state*/ - protected Map<Class, State> stateManager = new HashMap<Class, State>(); - /** state of all component added with add method. - * key: path of compoenent; value: State */ - protected Map<String, State> states; - - public SwingSession(File file, boolean autoSave) { - this.file = file; - this.autoSave = autoSave; - stateManager.put(Window.class, new WindowState()); - stateManager.put(JTable.class, new JTableState()); - stateManager.put(JTabbedPane.class, new JTabbedPaneState()); - stateManager.put(JSplitPane.class, new JSplitPaneState()); - - states = loadStates(file); - if (states == null) { - states = new HashMap<String, State>(); - } - } - - @Override - protected void finalize() throws Throwable { - save(); - super.finalize(); - } - - - /* If an exception occurs in the XMLEncoder/Decoder, we want - * to throw an IOException. The exceptionThrow listener method - * doesn't throw a checked exception so we just set a flag - * here and check it when the encode/decode operation finishes - */ - private static class AbortExceptionListener implements ExceptionListener { - - public Exception exception = null; - - @Override - public void exceptionThrown(Exception e) { - if (exception == null) { - exception = e; - } - } - } - - /* There are some (old) Java classes that aren't proper beans. Rectangle - * is one of these. When running within the secure sandbox, writing a - * Rectangle with XMLEncoder causes a security exception because - * DefaultPersistenceDelegate calls Field.setAccessible(true) to gain - * access to private fields. This is a workaround for that problem. - * A bug has been filed, see JDK bug ID 4741757 - */ - private static class RectanglePD extends DefaultPersistenceDelegate { - - public RectanglePD() { - super(new String[]{"x", "y", "width", "height"}); - } - - @Override - protected Expression instantiate(Object oldInstance, Encoder out) { - Rectangle oldR = (Rectangle) oldInstance; - Object[] constructorArgs = new Object[]{ - oldR.x, oldR.y, oldR.width, oldR.height - }; - return new Expression(oldInstance, oldInstance.getClass(), "new", constructorArgs); - } - } - - public void save() { - updateState(); - AbortExceptionListener el = new AbortExceptionListener(); - ByteArrayOutputStream bst = new ByteArrayOutputStream(); - XMLEncoder e = null; - /* Buffer the XMLEncoder's output so that decoding errors don't - * cause us to trash the current version of the specified file. - */ - try { - e = new XMLEncoder(bst); - e.setPersistenceDelegate(Rectangle.class, new RectanglePD()); - e.setExceptionListener(el); - e.writeObject(states); - } finally { - if (e != null) { - e.close(); - } - } - if (el.exception != null) { - log.warn("save failed \"" + file + "\"", el.exception); - } else { - OutputStream ost = null; - try { - ost = new FileOutputStream(file); - ost.write(bst.toByteArray()); - } catch (IOException eee) { - log.warn("save failed \"" + file + "\"", eee); - } finally { - if (ost != null) { - try { - ost.close(); - } catch (IOException eee) { - log.warn("can't close properly \"" + file + "\"", eee); - } - } - } - } - } - - /** - * Loads the states from the file - */ - public Map<String, State> loadStates(File file) { - Map<String, State> result = null; - if (file.exists()) { - XMLDecoder d = null; - try { - InputStream ist = new FileInputStream(file); - d = new XMLDecoder(ist); - AbortExceptionListener eee = new AbortExceptionListener(); - d.setExceptionListener(eee); - Object bean = d.readObject(); - if (eee.exception != null) { - log.warn("load failed \"" + file + "\"", eee.exception); - } else { - result = (Map<String, State>) bean; - } - } catch (IOException eee) { - log.warn("load failed \"" + file + "\"", eee); - } finally { - if (d != null) { - d.close(); - } - } - } - return result; - } - - public void updateState() { - walkThrowComponent("", registeredComponent, - new SaveStateAction()); - } - - public void add(Component c) { - if (registeredComponent.contains(c)) { - log.warn(String.format( - "Component already added %s(%s)", c.getClass(), c.getName())); - } else { - registeredComponent.add(c); - walkThrowComponent("", Collections.singleton(c), - new RestoreStateAction()); - } - } - - /** - * Remove component from component to save - * @param c - */ - public void remove(Component c) { - registeredComponent.remove(c); - } - - protected String getComponentName(Component c) { - String name = c.getName(); - if (name == null) { - int n = c.getParent().getComponentZOrder(c); - if (n >= 0) { - Class clazz = c.getClass(); - name = clazz.getSimpleName(); - if (name.length() == 0) { - name = "Anonymous" + clazz.getSuperclass().getSimpleName(); - } - name = name + n; - } else { - // Implies that the component tree is changing - // while we're computing the path. Punt. - log.warn("Couldn't compute pathname for " + c); - } - } - return name; - } - - public State getStateManager(Class clazz) { - State result = null; - while (result == null && clazz != null) { - result = stateManager.get(clazz); - clazz = clazz.getSuperclass(); - } - return result; - } - - public State getStates(String path) { - return states.get(path); - } - - public void setStates(String path, State state) { - this.states.put(path, state); - } - - protected void walkThrowComponent( - String path, Collection<Component> roots, Action action) { - for (Component root : roots) { - if (root != null) { - String pathname = path + "/" + getComponentName(root); - State state = getStateManager(root.getClass()); - if (state != null) { - action.doAction(this, pathname, root); - } - if (root instanceof Container) { - Component[] children = ((Container) root).getComponents(); - if ((children != null) && (children.length > 0)) { - walkThrowComponent(pathname, Arrays.asList(children), action); - } - } - if (root instanceof JFrame) { - Component[] children = ((JFrame) root).getContentPane().getComponents(); - if ((children != null) && (children.length > 0)) { - walkThrowComponent(pathname, Arrays.asList(children), action); - } - } - } - } - } - - static public interface Action { - public void doAction(SwingSession session, String path, Component c); - } - - static public class SaveStateAction implements Action { - @Override - public void doAction(SwingSession session, String path, Component c) { - State manager = session.getStateManager(c.getClass()); - State state = manager.getState(c); - session.setStates(path, state); - } - } - - static public class RestoreStateAction implements Action { - @Override - public void doAction(SwingSession session, String path, Component c) { - State manager = session.getStateManager(c.getClass()); - State state = session.getStates(path); - if (state != null) { - manager.setState(c, state); - } - } - } - - /** - * get(save) and set(restore) state of object passed in argument - */ - static public interface State { - public State getState(Object o); - public void setState(Object o, State state); - } - - /** - * State for JTabbedPane - */ - static public class JTabbedPaneState implements State { - - protected int selectedIndex = -1; - protected int tabCount; - - public JTabbedPaneState() { - } - - public int getSelectedIndex() { - return selectedIndex; - } - - public void setSelectedIndex(int selectedIndex) { - this.selectedIndex = selectedIndex; - } - - public int getTabCount() { - return tabCount; - } - - public void setTabCount(int tabCount) { - this.tabCount = tabCount; - } - - - protected JTabbedPane checkComponent(Object o) { - if (o == null) { - throw new IllegalArgumentException("null component"); - } - if (!(o instanceof JTabbedPane)) { - throw new IllegalArgumentException("invalid component"); - } - return (JTabbedPane) o; - } - - @Override - public State getState(Object o) { - JTabbedPaneState result = new JTabbedPaneState(); - - JTabbedPane p = checkComponent(o); - result.setSelectedIndex(p.getSelectedIndex()); - result.setTabCount(p.getTabCount()); - - return result; - } - - @Override - public void setState(Object o, State state) { - if (state == null) { - return; - } - if (state instanceof JTabbedPaneState) { - JTabbedPane p = checkComponent(o); - JTabbedPaneState tps = (JTabbedPaneState) state; - if (tps.getSelectedIndex() != -1 - && p.getTabCount() == tps.getTabCount()) { - p.setSelectedIndex(tps.getSelectedIndex()); - } - } else { - throw new IllegalArgumentException("invalid state"); - } - } - } - - /** - * State for JSplit - * FIXME add listener for divider move action - */ - static public class JSplitPaneState implements State { - - protected int dividerLocation = -1; - protected int orientation = JSplitPane.HORIZONTAL_SPLIT; - - public JSplitPaneState() { - } - - public int getDividerLocation() { - return dividerLocation; - } - - public void setDividerLocation(int dividerLocation) { - this.dividerLocation = dividerLocation; - } - - public int getOrientation() { - return orientation; - } - - public void setOrientation(int orientation) { - this.orientation = orientation; - } - - protected JSplitPane checkComponent(Object o) { - if (o == null) { - throw new IllegalArgumentException("null component"); - } - if (!(o instanceof JSplitPane)) { - throw new IllegalArgumentException("invalid component"); - } - return (JSplitPane) o; - } - - @Override - public State getState(Object o) { - JSplitPane p = checkComponent(o); - - JSplitPaneState result = new JSplitPaneState(); - result.setDividerLocation(p.getUI().getDividerLocation(p)); - result.setOrientation(p.getOrientation()); - - return result; - } - - @Override - public void setState(Object o, State state) { - if (state == null) { - return; - } - JSplitPane p = checkComponent(o); - if (state instanceof JSplitPaneState) { - JSplitPaneState sps = (JSplitPaneState) state; - if (sps.getDividerLocation() != -1 - && p.getOrientation() == sps.getOrientation()) { - p.setDividerLocation(sps.getDividerLocation()); - } - } else { - throw new IllegalArgumentException("invalid state"); - } - } - } - - /** - * State for JTable. - * TODO add support for column order change - */ - static public class JTableState implements State { - - protected int[] columnWidths = new int[0]; - - public JTableState() { - } - - public JTableState(int[] columnWidths) { - this.columnWidths = columnWidths; - } - - public int[] getColumnWidths() { - return columnWidths; - } - - public void setColumnWidths(int[] columnWidths) { - this.columnWidths = columnWidths; - } - - protected JTable checkComponent(Object o) { - if (o == null) { - throw new IllegalArgumentException("null component"); - } - if (!(o instanceof JTable)) { - throw new IllegalArgumentException("invalid component"); - } - return (JTable) o; - } - - @Override - public State getState(Object o) { - JTable table = checkComponent(o); - int[] columnWidths = new int[table.getColumnCount()]; - boolean resizableColumnExists = false; - for (int i = 0; i < columnWidths.length; i++) { - TableColumn tc = table.getColumnModel().getColumn(i); - columnWidths[i] = (tc.getResizable()) ? tc.getWidth() : -1; - if (tc.getResizable()) { - resizableColumnExists = true; - } - } - JTableState result = null; - if (resizableColumnExists) { - result = new JTableState(); - result.setColumnWidths(columnWidths); - } - return result; - } - - @Override - public void setState(Object o, State state) { - if (!(state instanceof JTableState)) { - throw new IllegalArgumentException("invalid state"); - } - JTable table = checkComponent(o); - int[] columnWidths = ((JTableState) state).getColumnWidths(); - if (columnWidths != null - && table.getColumnCount() == columnWidths.length) { - for (int i = 0; i < columnWidths.length; i++) { - if (columnWidths[i] != -1) { - TableColumn tc = table.getColumnModel().getColumn(i); - if (tc.getResizable()) { - tc.setPreferredWidth(columnWidths[i]); - } - } - } - } - } - } - - /** - * State for Window - */ - static public class WindowState implements State { - private static final String WINDOW_STATE_NORMAL_BOUNDS = - "WindowState.normalBounds"; - - protected Rectangle bounds; - protected Rectangle gcBounds; - protected int frameState = Frame.NORMAL; - - public WindowState() { - } - - public WindowState(Rectangle bounds, Rectangle gcBounds, int frameState) { - this.bounds = new Rectangle(bounds); - this.gcBounds = new Rectangle(gcBounds); - this.frameState = frameState; - } - - public Rectangle getBounds() { - return bounds; - } - - public void setBounds(Rectangle bounds) { - this.bounds = bounds; - } - - public Rectangle getGcBounds() { - return gcBounds; - } - - public void setGcBounds(Rectangle gcBounds) { - this.gcBounds = gcBounds; - } - - public int getFrameState() { - return frameState; - } - - public void setFrameState(int frameState) { - this.frameState = frameState; - } - - protected Window checkComponent(Object o) { - if (o == null) { - throw new IllegalArgumentException("null component"); - } - if (!(o instanceof Window)) { - throw new IllegalArgumentException("invalid component"); - } - return (Window) o; - } - - /** - * Checks whether the window supports resizing - * @param window the {@code Window} to be checked - * @return true if the window supports resizing - */ - protected static boolean isResizable(Window window) { - boolean resizable = true; - if (window instanceof Frame) { - resizable = ((Frame) window).isResizable(); - } else if (window instanceof Dialog) { - resizable = ((Dialog) window).isResizable(); - } - return resizable; - } - - /** - * Gets {@code Window} bounds from the client property - * @param window the source {@code Window} - * @return bounds from the client property - */ - protected static Rectangle getWindowNormalBounds(Window window) { - Rectangle result = null; - if (window instanceof JFrame) { - Object res = ((JFrame) window).getRootPane().getClientProperty( - WINDOW_STATE_NORMAL_BOUNDS); - if (res instanceof Rectangle) { - result = (Rectangle) res; - } - } - return result; - } - - /** - * Calculates virtual graphic bounds. - * On multiscreen systems all screens are united into one virtual screen. - * @return the graphic bounds - */ - public static Rectangle computeVirtualGraphicsBounds() { - Rectangle virtualBounds = new Rectangle(); - GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - GraphicsDevice[] gs = ge.getScreenDevices(); - for (GraphicsDevice gd : gs) { - GraphicsConfiguration gc = gd.getDefaultConfiguration(); - virtualBounds = virtualBounds.union(gc.getBounds()); - } - return virtualBounds; - } - - /** - * Puts {@code Window} bounds to client property. - * @param window the target {@code Window} - * @param bounds bounds - */ - public static void putWindowNormalBounds(Window window, Rectangle bounds) { - if (window instanceof JFrame) { - ((JFrame) window).getRootPane().putClientProperty( - WINDOW_STATE_NORMAL_BOUNDS, bounds); - } - } - - @Override - public State getState(Object o) { - Window c = checkComponent(o); - int frameState = Frame.NORMAL; - if (c instanceof Frame) { - frameState = ((Frame) c).getExtendedState(); - } - GraphicsConfiguration gc = c.getGraphicsConfiguration(); - Rectangle gcBounds = (gc == null) ? null : gc.getBounds(); - Rectangle frameBounds = c.getBounds(); - - /* If this is a JFrame created by FrameView and it's been maximized, - * retrieve the frame's normal (not maximized) bounds. More info: - * see FrameStateListener#windowStateChanged in FrameView. - */ - if ((c instanceof JFrame) && (0 != (frameState & Frame.MAXIMIZED_BOTH))) { - frameBounds = getWindowNormalBounds(c); - } - - WindowState result = null; - if (frameBounds != null && !frameBounds.isEmpty()) { - result = new WindowState(); - result.setBounds(frameBounds); - result.setGcBounds(gcBounds); - result.setFrameState(frameState); - } - - return result; - } - - @Override - public void setState(Object o, State state) { - Window w = checkComponent(o); - if ((state != null) && !(state instanceof WindowState)) { - throw new IllegalArgumentException("invalid state"); - } - WindowState windowState = (WindowState) state; - if (windowState.getBounds() != null) { - putWindowNormalBounds(w, windowState.getBounds()); - if (!w.isLocationByPlatform() && (state != null)) { - - Rectangle gcBounds0 = windowState.getGcBounds(); - if (gcBounds0 != null && isResizable(w)) { - if (computeVirtualGraphicsBounds().contains(gcBounds0.getLocation())) { - w.setBounds(windowState.getBounds()); - } else { - w.setSize(windowState.getBounds().getSize()); - } - } - } - if (w instanceof Frame) { - ((Frame) w).setExtendedState(windowState.getFrameState()); - } - } - } - - } - - - /** - * Just for test rapidly - * @param args - */ - static public void main(String[] args) { - final SwingSession session = - new SwingSession(new File("/tmp/SwingSession.config"), false); - - JFrame frame = new JFrame("truc"); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setBounds(10, 20, 300, 500); - - TableModel dataModel = new AbstractTableModel() { - - @Override - public String getColumnName(int column) { - return "c" + column; - } - - @Override - public int getColumnCount() { - return 5; - } - - @Override - public int getRowCount() { - return 10; - } - - @Override - public Object getValueAt(int row, int col) { - return new Integer(row * col); - } - }; - JTable table = new JTable(dataModel); - table.setName("MaTable"); - - JTabbedPane tab = new JTabbedPane(); - tab.setName("MaTab"); - tab.add("tab1", new JTextArea()); - tab.add("tab2", new JTextArea()); - tab.add("tab3", new JTextArea()); - - JSplitPane split = new JSplitPane(); - split.setTopComponent(new JScrollPane(table)); - split.setBottomComponent(tab); - - JButton button = new JButton("Save"); - button.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - session.save(); - } - }); - - frame.getContentPane().setLayout(new BorderLayout()); - frame.getContentPane().add(button, BorderLayout.NORTH); - frame.getContentPane().add(split, BorderLayout.CENTER); - - frame.setVisible(true); - session.add(frame); - session.save(); - } -}
participants (1)
-
tchemit@users.nuiton.org