/* * Copyright 2013 Simon Thiel * * This file is part of SitJar. * * SitJar 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. * * SitJar 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with SitJar. If not, see <http://www.gnu.org/licenses/lgpl.txt>. * */ package sit.gui; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JPanel; import sit.sstl.HashMapSet; import sit.sstl.ObjectWithKey; /** * * @author simon * @param <K> * @param <T> */ public class ViewSetPanel<K extends Enum,T extends ViewSetEntry<K>>{ public static final int MODE_CREATE_ON_VIEW=0; public static final int MODE_CREATE_ONCE=1; public static class ViewSetPanelException extends RuntimeException { public ViewSetPanelException(String message) { super(message); } } class ViewSetEntryContainer implements ObjectWithKey<K>{ private final Class entryClass; private final K key; private T viewEntry; private boolean firstView = true; public ViewSetEntryContainer(K key, Class viewEntryClass){ this.entryClass = viewEntryClass; this.key = key; this.viewEntry = null; } public ViewSetEntryContainer(K key, T viewEntry) { this.key = key; this.viewEntry = viewEntry; this.entryClass = viewEntry.getClass(); } public void setFirstView(boolean firstView) { this.firstView = firstView; } public boolean isFirstView() { return firstView; } public T getViewEntry() { return viewEntry; } public K getKey() { return key; } private void checkAndInstantiate() { if (viewEntry==null){ try { viewEntry = (T) entryClass.newInstance(); } catch (InstantiationException ex) { Logger.getLogger(ViewSetPanel.class.getName()).log(Level.SEVERE, null, ex); } catch (IllegalAccessException ex) { Logger.getLogger(ViewSetPanel.class.getName()).log(Level.SEVERE, null, ex); } } } } //the root panel private final JPanel panel; private final HashMapSet<K, ViewSetEntryContainer> views = new HashMapSet(); private ViewSetEntryContainer currentView = null; private final int mode; public ViewSetPanel(JPanel panel, int mode) { this.panel = panel; panel.setLayout(new GridBagLayout()); this.mode = mode; } public ViewSetPanel(int mode) { this(new JPanel(), mode); } public ViewSetPanel(JPanel panel) { this(panel, MODE_CREATE_ONCE); } public ViewSetPanel() { this(new JPanel()); } public synchronized void registerView(K key, Class<? extends T> viewClass){ views.add(new ViewSetEntryContainer(key, viewClass)); } public synchronized void registerView(Map<K, Class<? extends T>> viewMap){ for (Map.Entry<K, Class<? extends T>> entry : viewMap.entrySet()){ this.views.add(new ViewSetEntryContainer(entry.getKey(), entry.getValue())); } } public synchronized void registerView(T view){ views.add(new ViewSetEntryContainer(view.getKey(), view)); } public synchronized void registerViews(T [] views){ for (T view : views){ this.views.add(new ViewSetEntryContainer(view.getKey(), view)); } } public K getCurrentViewType(){ return currentView.getKey(); } public synchronized void switchToViewType(K viewType){ updateView(viewType); } private void updateView(K viewType) { if ((currentView!=null) && (currentView.getKey()==viewType)){ return; //view was shown already } if (!views.contains(viewType)){ throw new RuntimeException("View for type: "+viewType+ " has not been registered!"); } ViewSetEntryContainer newView = getViewForType(viewType); //call onHide on previous view if (this.currentView!=null){ this.currentView.getViewEntry().onHide(); } this.currentView = newView; //call onShow for new view this.currentView.getViewEntry().onShow(this.currentView.isFirstView()); this.currentView.setFirstView(false); panel.removeAll(); panel.add(currentView.getViewEntry().getComponent(), getGridBackConstraints()); //repaint panel panel.revalidate(); panel.repaint(); } public JPanel getPanel() { return panel; } private GridBagConstraints getGridBackConstraints() { GridBagConstraints gridBagConstraints; gridBagConstraints = new GridBagConstraints(); gridBagConstraints.gridx = 0; gridBagConstraints.gridy = 0; gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH; gridBagConstraints.anchor = GridBagConstraints.NORTHWEST; gridBagConstraints.weightx = 1.0; gridBagConstraints.weighty = 1.0; gridBagConstraints.ipadx=5; gridBagConstraints.ipady=5; return gridBagConstraints; } /** * ATTENTION this method returns the actual component - changes will be reflected accordingly * @param viewType * @return */ public synchronized T getView(K viewType) { if (currentView.getKey()==viewType){ return currentView.getViewEntry(); } if (mode==MODE_CREATE_ON_VIEW){ throw new ViewSetPanelException("getView for "+viewType+" but current view: "+currentView.getKey() +"\nIn MODE_CREATE_ON_VIEW mode: getView only defined for current view."); } return views.get(viewType).getViewEntry(); } private ViewSetEntryContainer getViewForType(K viewType) { ViewSetEntryContainer result = views.get(viewType); //in case of mode == MODE_CREATE_ON_VIEW make a copy so, it can be garbaged after hiding the view; if (mode==MODE_CREATE_ON_VIEW){ result = new ViewSetEntryContainer(result.key, result.entryClass); } //intantiate view if not already result.checkAndInstantiate(); return result; } }