/*
* Licensed Materials - Property of Perforce Software, Inc.
* © Copyright Perforce Software, Inc. 2014, 2021
* © Copyright IBM Corp. 2009, 2014
* © Copyright ILOG 1996, 2009
* All Rights Reserved.
*
* Note to U.S. Government Users Restricted Rights:
* The Software and Documentation were developed at private expense and
* are "Commercial Items" as that term is defined at 48 CFR 2.101,
* consisting of "Commercial Computer Software" and
* "Commercial Computer Software Documentation", as such terms are
* used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4,
* as applicable.
*/
package ganttviewer.viewer;
import ganttviewer.viewer.event.CurrentViewChangedEvent;
import ganttviewer.viewer.event.CurrentViewListener;
import ganttviewer.viewer.exceptions.AttachModelException;
import ganttviewer.viewer.exceptions.ViewException;
import ganttviewer.views.ResourceUsageView;
import ilog.views.gantt.IlvTimeInterval;
import ilog.views.gantt.util.event.IlvHashedEventService;
import ilog.views.util.event.IlvEventListenerCollection;
import ilog.views.util.event.IlvEventListenerSet;
import java.awt.CardLayout;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
/**
* <code>Viewer</code> is used by the demo to display several views.
*/
SuppressWarnings("serial")
public class Viewer extends JPanel {
/**
* Action instances
*/
private final Map<String, ViewerAbstractAction> actions = new HashMap<String, ViewerAbstractAction>();
/**
* Views.
*/
private final Map<String, View> views = new HashMap<String, View>();
/**
* Views list (to preserve the order)
*/
private final List<View> viewList = new ArrayList<View>();
/**
* Current view.
*/
private View currentView = null;
/**
* The model.
*/
private Object model = null;
/**
* The event service.
*/
private IlvHashedEventService eventService;
/**
* The view listener(s).
*/
private IlvEventListenerCollection<CurrentViewListener> currentViewListeners;
/**
* Indicates whether selection is synchronized or not.
*/
private boolean synchronizedSelection = true;
/**
* Builds a <code>Viewer</code>
*/
public Viewer() {
super(new CardLayout());
initEventService();
setOpaque(false);
}
/**
* Registers an action.
* @param action The action.
*/
public void registerAction(ViewerAbstractAction action) {
actions.put(action.getID(), action);
}
/**
* Unregisters an action.
* @param action The action.
*/
public void unregisterAction(ViewerAbstractAction action) {
actions.remove(action.getID());
}
/**
* Returns an action.
* @param actionID The action ID.
* @return The action.
*/
public ViewerAbstractAction getAction(String actionID) {
if (!actions.containsKey(actionID)) {
return null;
}
return actions.get(actionID);
}
/**
* Sets the model.
* @param model The model.
*/
public void setModel(Object model) throws AttachModelException {
// disables the synchronized selection
setSynchronizedSelection(false);
deSelectAll();
this.model = model;
for (View view : views()) {
try {
view.setModel(model);
} catch (Exception e) {
throw new AttachModelException(e);
}
}
// reactivates the synchronized selection
setSynchronizedSelection(true);
}
/**
* Internal selection (with view synchronization).
* @param obj The object to (de)select.
* @param selected The selection status.
* @param caller The view at the origin of this call.
*/
void setSelected(Object obj, boolean selected, View caller) {
if (model != null && this.isSynchronizedSelection()) {
for (View view : views()) {
if ((caller != null) && caller.getID().equals(view.getID())) {
continue;
}
view.setSelected(obj, selected);
}
}
}
/**
* Activates or disables the synchronized selection.
* @param enabled A boolean indicating whether this should be enabled or not.
*/
private void setSynchronizedSelection(boolean enabled) {
synchronizedSelection = enabled;
}
/**
* Indicates whether the synchronized selection is enabled or not.
* @return A boolean indicating whether it is enabled or not.
*/
private boolean isSynchronizedSelection() {
return synchronizedSelection;
}
/**
* Selects or deselects an object.
* @param obj The object to (de)select.
* @param selected The selection status.
*/
public void setSelected(Object obj, boolean selected) {
setSelected(obj, selected, null);
}
/**
* Deselects all objects.
* @param caller The view at the origin of this call.
*/
void deSelectAll(View caller) {
if (model != null && isSynchronizedSelection()) {
for (View view : views()) {
if ((caller != null) && caller.getID().equals(view.getID())) {
continue;
}
view.deSelectAll();
}
}
}
/**
* Deselects all objects.
*
*/
public void deSelectAll() {
deSelectAll(null);
}
/**
* Returns the model.
* @return The model.
*/
public Object getModel() {
return model;
}
/**
* Initializes the event services.
*/
private void initEventService() {
eventService = new IlvHashedEventService();
currentViewListeners = new IlvEventListenerSet<CurrentViewListener>();
}
/**
* Adds the specified listener to receive notifications when the current view
* has been changed.
* @param listener The listener that will be subscribed to subsequent view-change event.
* @see #removeCurrentViewListener
*/
public void addCurrentViewListener(CurrentViewListener listener) {
currentViewListeners.addListener(listener);
}
/**
* Removes the specified listener to receive notifications when the current
* view has been changed.
* @param listener The listener that will be unsubscribed from receiving view-change events.
* @see #addCurrentViewListener
*/
public void removeCurrentViewListener(CurrentViewListener listener) {
currentViewListeners.removeListener(listener);
}
/**
* Returns the current view.
* @return The current view.
*/
public View getCurrentView() {
return currentView;
}
/**
* Indicates whether the given view is set as current.
* @param view The view.
* @return A boolean indicating whether the view is set as the current one.
*/
public boolean isCurrentView(View view) {
if (getCurrentView() == null) {
return false;
}
return getCurrentView().getID().equals(view.getID());
}
/**
* Registers a view.
* @param view The view.
*/
void registerView(View view) {
if (!views.containsKey(view.getID())) {
views.put(view.getID(), view);
viewList.add(view);
}
if (viewList.size() == 1) {
// affects a current view
currentView = view;
}
}
/**
* Sets the current view and notifies listeners
* @param currentView The current view.
*/
public void setCurrentView(View currentView) {
View previousView = getCurrentView();
if (currentView == null) {
throw new ViewException("Null view set as current");
}
// update current view
this.currentView = currentView;
if (!views.containsKey(currentView.getID())) {
throw new ViewException("View " + currentView.getID() + " not registered");
}
// Fix JV-6642
SwingUtilities.invokeLater(new Runnable() {
Override
public void run() {
View currentView = getCurrentView();
if (currentView instanceof ResourceUsageView) {
ResourceUsageView view = (ResourceUsageView)currentView;
IlvTimeInterval chartInterval = view.getScheduleChart().getTimeScale().getVisibleInterval();
IlvTimeInterval sheetInterval = view.getScheduleChart().getGanttSheet().getVisibleInterval();
if (!sheetInterval.equals(chartInterval))
view.getScheduleChart().getGanttSheet().setVisibleInterval(chartInterval.getStart(), chartInterval.getDuration());
}
}
});
// makes the current view visible
((CardLayout) getLayout()).show(this, currentView.getID());
fireCurrentViewChanged(previousView);
currentView.setAsCurrentView();
}
/**
* Fires a <code>CurrentViewChanged</code> event.
* @param previousView The previous view.
*/
protected void fireCurrentViewChanged(View previousView) {
CurrentViewChangedEvent e = new CurrentViewChangedEvent(this, previousView,
getCurrentView());
eventService.publish(e);
for (Iterator<CurrentViewListener> it = currentViewListeners.getListeners(); it.hasNext();) {
CurrentViewListener listener = it.next();
listener.currentViewChanged(e);
}
}
/**
* Returns views.
* @return The views.
*/
public Collection<View> views() {
return Collections.unmodifiableCollection(this.viewList);
}
/**
* Returns the view identified by this ID.
* @param iD The ID.
* @return The view or <code>null</code>.
*/
public View getView(String iD) {
if (views.containsKey(iD)) {
return views.get(iD);
}
return null;
}
}