Announcement Announcement Module
Collapse
No announcement yet.
Persisting a view's JXTable user settings Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Persisting a view's JXTable user settings

    Hello

    Here is how to persist (save/restore) the users settings (ordering of columns, visbility etc) of JXTables in a view using the Swing Application Framework (JSR-296 -- https://appframework.dev.java.net/). You will need to download the jar for the App. framework to get the stuff below working.

    I guess the whole view can be persisted by the App. framework but that will have to be later.

    Code:
    <!-- Storage location for JXTable user settings -->
    	<bean id="moduleApplicationContext" class="ModuleApplicationContext">
    		<constructor-arg value="${user.home}/.myAppHome/" />
    	</bean>

    Code:
    /**
     * Nicked from
     * http://puces-blog.blogspot.com/2009/04/netbeans-platform-meets-swing.html
     */
    
    public class ModuleApplicationContext extends ApplicationContext {
    
    	private String storageDirectoryPath = "";
    
    	static {
    
    // download from https://jdnc-incubator.dev.java.net/source/browse/jdnc-incubator/src/kleopatra/java/org/jdesktop/appframework/swingx/XProperties.java?rev=1.3&view=markup
    		new XProperties().registerPersistenceDelegates();
    	}
    
    	public ModuleApplicationContext(String path) {
    		// Needed due to issue
    		// https://appframework.dev.java.net/issues/show_bug.cgi?id=112
    		setLocalStorage(new ModuleLocalStorage(this));
    		// getLocalStorage().setDirectory(getModuleSessionStorageDir(moduleInfo));
    		storageDirectoryPath = path;
    		getLocalStorage().setDirectory(new File(storageDirectoryPath));
    		getSessionStorage().putProperty(JXTable.class,
    				new XProperties.XTableProperty());
    	}
    
    }
    Code:
    /**
     * A LocalStorage for modules. It respects the direcory property in JNLP mode. <BR/>
     * <BR/>
     * Needed due to issue <A
     * HREF="https://appframework.dev.java.net/issues/show_bug.cgi?id=112">
     * https://appframework.dev.java.net/issues/show_bug.cgi?id=112</A>
     * 
     * @author puce
     */
    
    public class ModuleLocalStorage extends LocalStorage {
    
    	public ModuleLocalStorage(ApplicationContext context) {
    		super(context);
    	}
    
    	@Override
    	public boolean deleteFile(String fileName) throws IOException {
    		File path = new File(getDirectory(), fileName);
    		return path.delete();
    	}
    
    	@Override
    	public InputStream openInputFile(String fileName) throws IOException {
    		File path = new File(getDirectory(), fileName);
    		return new BufferedInputStream(new FileInputStream(path));
    	}
    
    	@Override
    	public OutputStream openOutputFile(String fileName) throws IOException {
    		File path = new File(getDirectory(), fileName);
    		return new BufferedOutputStream(new FileOutputStream(path));
    	}
    }
    Code:
    	<bean id="tableFactory" class="DefaultTableFactory" />
    
    	<bean id="componentFactory"
    		class="org.springframework.richclient.factory.DefaultComponentFactory">
    		<!--
    			property name="iconSource"> <ref bean="iconSource" /> </property
    		-->
    		<property name="messageSource">
    			<ref bean="messageSource" />
    		</property>
    		<property name="tableFactory">
    			<ref bean="tableFactory" />
    		</property>
    	</bean>
    Now we need a table factory that creates JXTables

    Code:
    public class DefaultTableFactory implements TableFactory {
    
    	public JTable createTable() {
    		JXTable result = new JXTable();
    		return configureTable(result);
    	}
    
    	public JTable createTable(TableModel model) {
    		JXTable result = new JXTable(model);
    		return configureTable(result);
    	}
    
    	private JXTable configureTable(JXTable result) {
    		result.getSelectionMapper().setEnabled(false);
    		result.setColumnControlVisible(true);
    		result.setHighlighters(createHighlighter(result), new ColorHighlighter(
    				HighlightPredicate.ROLLOVER_ROW, null, Color.BLUE));
    		result.setRolloverEnabled(true);
    		result.setHorizontalScrollEnabled(true);
    		return result;
    	}
    
    	private CompoundHighlighter createHighlighter(JXTable t) {
    		ColorHighlighter first = new SubstanceHighLighter(
    				HighlightPredicate.EVEN, t);
    		ColorHighlighter hl = new SubstanceHighLighter(HighlightPredicate.ODD,
    				t);
    		return new CompoundHighlighter(first, hl);
    	}
    
    	// get striping on jxtable to work with substance
    	static private class SubstanceHighLighter extends ColorHighlighter {
    
    		private JXTable comp;
    
    		SubstanceHighLighter(HighlightPredicate pred, JXTable t) {
    			setHighlightPredicate(pred);
    			comp = t;
    		}
    
    		@Override
    		public Color getBackground() {
    			return SubstanceColorUtilities.getStripedBackground(comp,
    					getHighlightPredicate() == HighlightPredicate.EVEN ? 1 : 0);
    		}
    	}
    
    }
    And then in your view(s):

    Code:
    public abstract class MyView extends AbstractView {
    private ModuleApplicationContext mac = (ModuleApplicationContext) Application
    			.instance().getApplicationContext().getBean(
    					"moduleApplicationContext");
    ...
    	@Override
    	public void dispose() {
    		saveJXTableSetup(getControl());
    	}
    
    	private void saveJXTableSetup(Container comp) {
    		Component[] components = comp.getComponents();
    		for (Component com : components) {
    			if (com instanceof JXTable) {
    				Container parent = com.getParent();
    				JXTable t = (JXTable) com;
    				parent.remove(com);
    				try {
    					log.debug("Saving table state in " + t.getName() + ".xml");
    					mac.getSessionStorage().save(com, t.getName() + ".xml");
    					parent.add(com);
    				} catch (IOException e) {
    					log.error("", e);
    				}
    			} else if (com instanceof Container) {
    				saveJXTableSetup((Container) com);
    			}
    		}
    	}
    Notice that the JXTables need to have a name for all of this to work, e.g.:

    Code:
    public abstract class MyTable extends AbstractObjectTable {
    
    	private ModuleApplicationContext mac = (ModuleApplicationContext) Application
    			.instance().getApplicationContext().getBean(
    					"moduleApplicationContext");
    
            ...
    
    	@Override
    	protected JComponent createControl() {
    		JXTable t = (JXTable) super.createControl();
    		// name table and restore its state
    		t.setName(getModelId());
    		try {
    			mac.getSessionStorage().restore(t, getModelId() + ".xml");
    		} catch (IOException e) {
    			log.error("", e);
    		}
    		return t;
    	}
    More info (but cluttered with netbeans stuff) can be found here http://puces-blog.blogspot.com/2009/...ets-swing.html

    BR
    Carsten
Working...
X