/* * (c) Copyright 2010-2011 AgileBirds * * This file is part of OpenFlexo. * * OpenFlexo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenFlexo 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>. * */ package org.openflexo.components.browser; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.SwingUtilities; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; import org.openflexo.components.browser.BrowserFilter.BrowserFilterStatus; import org.openflexo.components.browser.view.BrowserView; import org.openflexo.foundation.FlexoEditor; import org.openflexo.foundation.FlexoException; import org.openflexo.foundation.FlexoModelObject; import org.openflexo.foundation.ie.IEWOComponent; import org.openflexo.foundation.rm.FlexoProject; import org.openflexo.selection.SelectionManager; import org.openflexo.selection.SelectionSynchronizedComponent; import org.openflexo.toolbox.PropertyChangeListenerRegistrationManager; import org.openflexo.view.controller.FlexoController; /** * Object that will act as a model for a JTree to represent a browsing perspective of a project * * @author sguerin * */ public abstract class ProjectBrowser extends DefaultTreeModel implements SelectionSynchronizedComponent, PropertyChangeListener { static final Logger logger = Logger.getLogger(ProjectBrowser.class.getPackage().getName()); private static final int DEFAULT_ROW_HEIGHT = 18; protected FlexoProject _project; protected FlexoEditor _editor; private BrowserElement _rootElement; private FlexoModelObject _rootObject = null; protected Map<BrowserElementType, BrowserFilterStatus> _filterStatus; protected Map<BrowserElementType, Boolean> _filterDeepBrowsing; protected Map<BrowserElementType, ElementTypeBrowserFilter> _filters; // private Vector<ElementTypeBrowserFilter> _elementTypeFilters; private List<CustomBrowserFilter> _customFilters; // hashtable where keys are FlexoModelObject objects while values are either // BrowserElement // or a Vector of BrowserElement private Map<FlexoModelObject, Object> _elements = null; private final List<ProjectBrowserListener> _browserListeners; private SelectionManager _selectionManager; private SelectionController _selectionController; private boolean _handlesControlPanel = true; private boolean isRebuildingStructure = false; private boolean holdStructure = false; int rowHeight = DEFAULT_ROW_HEIGHT; private FlexoController controller; protected PropertyChangeListenerRegistrationManager manager = new PropertyChangeListenerRegistrationManager(); @Deprecated public ProjectBrowser(FlexoProject project) { this(project, true); } @Deprecated public ProjectBrowser(FlexoProject project, boolean initNow) { this(project, null, initNow); } @Deprecated public ProjectBrowser(FlexoEditor editor, SelectionManager selectionManager) { this(editor != null ? editor.getProject() : null, selectionManager, true); _editor = editor; } @Deprecated public ProjectBrowser(FlexoEditor editor, SelectionManager selectionManager, boolean initNow) { this(editor != null ? editor.getProject() : null, selectionManager, initNow); _editor = editor; } @Deprecated public ProjectBrowser(FlexoProject project, SelectionManager selectionManager) { this(project, selectionManager, true); } @Deprecated public ProjectBrowser(FlexoProject project, SelectionManager selectionManager, boolean initNow) { super(null); _project = project; _filterStatus = new Hashtable<BrowserElementType, BrowserFilterStatus>(); _filterDeepBrowsing = new Hashtable<BrowserElementType, Boolean>(); _filters = new Hashtable<BrowserElementType, ElementTypeBrowserFilter>(); // _elementTypeFilters = new Vector<ElementTypeBrowserFilter>(); _browserListeners = new Vector<ProjectBrowserListener>(); _customFilters = new Vector<CustomBrowserFilter>(); configure(); if (selectionManager != null) { _selectionManager = selectionManager; _selectionManager.addToSelectionListeners(this); } _selectionController = new SelectionController.DefaultSelectionController(); if (initNow) { init(); } } @Deprecated protected ProjectBrowser(BrowserConfiguration configuration, SelectionManager selectionManager, boolean initNow) { super(null); _filterStatus = new Hashtable<BrowserElementType, BrowserFilterStatus>(); _filterDeepBrowsing = new Hashtable<BrowserElementType, Boolean>(); _filters = new Hashtable<BrowserElementType, ElementTypeBrowserFilter>(); // _elementTypeFilters = new Vector<ElementTypeBrowserFilter>(); _browserListeners = new Vector<ProjectBrowserListener>(); _customFilters = new Vector<CustomBrowserFilter>(); if (configuration != null) { _project = configuration.getProject(); _browserElementFactory = configuration.getBrowserElementFactory(); configuration.configure(this); } if (selectionManager != null) { _selectionManager = selectionManager; _selectionManager.addToSelectionListeners(this); } _selectionController = new SelectionController.DefaultSelectionController(); } protected ProjectBrowser(FlexoController controller) { this(null, controller); } protected ProjectBrowser(TreeConfiguration configuration, FlexoController controller) { super(null); this.controller = controller; if (configuration != null) { _browserElementFactory = configuration.getBrowserElementFactory(); } _filterStatus = new Hashtable<BrowserElementType, BrowserFilterStatus>(); _filterDeepBrowsing = new Hashtable<BrowserElementType, Boolean>(); _filters = new Hashtable<BrowserElementType, ElementTypeBrowserFilter>(); // _elementTypeFilters = new Vector<ElementTypeBrowserFilter>(); _browserListeners = new Vector<ProjectBrowserListener>(); _customFilters = new Vector<CustomBrowserFilter>(); if (configuration != null) { configuration.configure(this); } else { configure(); } if (controller != null && controller.getSelectionManager() != null) { _selectionManager = controller.getSelectionManager(); _selectionManager.addToSelectionListeners(this); } _selectionController = new SelectionController.DefaultSelectionController(); } public boolean showRootNode() { return true; } public boolean isRootCollapsable() { return false; } public void setSelectionManager(SelectionManager aSelectionManager) { _selectionManager = aSelectionManager; _selectionManager.addToSelectionListeners(this); } public void init() { if (getRootElement() != null) { setRoot(getRootElement()); } } private BrowserElementFactory _browserElementFactory = null; public BrowserElementFactory getBrowserElementFactory() { if (_browserElementFactory == null) { return DefaultBrowserElementFactory.DEFAULT_FACTORY; } else { return _browserElementFactory; } } protected void setBrowserElementFactory(BrowserElementFactory browserElementFactory) { _browserElementFactory = browserElementFactory; } public BrowserElement makeNewElement(FlexoModelObject object, BrowserElement parent) { return getBrowserElementFactory().makeNewElement(object, this, parent); } public void changeFilterStatus(BrowserElementType elementType, BrowserFilterStatus initialFilterStatus) { if (getFilterForElementType(elementType) != null) { getFilterForElementType(elementType).setInitialFilterStatus(initialFilterStatus); notifyListeners(new OptionalFilterAddedEvent(getFilterForElementType(elementType))); } } public void setFilterStatus(BrowserElementType elementType, BrowserFilterStatus status) { if (logger.isLoggable(Level.FINE)) { logger.fine(getClass().getName() + ": Setting filter status for " + elementType.getName() + " status=" + status); } _filterStatus.put(elementType, status); } public void setFilterStatus(BrowserElementType elementType, BrowserFilterStatus status, boolean isDeepBrowsing) { setFilterStatus(elementType, status); _filterDeepBrowsing.put(elementType, new Boolean(isDeepBrowsing)); } protected boolean activateBrowsingFor(BrowserElement newElement) { boolean returned = newElement.getBrowserFilter().getStatus() == BrowserFilterStatus.SHOW; if (logger.isLoggable(Level.FINE)) { logger.finer("activateBrowsingFor() " + newElement + " return " + returned); } return returned; } public boolean activateBrowsingFor(FlexoModelObject object) { BrowserElement browserElement = makeNewElement(object, null); boolean returned = activateBrowsingFor(browserElement); browserElement.delete(); return returned; } public ElementTypeBrowserFilter getFilterForObject(FlexoModelObject object) { BrowserElement browserElement = makeNewElement(object, null); ElementTypeBrowserFilter returned = getFilterForElement(browserElement); browserElement.delete(); return returned; } protected boolean requiresDeepBrowsing(BrowserElement newElement) { return newElement.getBrowserFilter().isDeepBrowsing(); } public ElementTypeBrowserFilter getFilterForElementType(BrowserElementType elementType) { return _filters.get(elementType); } public ElementTypeBrowserFilter getFilterForElement(BrowserElement element) { BrowserElementType elementType = element.getFilteredElementType(); if (elementType == null) { return null; } if (_filters.get(elementType) == null) { // first time we see this element type ElementTypeBrowserFilter newBrowserFilter = element.newBrowserFilter(_filterStatus.get(elementType)); /* * if (_filterStatus.get(elementType) != null) { newBrowserFilter.setStatus((_filterStatus.get(elementType))); if * (logger.isLoggable(Level.FINE)) logger.fine(getClass().getName() + ": Setting filter " + newBrowserFilter.getName() + * " status to " + (_filterStatus.get(elementType))); if ((newBrowserFilter.getStatus() == * BrowserFilterStatus.OPTIONAL_INITIALLY_HIDDEN) || (newBrowserFilter.getStatus() == * BrowserFilterStatus.OPTIONAL_INITIALLY_SHOWN)) { if (logger.isLoggable(Level.FINE)) logger.fine(getClass().getName() + * ": Adding optional filter " + newBrowserFilter.getName()); //_elementTypeFilters.add(newBrowserFilter); if * ((newBrowserFilter.getStatus() == BrowserFilterStatus.OPTIONAL_INITIALLY_HIDDEN)) { * newBrowserFilter.setStatus(BrowserFilterStatus.HIDE); } else if ((newBrowserFilter.getStatus() == * BrowserFilterStatus.OPTIONAL_INITIALLY_SHOWN)) { newBrowserFilter.setStatus(BrowserFilterStatus.SHOW); } // * notifyListeners(new OptionalFilterAddedEvent(newBrowserFilter)); } } */ if (_filterDeepBrowsing.get(elementType) != null) { newBrowserFilter.setDeepBrowsing(_filterDeepBrowsing.get(elementType).booleanValue()); } _filters.put(elementType, newBrowserFilter); notifyListeners(new OptionalFilterAddedEvent(newBrowserFilter)); if (logger.isLoggable(Level.FINE)) { logger.fine(getClass().getName() + ": Registering filter " + newBrowserFilter.getName()); } } return _filters.get(elementType); } @Deprecated public FlexoProject getProject() { return _project; } /* * Pour le moment parce que j'ai pas trop le temps, on reconstruit a chaque fois tout l'arbre. On pourrait faire un truc beaucoup plus * chiade avec des MutableNodeTree qui recoivent plein de DataModification toutes plus chiadees les unes que les autres, faire des * insert nodes, en notifier le modele, tout ca.... */ /** * Brutal update of the whole browser. You rarely need to invoke it, except when you have done big structural changes which are not * notified (for example filter status modification) */ public void update() { if (!SwingUtilities.isEventDispatchThread()) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { update(); } }); return; } Vector<FlexoModelObject> selectionBeforeUpdate = null; if (getSelectedObjects() != null) { selectionBeforeUpdate = new Vector<FlexoModelObject>(getSelectedObjects()); if (logger.isLoggable(Level.FINE)) { logger.fine("Before update, selected objects are " + selectionBeforeUpdate); } } Vector<FlexoModelObject> expandedObjects = null; if (leadingView != null) { expandedObjects = new Vector<FlexoModelObject>(); Vector<BrowserElement> expandedElements = leadingView.getExpandedElements(); for (Enumeration<BrowserElement> en = expandedElements.elements(); en.hasMoreElements();) { BrowserElement next = en.nextElement(); expandedObjects.add(next.getObject()); } if (logger.isLoggable(Level.FINE)) { logger.fine("Before update, expanded objects are " + expandedObjects); } } rebuildTree(); if (logger.isLoggable(Level.FINE)) { logger.fine("Notifying expansions"); } if (getRootObject() != null) { notifyListeners(new ExpansionNotificationEvent()); if (selectionBeforeUpdate != null) { for (Enumeration<FlexoModelObject> en = selectionBeforeUpdate.elements(); en.hasMoreElements();) { FlexoModelObject next = en.nextElement(); if (logger.isLoggable(Level.FINE)) { logger.fine("Select " + next); } fireObjectSelected(next); } } if (expandedObjects != null) { for (Enumeration<FlexoModelObject> en = expandedObjects.elements(); en.hasMoreElements();) { FlexoModelObject next = en.nextElement(); if (logger.isLoggable(Level.FINE)) { logger.fine("Expand " + next); } expand(next, false); // expandAll(next); } } } } /* * private void expandAll(FlexoModelObject object) { BrowserElement[] elements = elementForObject(object); for (int i=0; * i<elements.length; i++) { BrowserElement el = elements[i]; for (int j=0; j<el.getChildCount(); j++) { BrowserElement el2 = * (BrowserElement)el.getChildAt(j); expand(el2.getObject()); } } } */ private BrowserView leadingView; private boolean deleted; protected BrowserView getLeadingView() { return leadingView; } public void setLeadingView(BrowserView leadingView) { this.leadingView = leadingView; } protected Vector<BrowserElement> getSelectedElements() { if (leadingView != null) { return leadingView.getSelectedElements(); } return null; } protected Vector<FlexoModelObject> getSelectedObjects() { if (leadingView != null) { return leadingView.getSelectedObjects(); } return null; } protected Vector<FlexoModelObject> getExpandedObjects() { Vector<FlexoModelObject> expandedObjects = new Vector<FlexoModelObject>(); if (leadingView != null) { Vector<BrowserElement> expandedElements = leadingView.getExpandedElements(); for (Enumeration<BrowserElement> en = expandedElements.elements(); en.hasMoreElements();) { BrowserElement next = en.nextElement(); expandedObjects.add(next.getObject()); } if (logger.isLoggable(Level.FINE)) { logger.fine("Before update, expanded objects are " + expandedObjects); } } return expandedObjects; } /** * Update the TreeModel juste below element * * @param element */ protected void update(BrowserElement element) { if (logger.isLoggable(Level.FINE)) { logger.fine("Update tree from " + element + " in ProjectBrowser"); } reload(element); } public BrowserElement getRootElement() { if (_rootElement == null && this.getRootObject() != null) { rebuildTree(); } return _rootElement; } /** * This has no modifier because sub-classes should call this directly. */ void rebuildTree() { if (!SwingUtilities.isEventDispatchThread()) { try { SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { if (logger.isLoggable(Level.FINE)) { logger.fine("refreshWhenPossible() DO IT NOW"); } rebuildTree(); } }); } catch (InterruptedException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return; } if (logger.isLoggable(Level.FINE)) { logger.fine("Rebuild whole tree in ProjectBrowser"); } setIsRebuildingStructure(); try { if (_elements != null) { clearTree(); } if (getRootObject() != null) { _elements = new Hashtable<FlexoModelObject, Object>(); setRoot(_rootElement = makeNewElement(getRootObject(), null)); } else { setRoot(null); } } finally { resetIsRebuildingStructure(); } } public void setRootObject(FlexoModelObject aRootObject) { if (logger.isLoggable(Level.FINE)) { logger.fine("Setting root object to be " + aRootObject); } if (this._rootObject != null && this._rootObject.getDeletedProperty() != null) { manager.removeListener(this._rootObject.getDeletedProperty(), this, this._rootObject); } _rootObject = aRootObject; if (this._rootObject != null && this._rootObject.getDeletedProperty() != null) { manager.addListener(this._rootObject.getDeletedProperty(), this, this._rootObject); } update(); if (_rootObject != null && !isRootCollapsable()) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { if (deleted) { return; } if (showRootNode()) { expand(_rootObject, false); } else { BrowserElement[] elements = elementForObject(_rootObject); List<BrowserElement> children = new ArrayList<BrowserElement>(); for (BrowserElement el : elements) { Enumeration<BrowserElement> en = el.children(); while (en.hasMoreElements()) { children.add(en.nextElement()); } } notifyListeners(new ExpansionNotificationEvent(children.toArray(new BrowserElement[children.size()]), true)); } } }); } } public FlexoModelObject getRootObject() { if (_rootObject != null) { return _rootObject; } else { return getDefaultRootObject(); } } public void delete() { if (logger.isLoggable(Level.FINE)) { logger.fine("Delete browser " + getClass().getName()); } deleted = true; manager.delete(); clearTree(); _project = null; _rootElement = null; _filterStatus.clear(); _filterDeepBrowsing.clear(); _filters.clear(); _browserListeners.clear(); _selectionManager = null; controller = null; } private void clearTree() { if (_rootElement != null) { _rootElement.delete(); } for (Object obj : new ArrayList<Object>(_elements.values())) { if (obj instanceof BrowserElement) { ((BrowserElement) obj).delete(); } else if (obj instanceof Vector) { Vector<BrowserElement> elementList = (Vector<BrowserElement>) obj; for (Enumeration<BrowserElement> e2 = elementList.elements(); e2.hasMoreElements();) { BrowserElement element = e2.nextElement(); element.delete(); } } } _elements.clear(); _expansionSynchronizedElements.removeAllElements(); _expansionSynchronizedElements = new Vector<ExpansionSynchronizedElement>(); _elements = null; } Vector<ExpansionSynchronizedElement> _expansionSynchronizedElements = new Vector<ExpansionSynchronizedElement>(); protected void registerElementForObject(BrowserElement element, FlexoModelObject modelObject) { if (element == null) { if (logger.isLoggable(Level.WARNING)) { logger.warning("Try to register a null element for " + modelObject + " in ProjectBrowser !"); } return; } if (_elements == null) { if (logger.isLoggable(Level.WARNING)) { logger.warning("_elements is null in browser " + getClass().getName()); } return; } Object existingValue = _elements.get(modelObject); if (existingValue != null) { if (existingValue instanceof BrowserElement) { Vector<BrowserElement> newVector = new Vector<BrowserElement>(); newVector.add((BrowserElement) existingValue); newVector.add(element); _elements.put(modelObject, newVector); } else if (existingValue instanceof Vector) { Vector<BrowserElement> newVector = (Vector<BrowserElement>) _elements.get(modelObject); newVector.add(element); } else { if (logger.isLoggable(Level.WARNING)) { logger.warning("Found unexpected " + existingValue.getClass().getName() + " in ProjectBrowser !"); } } } else { _elements.put(modelObject, element); } if (element instanceof ExpansionSynchronizedElement) { // logger.info("What about "+element+" isExpansionSynchronizedWithData()="+((ExpansionSynchronizedElement) // element).isExpansionSynchronizedWithData()); if (((ExpansionSynchronizedElement) element).isExpansionSynchronizedWithData()) { _expansionSynchronizedElements.add((ExpansionSynchronizedElement) element); } } if (element.getSelectableObject() != modelObject) { registerElementForObject(element, element.getSelectableObject()); } } protected void unregisterElementForObject(BrowserElement element, FlexoModelObject modelObject) { if (_elements == null) { return; } if (element.getSelectableObject() != modelObject) { unregisterElementForObject(element, element.getSelectableObject()); } Object existingValue = _elements.get(modelObject); if (existingValue != null) { if (existingValue instanceof BrowserElement) { _elements.remove(modelObject); } else if (existingValue instanceof Vector) { Vector newVector = (Vector) _elements.get(modelObject); newVector.remove(element); } else { if (logger.isLoggable(Level.WARNING)) { logger.warning("Found unexpected " + existingValue.getClass().getName() + " in ProjectBrowser !"); } } } if (element instanceof ExpansionSynchronizedElement) { _expansionSynchronizedElements.remove(element); } } public boolean isExpansionSynchronizedElement(BrowserElement element) { return element instanceof ExpansionSynchronizedElement && _expansionSynchronizedElements.contains(element); } /** * Return an array of TreePath of all paths where this observable is defined * * @param object * @return */ public TreePath[] treePathForObject(FlexoModelObject object) { Vector<TreePath> builtVector = new Vector<TreePath>(); if (object == null) { return null; } if (_elements == null) { return null; } Object found = _elements.get(object); if (found instanceof BrowserElement) { BrowserElement element = (BrowserElement) found; builtVector.add(element.getTreePath()); } else if (found instanceof Vector) { Vector<BrowserElement> elementList = (Vector<BrowserElement>) found; for (Enumeration<BrowserElement> e = elementList.elements(); e.hasMoreElements();) { BrowserElement element = e.nextElement(); builtVector.add(element.getTreePath()); } } else if (found != null) { if (logger.isLoggable(Level.WARNING)) { logger.warning("Found unexpected " + found.getClass().getName() + " in ProjectBrowser !"); } return null; } else { if (logger.isLoggable(Level.FINE)) { logger.fine("Found null in ProjectBrowser for object " + object); } return null; } TreePath[] returned = new TreePath[builtVector.size()]; for (int i = 0; i < builtVector.size(); i++) { returned[i] = builtVector.get(i); } return returned; } /** * Return an array of TreePath of all paths where this observable is defined * * @param object * @return */ protected BrowserElement[] elementForObject(FlexoModelObject object) { List<BrowserElement> builtVector = new ArrayList<BrowserElement>(); Object found = object != null ? _elements.get(object) : null; if (found instanceof BrowserElement) { BrowserElement element = (BrowserElement) found; builtVector.add(element); } else if (found instanceof Vector) { builtVector.addAll((Vector) found); } else if (found != null) { if (logger.isLoggable(Level.WARNING)) { logger.warning("Found unexpected " + found.getClass().getName() + " in ProjectBrowser !"); } } else { if (logger.isLoggable(Level.FINE)) { logger.fine("Found null in ProjectBrowser for object " + object); } } return builtVector.toArray(new BrowserElement[builtVector.size()]); } @Deprecated public FlexoModelObject getDefaultRootObject() { return null; } public abstract void configure(); @Override public Object getChild(Object parent, int index) { return ((BrowserElement) parent).getChildAt(index); } @Override public int getChildCount(Object parent) { return ((BrowserElement) parent).getChildCount(); } @Override public boolean isLeaf(Object node) { return ((BrowserElement) node).isLeaf(); } @Override public int getIndexOfChild(Object parent, Object child) { return ((BrowserElement) parent).getIndex((TreeNode) child); } public synchronized void addBrowserListener(ProjectBrowserListener l) { _browserListeners.add(l); } public synchronized void deleteBrowserListener(ProjectBrowserListener l) { _browserListeners.remove(l); } public void notifyExpansionChanged(final ExpansionSynchronizedElement element) { if (element instanceof BrowserElement) { if (((BrowserElement) element).refreshHasBeenRequested()) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { if (!((BrowserElement) element).isDeleted()) { notifyListeners(new ExpansionNotificationEvent(element)); } } }); return; } } notifyListeners(new ExpansionNotificationEvent(element)); } public synchronized void notifyListeners(BrowserEvent event) { // TODO: Fix this. It seems that sole Listeners (BrowserView) are removing/adding themselves // during the notification phase (for ExpansionNotificationEvent, for example) for (ProjectBrowserListener l : new ArrayList<ProjectBrowserListener>(_browserListeners)) { if (event instanceof OptionalFilterAddedEvent) { l.optionalFilterAdded((OptionalFilterAddedEvent) event); } else if (event instanceof ObjectAddedToSelectionEvent) { l.objectAddedToSelection((ObjectAddedToSelectionEvent) event); } else if (event instanceof ObjectRemovedFromSelectionEvent) { l.objectRemovedFromSelection((ObjectRemovedFromSelectionEvent) event); } else if (event instanceof SelectionClearedEvent) { l.selectionCleared((SelectionClearedEvent) event); } else if (event instanceof ExpansionNotificationEvent) { l.notifyExpansions((ExpansionNotificationEvent) event); } else if (event instanceof EnableExpandingSynchronizationEvent) { l.enableExpandingSynchronization((EnableExpandingSynchronizationEvent) event); } else if (event instanceof DisableExpandingSynchronizationEvent) { l.disableExpandingSynchronization((DisableExpandingSynchronizationEvent) event); } } } public class BrowserEvent { } public class OptionalFilterAddedEvent extends BrowserEvent { private final ElementTypeBrowserFilter _browserFilter; protected OptionalFilterAddedEvent(ElementTypeBrowserFilter browserFilter) { super(); _browserFilter = browserFilter; } public ElementTypeBrowserFilter getFilter() { return _browserFilter; } } public class ObjectAddedToSelectionEvent extends BrowserEvent { private final FlexoModelObject _object; protected ObjectAddedToSelectionEvent(FlexoModelObject object) { super(); if (logger.isLoggable(Level.FINE)) { logger.fine("ObjectAddedToSelectionEvent"); } _object = object; } public FlexoModelObject getAddedObject() { return _object; } } public class ObjectRemovedFromSelectionEvent extends BrowserEvent { private final FlexoModelObject _object; protected ObjectRemovedFromSelectionEvent(FlexoModelObject object) { super(); if (logger.isLoggable(Level.FINE)) { logger.fine("ObjectRemovedFromSelectionEvent"); } _object = object; } public FlexoModelObject getRemovedObject() { return _object; } } public class SelectionClearedEvent extends BrowserEvent { protected SelectionClearedEvent() { super(); if (logger.isLoggable(Level.FINE)) { logger.fine("SelectionClearedEvent"); } } } public class EnableExpandingSynchronizationEvent extends BrowserEvent { protected EnableExpandingSynchronizationEvent() { super(); } } public class DisableExpandingSynchronizationEvent extends BrowserEvent { protected DisableExpandingSynchronizationEvent() { super(); } } public class ExpansionNotificationEvent extends BrowserEvent { protected List<TreePath> _pathsToExpand; protected List<TreePath> _pathsToCollapse; public ExpansionNotificationEvent() { super(); _pathsToExpand = new Vector<TreePath>(); _pathsToCollapse = new Vector<TreePath>(); for (Enumeration<ExpansionSynchronizedElement> e = _expansionSynchronizedElements.elements(); e.hasMoreElements();) { ExpansionSynchronizedElement element = e.nextElement(); TreePath path = element.getTreePath(); if (element.isExpanded()) { _pathsToExpand.add(path); } else { _pathsToCollapse.add(path); } } } public ExpansionNotificationEvent(ExpansionSynchronizedElement element) { super(); _pathsToExpand = new Vector<TreePath>(); _pathsToCollapse = new Vector<TreePath>(); TreePath path = ((BrowserElement) element).getTreePath(); if (element.isExpanded()) { _pathsToExpand.add(path); } else { _pathsToCollapse.add(path); } } public ExpansionNotificationEvent(BrowserElement[] elements, boolean expand) { super(); _pathsToExpand = new ArrayList<TreePath>(); _pathsToCollapse = new ArrayList<TreePath>(); for (int i = 0; i < elements.length; i++) { BrowserElement element = elements[i]; TreePath path = element.getTreePath(); if (expand) { _pathsToExpand.add(path); } else { _pathsToCollapse.add(path); } } } public List<TreePath> pathsToExpand() { return _pathsToExpand; } public List<TreePath> pathsToCollapse() { return _pathsToCollapse; } } /** * Adds specified object to selection * * @param object */ @Override public void fireObjectSelected(FlexoModelObject object) { if (object instanceof IEWOComponent) { fireObjectSelected(((IEWOComponent) object).getComponentDefinition()); return; } if (logger.isLoggable(Level.FINE)) { logger.fine("ProjectBrowser.addToSelection() " + object); } notifyListeners(new ObjectAddedToSelectionEvent(object)); } /** * Removes specified object from selection * * @param object */ @Override public void fireObjectDeselected(FlexoModelObject object) { if (object instanceof IEWOComponent) { fireObjectDeselected(((IEWOComponent) object).getComponentDefinition()); return; } if (logger.isLoggable(Level.FINE)) { logger.fine("ProjectBrowser.removeFromSelection() " + object); } notifyListeners(new ObjectRemovedFromSelectionEvent(object)); } /** * Clear selection */ @Override public void fireResetSelection() { notifyListeners(new SelectionClearedEvent()); } /** * Update selection */ public void updateSelection() { if (_selectionManager != null) { _selectionManager.fireUpdateSelection(this); } } /** * Notify that the selection manager is performing a multiple selection */ @Override public void fireBeginMultipleSelection() { notifyListeners(new DisableExpandingSynchronizationEvent()); } /** * Notify that the selection manager has finished to perform a multiple selection */ @Override public void fireEndMultipleSelection() { notifyListeners(new EnableExpandingSynchronizationEvent()); } /** * Notify that selection must be saved to be restored later (modification of the structure) */ /* * public void saveSelection() { notifyListeners(new SaveSelectionEvent()); } */ /** * Notify that selection must be saved to be restored later (modification of the structure) */ /* * public void restoreSelection() { notifyListeners(new RestoreSelectionEvent()); } */ @Override public SelectionManager getSelectionManager() { return _selectionManager; } public void focusOn(FlexoModelObject object) { // logger.info("Focus on "+object); // fireResetSelection(); // fireObjectSelected(object); resetSelection(); addToSelected(object); } public void focusOff(FlexoModelObject object) { collapse(object); } public void expand(FlexoModelObject object, boolean synchronizeExpansion) { BrowserElement[] elements = elementForObject(object); if (elements == null) { // logger.info("Elements representing object "+object+" could not be // found"); } else { if (!synchronizeExpansion) { for (BrowserElement e : elements) { e.enableSynchronizeExpansion(); } } notifyListeners(new ExpansionNotificationEvent(elements, true)); if (!synchronizeExpansion) { for (BrowserElement e : elements) { e.disableSynchronizeExpansion(); } } } } public void collapse(FlexoModelObject object) { BrowserElement[] elements = elementForObject(object); if (elements != null) { notifyListeners(new ExpansionNotificationEvent(elements, false)); } } @Override public void valueForPathChanged(TreePath path, Object newValue) { BrowserElement element = (BrowserElement) path.getLastPathComponent(); if (element.isNameEditable()) { try { element.setName((String) newValue); } catch (FlexoException e) { // TODO handle those error properly // Instead of doing setName() on the model, use a FlexoAction // This is the FlexoAction exception handler that will catch // those errors !!! e.printStackTrace(); } } } public Iterator<FlexoModelObject> getAllObjects() { return _elements.keySet().iterator(); } public SelectionController getSelectionController() { return _selectionController; } public void setSelectionController(SelectionController selectionController) { _selectionController = selectionController; } public boolean handlesControlPanel() { return _handlesControlPanel; } public void setHandlesControlPanel(boolean handlesControlPanel) { _handlesControlPanel = handlesControlPanel; } public Vector<ElementTypeBrowserFilter> getConfigurableElementTypeFilters() { Vector<ElementTypeBrowserFilter> returned = new Vector<ElementTypeBrowserFilter>(); for (BrowserElementType t : _filters.keySet()) { ElementTypeBrowserFilter f = _filters.get(t); if (f.getInitialFilterStatus() == BrowserFilterStatus.OPTIONAL_INITIALLY_HIDDEN || f.getInitialFilterStatus() == BrowserFilterStatus.OPTIONAL_INITIALLY_SHOWN) { returned.add(f); } } return returned; } @Override public Vector<FlexoModelObject> getSelection() { if (getSelectionManager() != null) { return getSelectionManager().getSelection(); } return null; } @Override public void resetSelection() { if (getSelectionManager() != null) { getSelectionManager().resetSelection(); } else { fireResetSelection(); } } @Override public void addToSelected(FlexoModelObject object) { if (mayRepresents(object)) { if (getSelectionManager() != null) { getSelectionManager().addToSelected(object); } else { fireObjectSelected(object); } } } @Override public void removeFromSelected(FlexoModelObject object) { if (mayRepresents(object)) { if (getSelectionManager() != null) { getSelectionManager().removeFromSelected(object); } else { fireObjectDeselected(object); } } } @Override public void addToSelected(Vector<? extends FlexoModelObject> objects) { if (getSelectionManager() != null) { getSelectionManager().addToSelected(objects); } else { fireBeginMultipleSelection(); for (Enumeration<? extends FlexoModelObject> en = objects.elements(); en.hasMoreElements();) { FlexoModelObject next = en.nextElement(); fireObjectSelected(next); } fireEndMultipleSelection(); } } @Override public void removeFromSelected(Vector<? extends FlexoModelObject> objects) { if (getSelectionManager() != null) { getSelectionManager().removeFromSelected(objects); } else { fireBeginMultipleSelection(); for (Enumeration<? extends FlexoModelObject> en = objects.elements(); en.hasMoreElements();) { FlexoModelObject next = en.nextElement(); fireObjectDeselected(next); } fireEndMultipleSelection(); } } @Override public void setSelectedObjects(Vector<? extends FlexoModelObject> objects) { if (getSelectionManager() != null) { getSelectionManager().setSelectedObjects(objects); } else { resetSelection(); if (objects != null) { addToSelected(objects); } } } @Override public FlexoModelObject getFocusedObject() { if (getSelectionManager() != null) { return getSelectionManager().getFocusedObject(); } return null; } @Override public boolean mayRepresents(FlexoModelObject anObject) { if (anObject instanceof IEWOComponent) { return _elements.get(anObject) != null || mayRepresents(((IEWOComponent) anObject).getComponentDefinition()); } return _elements != null && anObject != null && _elements.get(anObject) != null; } public List<CustomBrowserFilter> getCustomFilters() { return _customFilters; } public void setCustomFilters(Vector<CustomBrowserFilter> customFilters) { _customFilters = customFilters; } public void addToCustomFilters(CustomBrowserFilter aCustomFilter) { _customFilters.add(aCustomFilter); } public void removeFromCustomFilters(CustomBrowserFilter aCustomFilter) { _customFilters.remove(aCustomFilter); } // TODO: should NOT be handled at this level public static enum DMViewMode { Repositories, Packages, Hierarchy, Diagrams } // TODO: should NOT be handled at this level private DMViewMode _viewMode = DMViewMode.Repositories; // TODO: should NOT be handled at this level public DMViewMode getDMViewMode() { return _viewMode; } // TODO: should NOT be handled at this level public void setDMViewMode(DMViewMode viewMode) { if (_viewMode != viewMode) { _viewMode = viewMode; update(); } } // TODO: should NOT be handled at this level public static enum OEViewMode { NoHierarchy, PartialHierarchy, FullHierarchy } // TODO: should NOT be handled at this level private OEViewMode _oeViewMode = OEViewMode.NoHierarchy; // TODO: should NOT be handled at this level public OEViewMode getOEViewMode() { return _oeViewMode; } // TODO: should NOT be handled at this level public void setOEViewMode(OEViewMode viewMode) { if (_oeViewMode != viewMode) { _oeViewMode = viewMode; update(); } } // TODO: should NOT be handled at this level private boolean _showOnlyAnnotationProperties = false; // TODO: should NOT be handled at this level public boolean showOnlyAnnotationProperties() { return _showOnlyAnnotationProperties; } // TODO: should NOT be handled at this level public void setShowOnlyAnnotationProperties(boolean showOnlyAnnotationProperties) { _showOnlyAnnotationProperties = showOnlyAnnotationProperties; } @Override public void reload(TreeNode node) { if (node instanceof BrowserElement && ((BrowserElement) node).isDeleted()) { return; } setHoldStructure(); super.reload(node); resetHoldStructure(); } public boolean isRebuildingStructure() { return isRebuildingStructure; } public void setIsRebuildingStructure() { isRebuildingStructure = true; } public void resetIsRebuildingStructure() { isRebuildingStructure = false; } public boolean isHoldingStructure() { return holdStructure; } public void setHoldStructure() { holdStructure = true; } public void resetHoldStructure() { holdStructure = false; } /** * Return editor when available False otherwise * * @return */ public FlexoEditor getEditor() { if (controller != null) { return controller.getEditor(); } return _editor; } public FlexoController getController() { return controller; } public int getRowHeight() { return rowHeight; } public void setRowHeight(int rowHeight) { this.rowHeight = rowHeight; } @Override public void propertyChange(PropertyChangeEvent evt) { if (evt.getSource() == this._rootObject && evt.getPropertyName().equals(this._rootObject.getDeletedProperty())) { setRootObject(null); } } public boolean showOptionsButton() { return true; } }