/** * eAdventure (formerly <e-Adventure> and <e-Game>) is a research project of the * <e-UCM> research group. * * Copyright 2005-2010 <e-UCM> research group. * * You can access a list of all the contributors to eAdventure at: * http://e-adventure.e-ucm.es/contributors * * <e-UCM> is a research group of the Department of Software Engineering * and Artificial Intelligence at the Complutense University of Madrid * (School of Computer Science). * * C Profesor Jose Garcia Santesmases sn, * 28040 Madrid (Madrid), Spain. * * For more info please visit: <http://e-adventure.e-ucm.es> or * <http://www.e-ucm.es> * * **************************************************************************** * * This file is part of eAdventure, version 2.0 * * eAdventure 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. * * eAdventure 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 eAdventure. If not, see <http://www.gnu.org/licenses/>. */ package es.eucm.ead.editor.view.panel; import es.eucm.ead.editor.control.Controller; import es.eucm.ead.editor.model.EditorModel; import es.eucm.ead.editor.model.ModelEvent; import es.eucm.ead.editor.model.ModelEventUtils; import es.eucm.ead.editor.model.nodes.DependencyNode; import es.eucm.ead.editor.view.dock.ElementPanel; import es.eucm.ead.editor.view.generic.OptionPanel; import java.awt.BorderLayout; import java.util.ArrayList; import javax.swing.JLabel; import javax.swing.JPanel; /** * An elementPanel that can display anything. Intended as the common base * of all elementPanels. Panels should * <ul> * <li>register their OptionPanels in 'panels' during rebuild. * </ul> * * @author mfreire */ public abstract class AbstractElementPanel<T extends DependencyNode> extends JPanel implements ElementPanel<T>, EditorModel.ModelListener { protected T target; protected Controller controller; protected ArrayList<OptionPanel> panels = new ArrayList<OptionPanel>(); /** * Sets the target. Internally calls rebuild() (or cleanup & rebuild) * as necessary. */ @Override public void setTarget(T target) { if (this.target != null) { if (this.target.getId() == target.getId()) { // same target - nothing to do; return; } else { cleanup(); } } this.target = target; rebuild(); controller.getModel().addModelListener(this); } /** * Frees any resources and listeners used by this panel. Subclasses * that listen on anything but modelEvents should override this. */ @Override public void cleanup() { controller.getModel().removeModelListener(this); } /** * Sets the controller. Guaranteed to be called before setTarget. */ @Override public void setController(Controller controller) { this.controller = controller; } @Override public T getTarget() { return target; } /** * Reacts to a model change. If requiresRebuild(), then a full rebuild() * is triggered. Otherwise, if requiresRefresh(), the event will be * re-dispatched to all options. Finally, if requiresResurrection() * returns true, then target has been erased from the model; it is up to * us to restore it. * @param event */ @Override public void modelChanged(ModelEvent event) { if (requiresRebuild(event)) { cleanup(); rebuild(); controller.getModel().addModelListener(this); } else if (requiresRefresh(event)) { for (OptionPanel p : panels) { p.modelChanged(event); } } else if (requiresResurrection(event)) { removeAll(); setLayout(new BorderLayout()); add(new JLabel("Sorry, this view has been erased externally"), BorderLayout.CENTER); cleanup(); } } /** * Checks if a change requires a full rebuild of this view. Called from * modelChanged. * @param event describing the change * @return true if rebuild required */ protected boolean requiresRebuild(ModelEvent event) { return false; } /** * Checks if a change requires a refresh of this view. Called from * modelChanged. * @param event describing the change * @return true if refresh of fields required */ protected boolean requiresRefresh(ModelEvent event) { return ModelEventUtils.changes(event, target); } /** * Checks if a change completely invalidates this view. Called from * modelChanged. * @param event describing the change * @return true if resurrection required */ protected boolean requiresResurrection(ModelEvent event) { return ModelEventUtils.contains(event.getRemoved(), target); } /** * Rebuild contents after a (deep) change to the target. Smaller changes * should be managed automatically via ModelEvent dispatch from modelChanged(). */ protected abstract void rebuild(); }