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