/* * This file is part of the OSMembrane project. * More informations under www.osmembrane.de * * The project is licensed under the GNU GENERAL PUBLIC LICENSE 3.0. * for more details about the license see http://www.osmembrane.de/license/ * * Source: $HeadURL$ ($Revision$) * Last changed: $Date$ */ package de.osmembrane.view; import java.util.HashMap; import java.util.Map; import java.util.Observable; import java.util.Observer; import javax.swing.SwingUtilities; import de.osmembrane.Application; import de.osmembrane.Main; import de.osmembrane.controller.ActionRegistry; import de.osmembrane.exceptions.ControlledException; import de.osmembrane.exceptions.ExceptionSeverity; import de.osmembrane.model.settings.SettingsObserverObject; import de.osmembrane.tools.I18N; import de.osmembrane.view.dialogs.ExceptionDialog; import de.osmembrane.view.frames.MainFrame; import de.osmembrane.view.interfaces.IView; /** * The view registry implements the View-Handler pattern to organize the * {@link IView}s. * * @author tobias_kuhn * */ public class ViewRegistry extends Observable implements Observer { /** * implements the error-handling dialog Note: This is important to be static * and external to the {@link ViewRegistry} instance, because anyway else * occurring exceptions during anything static would cause an * {@link ExceptionInInitializerError} because the error handling would * require the ViewRegistry instance to be available. */ private static ExceptionDialog exceptionDialog; /** * implements the Singleton pattern */ private static ViewRegistry instance = new ViewRegistry(); /** * internal storage of the views, indexed by class */ private Map<Class<? extends IView>, IView> views = new HashMap<Class<? extends IView>, IView>(); /** * initializes the view registry */ private ViewRegistry() { } /** * * @return the one and only instance of {@link ViewRegistry} */ public static ViewRegistry getInstance() { return instance; } /** * Adds a view to the registry * * @param view * IView to add */ public void register(IView view) { views.put(view.getClass(), view); } /** * Returns a view from the registry. If not already registered, creates it * and registers it. * * @param clazz * desired class to return * @return the registered object for that class */ public IView get(Class<? extends IView> clazz) { return views.get(clazz); } /** * Returns a view from the registry. If not already registered, creates it * and registers it. Tries to cast it to castTo. Throws * {@link ClassCastException}, if not possible. Causes critical failure, if * break-in is tried (when clazz is not an interface). * * @param castTo * the desired type to return * @param clazz * desired <b>interface</b> to return * @return the registered object for that class casted to type castTo * @throws ClassCastException * if clazz cannot be of type castTo. Test clazz instanceof * castTo, if you want to make sure (Java 1.6 Generics don't * support this) */ @SuppressWarnings("unchecked") public <T extends IView> T getCasted(Class<? extends IView> clazz, Class<? extends T> castTo) { // prevent break-ins if (!castTo.isInterface()) { Application.handleException(new ControlledException(this, ExceptionSeverity.CRITICAL_UNEXPECTED_BEHAVIOR, I18N .getInstance().getString("View.IllegalCast"))); } IView result = get(clazz); return (T) result; } @Override public void update(Observable o, Object arg) { // if this means language change, do your worst if (arg instanceof SettingsObserverObject) { SettingsObserverObject soo = (SettingsObserverObject) arg; // language change switch (soo.getChangedEntry()) { case ACTIVE_LANGUAGE: case ACTIVE_PLAF: exceptionDialog = null; for (IView iv : views.values()) { iv.hideWindow(); iv.dispose(); } views.clear(); deleteObservers(); // if Java GC understands that, I'm impressed System.gc(); ActionRegistry.getInstance().reinitialize(); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { Main.getApplication().showMainFrame(); } }); break; } /* switch */ } // forward update() for Model classes setChanged(); notifyObservers(arg); } /** * Note: The {@link ViewRegistry} can be exchanged along with all view * components, so it has to identify its main window for the purpose of * showing this window at startup. * * @param createIfRequired * if set to false, the mainFrame will not be created and the * return value will be null, true means default behavior * * @return the {@link MainFrame} of this view component or null, if * dontCreate and MainFrame wasn't initialized */ public IView getMainFrame(boolean createIfRequired) { if (!createIfRequired && (views.get(MainFrame.class) == null)) { return null; } return get(MainFrame.class); } /** * Displays an occurred exception using the {@link ExceptionDialog}. This * method should not be called directly. Use the * {@link Application#handleException} method instead. * * @param t * {@link Throwable} that caused the exception * @param severity * indicates what happened and how fatal it is * @param causingObject * object that caused the */ public static void showException(Throwable t, ExceptionSeverity severity, Object causingObject) { if (exceptionDialog == null) { exceptionDialog = new ExceptionDialog(null); } exceptionDialog.showException(t, severity, causingObject); } }