From: <cpm...@us...> - 2011-04-12 05:25:10
|
Revision: 14784 http://pcgen.svn.sourceforge.net/pcgen/?rev=14784&view=rev Author: cpmeister Date: 2011-04-12 05:25:03 +0000 (Tue, 12 Apr 2011) Log Message: ----------- Character Tab switching enhancement Modified Paths: -------------- sandbox/uisync/code/src/java/pcgen/gui2/tabs/InfoTabbedPane.java Modified: sandbox/uisync/code/src/java/pcgen/gui2/tabs/InfoTabbedPane.java =================================================================== --- sandbox/uisync/code/src/java/pcgen/gui2/tabs/InfoTabbedPane.java 2011-04-12 02:42:42 UTC (rev 14783) +++ sandbox/uisync/code/src/java/pcgen/gui2/tabs/InfoTabbedPane.java 2011-04-12 05:25:03 UTC (rev 14784) @@ -23,13 +23,21 @@ import java.awt.Component; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.lang.reflect.InvocationTargetException; +import java.util.Comparator; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; +import java.util.PriorityQueue; import java.util.WeakHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ThreadFactory; import javax.swing.Icon; import javax.swing.JTabbedPane; import javax.swing.SwingUtilities; +import pcgen.base.lang.UnreachableError; import pcgen.base.util.DoubleKeyMap; import pcgen.core.facade.CharacterFacade; import pcgen.gui2.tools.CharacterSelectionListener; @@ -42,14 +50,30 @@ implements CharacterSelectionListener { + private final ExecutorService restoringThread = Executors.newSingleThreadExecutor(new ThreadFactory() + { + + public Thread newThread(Runnable r) + { + Thread thread = new Thread(r); + thread.setDaemon(true); + thread.setPriority(Thread.NORM_PRIORITY); + thread.setName("tab-info-thread"); + return thread; + } + + }); + private final Map<CharacterInfoTab, Long> timingMap; private final DoubleKeyMap<CharacterFacade, CharacterInfoTab, Hashtable<Object, Object>> stateMap; private final Map<CharacterFacade, Integer> tabSelectionMap; private CharacterFacade currentCharacter = null; + private Future restoringTask; public InfoTabbedPane() { this.stateMap = new DoubleKeyMap<CharacterFacade, CharacterInfoTab, Hashtable<Object, Object>>(WeakHashMap.class, HashMap.class); this.tabSelectionMap = new WeakHashMap<CharacterFacade, Integer>(); + this.timingMap = new HashMap<CharacterInfoTab, Long>(); initComponent(); } @@ -77,6 +101,16 @@ addTab(new CharacterSheetInfoTab()); } + private <T extends Component & CharacterInfoTab> void addTab(T tab) + { + TabTitle tabTitle = tab.getTabTitle(); + String title = (String) tabTitle.getValue(TabTitle.TITLE); + String tooltip = (String) tabTitle.getValue(TabTitle.TOOLTIP); + Icon icon = (Icon) tabTitle.getValue(TabTitle.ICON); + addTab(title, icon, tab, tooltip); + tabTitle.addPropertyChangeListener(new TabActionListener(tab)); + } + public void setCharacter(CharacterFacade character) { if (!stateMap.containsKey(character)) @@ -103,39 +137,92 @@ currentCharacter = character; //TODO: change this to use a SwingWorker //it might be possible to do this better - final Map<CharacterInfoTab, Hashtable<Object, Object>> states = stateMap.getMapFor(character); + Map<CharacterInfoTab, Hashtable<Object, Object>> states = stateMap.getMapFor(character); int selectedIndex = tabSelectionMap.get(character); - final CharacterInfoTab tab = (CharacterInfoTab) getComponentAt(selectedIndex); - tab.restoreModels(states.get(tab)); - setSelectedIndex(selectedIndex); + if (restoringTask != null && !restoringTask.isDone()) + { + restoringTask.cancel(true); + } + restoringTask = restoringThread.submit(new TabModelRestoringTask(states, selectedIndex)); + } - SwingUtilities.invokeLater(new Runnable() + private class TabModelRestoringTask implements Runnable, Comparator<CharacterInfoTab> + { + + private final Map<CharacterInfoTab, Hashtable<Object, Object>> states; + private final CharacterInfoTab firstTab; + private boolean terminated = false; + + public TabModelRestoringTask(Map<CharacterInfoTab, Hashtable<Object, Object>> states, int selectedIndex) { + this.states = states; + //restore the selected tab first so that user can see it + this.firstTab = (CharacterInfoTab) getComponentAt(selectedIndex); + firstTab.restoreModels(states.get(firstTab)); + setSelectedIndex(selectedIndex); + } - public void run() + public void run() + { + PriorityQueue<CharacterInfoTab> queue = new PriorityQueue<CharacterInfoTab>(states.keySet().size(), this); + queue.addAll(states.keySet()); + queue.remove(firstTab); + while (!queue.isEmpty()) { - for (CharacterInfoTab infoTab : states.keySet()) + final CharacterInfoTab infoTab = queue.poll(); + try { - if (tab == infoTab) + SwingUtilities.invokeAndWait(new Runnable() { - continue; - } - infoTab.restoreModels(states.get(infoTab)); + + public void run() + { + if (!terminated) + { + long starttime = System.nanoTime(); + infoTab.restoreModels(states.get(infoTab)); + timingMap.put(infoTab, System.nanoTime() - starttime); + } + } + + }); } + catch (InterruptedException ex) + { + //This means we've been cancelled so exit + terminated = true; + return; + } + catch (InvocationTargetException ex) + { + throw new UnreachableError(); + } + if (Thread.interrupted()) + { + terminated = true; + return; + } } + } - }); - } + public int compare(CharacterInfoTab o1, CharacterInfoTab o2) + { + if (timingMap.containsKey(o1) && timingMap.containsKey(o2)) + { + long dif = timingMap.get(o1) - timingMap.get(o2); + if (dif < 0) + { + return -1; + } + if (dif > 0) + { + return 1; + } + } + return 0; + } - private <T extends Component & CharacterInfoTab> void addTab(T tab) - { - TabTitle tabTitle = tab.getTabTitle(); - String title = (String) tabTitle.getValue(TabTitle.TITLE); - String tooltip = (String) tabTitle.getValue(TabTitle.TOOLTIP); - Icon icon = (Icon) tabTitle.getValue(TabTitle.ICON); - addTab(title, icon, tab, tooltip); - tabTitle.addPropertyChangeListener(new TabActionListener(tab)); } private class TabActionListener implements PropertyChangeListener This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |