/*
* 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;
import ganttviewer.StyleManager.Style;
import ganttviewer.actions.GanttViewerDeleteConstraintAction;
import ganttviewer.actions.GanttViewerDeleteRowAction;
import ganttviewer.actions.GanttViewerEditPropertiesAction;
import ganttviewer.actions.GanttViewerInsertConstraintAction;
import ganttviewer.actions.GanttViewerInsertRowAction;
import ganttviewer.actions.GanttViewerMagnifyAction;
import ganttviewer.actions.GanttViewerPanAction;
import ganttviewer.actions.GanttViewerRowDownAction;
import ganttviewer.actions.GanttViewerRowExpandCollapseAction;
import ganttviewer.actions.GanttViewerRowIndentAction;
import ganttviewer.actions.GanttViewerRowOutdentAction;
import ganttviewer.actions.GanttViewerRowUpAction;
import ganttviewer.actions.GanttViewerSelectAction;
import ganttviewer.actions.GanttViewerZoomInAction;
import ganttviewer.actions.GanttViewerZoomOutAction;
import ganttviewer.actions.GanttViewerZoomToFitAction;
import ganttviewer.exceptions.ApplyStyleException;
import ganttviewer.model.GanttViewerConstraint;
import ganttviewer.util.CustomExample;
import ganttviewer.util.GanttViewerLogger;
import ganttviewer.util.GanttViewerProperties;
import ganttviewer.util.ImageUtilities;
import ganttviewer.util.WindowSizeUtils;
import ganttviewer.util.help.HelpPanel;
import ganttviewer.viewer.View;
import ganttviewer.viewer.Viewer;
import ganttviewer.viewer.ViewerAbstractAction;
import ganttviewer.viewer.event.CurrentViewChangedEvent;
import ganttviewer.viewer.event.CurrentViewListener;
import ganttviewer.viewer.exceptions.AttachModelException;
import ganttviewer.viewer.exceptions.ViewException;
import ganttviewer.views.GanttTableView;
import ganttviewer.views.GanttView;
import ganttviewer.views.MonthlyCalendarView;
import ganttviewer.views.PERTView;
import ganttviewer.views.ResourceUsageView;
import ganttviewer.views.ScheduleTableView;
import ilog.views.gantt.IlvActivity;
import ilog.views.gantt.IlvActivityFactory;
import ilog.views.gantt.IlvConstraint;
import ilog.views.gantt.IlvConstraintFactory;
import ilog.views.gantt.IlvConstraintType;
import ilog.views.gantt.IlvGanttModel;
import ilog.views.gantt.IlvTimeInterval;
import ilog.views.gantt.IlvTimeScrollController;
import ilog.views.gantt.action.IlvAction;
import ilog.views.gantt.model.IlvDefaultGanttModel;
import ilog.views.gantt.model.general.IlvGeneralActivity;
import ilog.views.gantt.model.general.IlvGeneralConstraint;
import ilog.views.gantt.xml.IlvGanttDocumentReader;
import ilog.views.gantt.xml.IlvGeneralActivityReader;
import ilog.views.gantt.xml.IlvGeneralConstraintReader;
import ilog.views.util.IlvProductUtil;
import ilog.views.util.swing.IlvSwingUtil;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.net.MalformedURLException;
import java.text.MessageFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.swing.AbstractButton;
import javax.swing.ActionMap;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.Icon;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.filechooser.FileFilter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import shared.AbstractExample;
import shared.GanttCommand;
import shared.swing.ExampleFrame;
/**
* <code>GanttViewer</code> is the main class of the sample.
*/
SuppressWarnings("serial")
public class GanttViewer extends CustomExample {
private static int ACTIVITY_ID_INCR = 0;
/**
* Available actions property.
*/
public static final String ACTIONS_SUFFIX = ".Actions";
/**
* Calendar view ID.
*/
public static final String CALENDAR_VIEW = "View.Calendar";
/**
* Gantt Chart view ID.
*/
public static final String GANTT_CHART_VIEW = "View.GanttChart";
/**
* Resource Sheet view ID.
*/
public static final String RESOURCE_SHEET_VIEW = "View.ResourceSheet";
/**
* Resource Usage view ID.
*/
public static final String RESOURCE_USAGE_VIEW = "View.ResourceUsage";
/**
* Task Sheet view ID.
*/
public static final String TASK_SHEET_VIEW = "View.TaskSheet";
/**
* PERT View view ID.
*/
public static final String PERT_VIEW = "View.PERTDiagram";
/**
* The frame icon.
*/
private static final String ICON_IMAGE = "ilog32.gif";
/**
* View icon property.
*/
private static final String CHANGE_VIEW_ICON_SUFFIX = ".Icon";
/**
* View short description property.
*/
private static final String CHANGE_VIEW_SHORT_DESCRIPTION = "Action.ChangeView.Tooltip";
/**
* View long description property.
*/
private static final String CHANGE_VIEW_LONG_DESCRIPTION = "Action.ChangeView.Description";
/**
* The viewer.
*/
private Viewer viewer = null;
/**
* Activity factory.
*/
private final IlvActivityFactory activityFactory = new ActivityFactory();
/**
* Constraint factory.
*/
private final IlvConstraintFactory constraintFactory = new ConstraintFactory();
/**
* Handle lag time management.
*/
private LagTimeHandler lagTimeHandler;
/**
* List of available views.
*/
private JComponent viewBar = null;
/**
* Button updater.
*/
private final ButtonUpdater buttonUpdater = new ButtonUpdater();
/**
* MenuItem updater.
*/
private final MenuItemUpdater menuUpdater = new MenuItemUpdater();
/**
* Style manager.
*/
private final StyleManager styleManager = new StyleManager();
/**
* Changes view actions.
*/
private final Map<String, ChangeViewAction> changeViewActions = new HashMap<String, ChangeViewAction>();
/**
* Show/Hide Help Panel action.
*/
private final ShowHideHelpAction showHideHelpAction = new ShowHideHelpAction();
/**
* The actions that set styles.
*/
private Set<SetStyleAction> setStyleActions = new HashSet<SetStyleAction>();
/**
* Help panel.
*/
private HelpPanel helpPanel;
/**
* Show/Hide help button.
*/
private JToggleButton helpButton;
/**
* Data set change action.
*/
private final ActionListener dataSetChangesHandler = new ActionListener() {
Override
public void actionPerformed(ActionEvent event) {
AbstractButton button = (AbstractButton) event.getSource();
String dataSet = button.getActionCommand();
try {
// set Gantt model
setGanttModel(createGanttModel(dataSet, true));
} catch (AttachModelException e) {
GanttViewerLogger.error(e);
}
}
};
/**
* Synchronizes visible time intervals.
*/
private final IlvTimeScrollController timeScrollController = new IlvTimeScrollController();
/**
* Action Description Suffix.
*/
public static final String DESCRIPTION_SUFFIX = ".Description";
/**
* Action Tooltip Suffix.
*/
public static final String TOOLTIP_SUFFIX = ".Tooltip";
/**
* Action Icon Suffix.
*/
public static final String ICON_SUFFIX = ".Icon";
/**
* Builds a <code>GanttViewer</code>.
*/
public GanttViewer() {
createHelpPanel();
}
/**
* Creates the help panel.
*/
protected void createHelpPanel() {
helpPanel = new HelpPanel(GanttViewerProperties.getString("Help.Title"),
GanttViewer.class.getResource(GanttViewerProperties
.getString("Help.HtmlFileName")), GanttViewerProperties
.getString("Help.BackToHomePage"), ImageUtilities.getIcon(
GanttViewer.class, "help/images/home.gif"), GanttViewerProperties
.getString("Help.BackToHomePage.Description"));
helpPanel.addWindowListener(new WindowAdapter() {
Override
public void windowClosing(WindowEvent e) {
helpButton.setSelected(false);
}
Override
public void windowIconified(WindowEvent e) {
helpButton.setSelected(false);
}
Override
public void windowDeiconified(WindowEvent e) {
helpButton.setSelected(true);
}
});
helpPanel.setIconImage(ImageUtilities.getImage(
shared.swing.ExampleFrame.class, GanttViewer.ICON_IMAGE));
}
/**
* Returns the help panel.
*
* @return The help panel.
*/
Override
public HelpPanel getHelpPanel() {
return helpPanel;
}
/**
* Initializes the user interface of the sample in the specified container.
* This will be the <code>JFrame</code> of the application.
*/
Override
public void init(Container container) {
// This sample uses JViews Gantt features. When deploying an
// application that includes this code, you need to be in possession
// of a Perforce JViews Gantt Deployment license.
IlvProductUtil.DeploymentLicenseRequired(
IlvProductUtil.JViews_Gantt_Deployment);
// This sample uses JViews Diagrammer features, for the PERT diagram.
// When deploying an application that includes this code, you need to
// be in possession of a Perforce JViews Diagrammer Deployment license.
IlvProductUtil.DeploymentLicenseRequired(
IlvProductUtil.JViews_Diagrammer_Deployment);
super.init(container);
// creates a lag time manager.
lagTimeHandler = new LagTimeHandler();
// create the viewer.
viewer = this.createViewer();
viewerCreated();
// set Gantt model
IlvGanttModel ganttModel = null;
try {
ganttModel = createGanttModel(GanttViewerProperties
.getString("DataSets.Default"), true);
setGanttModel(ganttModel);
} catch (AttachModelException e) {
GanttViewerLogger.error(e);
}
// initialize the GUI.
initializeGUI(container);
// sets the current view.
getViewer().setCurrentView(getViewer().getView(GANTT_CHART_VIEW));
// set preferred size
container.setPreferredSize(WindowSizeUtils.getMainWindowSize());
// styling
try {
this.styleManager.applyStyle(getViewer());
} catch (ApplyStyleException e) {
GanttViewerLogger.error(e);
}
// display the help panel
if (showHelp) {
SwingUtilities.invokeLater(new Runnable() {
Override
public void run() {
helpButton.getAction().actionPerformed(
new ActionEvent(this, ActionEvent.ACTION_PERFORMED, ""));
}
});
}
}
/**
* Sets the Gantt data model to the viewer.
*
* @param ganttModel
* The Gantt model.
*/
private void setGanttModel(IlvGanttModel ganttModel)
throws AttachModelException {
// computation on styles before
// count the number of activities and resources
int count = 0;
Iterator<?> it = ganttModel.activityPreorderIterator(ganttModel
.getRootActivity());
for (; it.hasNext(); it.next()) {
count++;
}
it = ganttModel.resourcePreorderIterator(ganttModel.getRootResource());
for (; it.hasNext(); it.next()) {
count++;
}
if (count >= 1000) {
// if there are between 1000 and 5000 elements, prefer simple and medium complexity styles
// if there are more than 5000 elements, prefer simple styles
Style aStyle = null;
for (SetStyleAction action : setStyleActions) {
if ((count >= 5000 && action.getStyle().getComplexity() == StyleManager.COMPLEXITY_SIMPLE)
|| (count < 5000 && action.getStyle().getComplexity() != StyleManager.COMPLEXITY_HIGH)) {
if (aStyle == null) {
aStyle = action.getStyle();
}
}
}
if (aStyle != null
&& (count >= 5000 && styleManager.getCurrentStyle().getComplexity() != StyleManager.COMPLEXITY_SIMPLE)
|| (count < 5000 && styleManager.getCurrentStyle().getComplexity() == StyleManager.COMPLEXITY_HIGH)) {
try {
this.styleManager.applyStyle(getViewer(), aStyle);
} catch (ApplyStyleException e) {
GanttViewerLogger.error(e);
}
}
} else {
for (SetStyleAction action : setStyleActions) {
action.setEnabled(true);
}
}
viewer.setModel(ganttModel);
// handles lag time management
lagTimeHandler.setGanttModel(ganttModel);
// initial selection.
viewer.setSelected(ganttModel.getRootActivity(), true);
viewer.setSelected(ganttModel.getRootResource(), true);
// initial zoom-to-fit if there isn't default transformer associated
// with the current view
if (viewer.getCurrentView().getDefaultTransformer() == null) {
SwingUtilities.invokeLater(new Runnable() {
Override
public void run() {
viewer.getAction(GanttViewerZoomToFitAction.ID).actionPerformed(
new ActionEvent(this, ActionEvent.ACTION_PERFORMED, ""));
}
});
}
}
/**
* Initializes the GUI.
*
* @param container
* The graphical container.
*/
protected void initializeGUI(Container container) {
container.setLayout(new BorderLayout());
// create and install the menu bar.
JMenuBar menuBar = createMenuBar();
setJMenuBar(menuBar);
// create the status bar.
JLabel status = createStatusBar();
// create the toolbar.
JToolBar toolbar = createToolBar();
container.add(toolbar, BorderLayout.NORTH);
container.add(viewer, BorderLayout.CENTER);
container.add(status, BorderLayout.SOUTH);
// size
setSize(WindowSizeUtils.getMainWindowSize());
// register GUI components updaters
getViewer().addCurrentViewListener(menuUpdater);
getViewer().addCurrentViewListener(buttonUpdater);
// create the viewbar
viewBar = createViewBar();
container.add(viewBar, BorderLayout.LINE_START);
}
/**
* Once the viewer is created, actions are created to change the current
* view.
*/
protected void viewerCreated() {
for (View view : getViewer().views()) {
Object[] args = { view.getName() };
Icon icon = ImageUtilities.getIcon(GanttViewer.class,
GanttViewerProperties.getString(view.getID().concat(
GanttViewer.CHANGE_VIEW_ICON_SUFFIX)));
String shortDescription = MessageFormat.format(GanttViewerProperties
.getString(GanttViewer.CHANGE_VIEW_SHORT_DESCRIPTION), args);
String longDescription = MessageFormat.format(GanttViewerProperties
.getString(GanttViewer.CHANGE_VIEW_LONG_DESCRIPTION), args);
changeViewActions.put(view.getID(), new ChangeViewAction(view, icon,
shortDescription, longDescription));
}
}
/**
* Creates the menu bar.
*/
public JMenuBar createMenuBar() {
JMenuBar menubar = new JMenuBar();
menubar.add(createFileMenu(), 0);
menubar.add(createEditMenu(), 1);
menubar.add(createStyleMenu(), 2);
menubar.add(createViewMenu(), 3);
return menubar;
}
/**
* Returns the Gantt Viewer title.
*
* @return The title.
*/
Override
public String getTitle() {
return GanttViewerProperties.getString("Demo.Title");
}
/**
* Registers the actions.
*
* @param viewer
* The viewer.
*/
protected void registerActions(Viewer viewer) {
viewer.registerAction(new GanttViewerZoomInAction(viewer));
viewer.registerAction(new GanttViewerZoomOutAction(viewer));
viewer.registerAction(new GanttViewerZoomToFitAction(viewer));
viewer.registerAction(new GanttViewerRowUpAction(viewer));
viewer.registerAction(new GanttViewerRowDownAction(viewer));
viewer.registerAction(new GanttViewerRowIndentAction(viewer));
viewer.registerAction(new GanttViewerRowOutdentAction(viewer));
viewer.registerAction(new GanttViewerInsertRowAction(viewer));
viewer.registerAction(new GanttViewerInsertConstraintAction(viewer));
viewer.registerAction(new GanttViewerEditPropertiesAction(viewer));
viewer.registerAction(new GanttViewerDeleteRowAction(viewer));
viewer.registerAction(new GanttViewerDeleteConstraintAction(viewer));
viewer.registerAction(new GanttViewerRowExpandCollapseAction(viewer));
viewer.registerAction(new GanttViewerSelectAction(viewer));
viewer.registerAction(new GanttViewerPanAction(viewer));
viewer.registerAction(new GanttViewerMagnifyAction(viewer));
}
/**
* Registers view actions.
*
* @param view
* The view.
* @param actionsStr
* A string indicating the actions to associate with.
*/
protected void registerActions(View view, String actionsStr) {
// list available actions from the given string and create a controller.
if (!"".equals(actionsStr)) {
String[] actionsArray = actionsStr
.split(GanttViewerProperties.PROPERTIES_SEPARATOR);
for (String element : actionsArray) {
view.registerAction(view.getViewer().getAction(element.trim()));
}
}
}
/**
* Creates the viewer and the views.
*
* @return The new <code>GanttViewerChart</code>.
*/
protected Viewer createViewer() {
String[] viewActions = new String[] {
GanttViewer.GANTT_CHART_VIEW.concat(GanttViewer.ACTIONS_SUFFIX),
GanttViewer.CALENDAR_VIEW.concat(GanttViewer.ACTIONS_SUFFIX),
GanttViewer.RESOURCE_USAGE_VIEW.concat(GanttViewer.ACTIONS_SUFFIX),
GanttViewer.TASK_SHEET_VIEW.concat(GanttViewer.ACTIONS_SUFFIX),
GanttViewer.RESOURCE_SHEET_VIEW.concat(GanttViewer.ACTIONS_SUFFIX),
GanttViewer.PERT_VIEW.concat(GanttViewer.ACTIONS_SUFFIX) };
Viewer viewer = new Viewer();
// register actions
registerActions(viewer);
// create views
try {
new GanttView(viewer, GanttViewer.GANTT_CHART_VIEW, GanttViewerProperties
.getString(GanttViewer.GANTT_CHART_VIEW), timeScrollController,
activityFactory, constraintFactory);
new MonthlyCalendarView(viewer, GanttViewer.CALENDAR_VIEW,
GanttViewerProperties.getString(GanttViewer.CALENDAR_VIEW));
new ResourceUsageView(viewer, GanttViewer.RESOURCE_USAGE_VIEW,
GanttViewerProperties.getString(GanttViewer.RESOURCE_USAGE_VIEW),
timeScrollController, activityFactory, constraintFactory);
new GanttTableView(viewer, GanttViewer.TASK_SHEET_VIEW,
GanttViewerProperties.getString(GanttViewer.TASK_SHEET_VIEW),
activityFactory, constraintFactory);
new ScheduleTableView(viewer, GanttViewer.RESOURCE_SHEET_VIEW,
GanttViewerProperties.getString(GanttViewer.RESOURCE_SHEET_VIEW),
activityFactory, constraintFactory);
new PERTView(viewer, GanttViewer.PERT_VIEW, GanttViewerProperties
.getString(GanttViewer.PERT_VIEW));
// associate actions
int k = 0;
for (View view : viewer.views()) {
registerActions(view, GanttViewerProperties.getString(viewActions[k++]));
}
} catch (ViewException e) {
GanttViewerLogger.error(e);
}
return viewer;
}
/**
* Returns the viewer.
*
* @return The viewer.
*/
public Viewer getViewer() {
return viewer;
}
/**
* Creates the Gantt data model.
*
* @param dataSet
* The dataSet to load.
* @param resolve
* Resolves the data set location.
* @return The Gantt data model.
*/
protected IlvGanttModel createGanttModel(String dataSet, boolean resolve) {
// model creation
InputSource source;
IlvGanttDocumentReader docReader;
try {
String path = dataSet;
if (resolve) {
path = getClass().getResource(dataSet).toString();
}
// create an InputSource
source = new InputSource(path);
docReader = new IlvGanttDocumentReader();
docReader.setActivityReader(new IlvGeneralActivityReader() {
Override
protected IlvActivity createActivity(String id, String name,
Date start, Date end) {
IlvActivity activity = activityFactory
.createActivity(new IlvTimeInterval(start, end));
activity.setID(id);
activity.setName(name);
return activity;
}
});
docReader.setConstraintReader(new IlvGeneralConstraintReader() {
Override
protected IlvConstraint createConstraint(IlvActivity from,
IlvActivity to, IlvConstraintType type) {
return constraintFactory.createConstraint(from, to, type);
}
});
} catch (Exception e) {
IlvSwingUtil.showErrorDialog(this, e);
return null;
}
// create the document
Document document;
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
document = builder.parse(source);
} catch (Exception ex) {
IlvSwingUtil.showErrorDialog(this, ex);
return null;
}
// create a default Gantt model
IlvGanttModel model = new IlvDefaultGanttModel();
// read the document into the Gantt model.
try {
docReader.readGanttModel(document, model);
} catch (Exception ex) {
IlvSwingUtil.showErrorDialog(this, ex);
return null;
}
return model;
}
/**
* Creates the File menu.
*
* @return The File menu.
*/
public JMenu createFileMenu() {
JMenu menu = new JMenu(GanttViewerProperties.getString("Menu.File"));
menu.setMnemonic(KeyEvent.VK_F);
setStatusText(menu, GanttViewerProperties
.getString("Menu.File.Description"));
// classic open file dialog in standalone mode
addAction(menu, new OpenFileAction());
if (isExitAllowed()) {
menu.addSeparator();
addAction(menu, new GanttCommand.ExitAction());
}
return menu;
}
/**
* Creates the menu for selecting the data set.
*
* @param dataSetMenu
* The parent menu item.
*/
protected void createDataSetSelectorMenu(JMenu dataSetMenu) {
String dataSetsProperty = GanttViewerProperties.getString("DataSets")
.trim();
String defaultDataSet = GanttViewerProperties.getString("DataSets.Default")
.trim();
ButtonGroup buttonGroup = new ButtonGroup();
if (!"".equals(dataSetsProperty)) {
String[] dataSetsArray = dataSetsProperty
.split(GanttViewerProperties.PROPERTIES_SEPARATOR);
for (String element : dataSetsArray) {
String dataSet = element.trim();
JRadioButtonMenuItem menuItem = new JRadioButtonMenuItem(dataSet,
dataSet.equals(defaultDataSet));
menuItem.setActionCommand(dataSet);
menuItem.addActionListener(this.dataSetChangesHandler);
dataSetMenu.add(menuItem);
buttonGroup.add(menuItem);
}
}
}
/**
* Adds the specified action to a toolbar as a button and returns the
* button. <code>AbstractButton</code>.
*
* @param toolbar
* The toolbar where the button is to be added.
* @param action
* The action to launch.
* @param toggle
* Add a toggle button?
*/
protected AbstractButton addAction(JToolBar toolbar,
final ViewerAbstractAction action, boolean toggle) {
final AbstractButton button;
if (!toggle) {
button = new JButton(action);
} else {
button = new JToggleButton(action);
// synchronize selection state
action.addPropertyChangeListener(new PropertyChangeListener() {
Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(ViewerAbstractAction.SELECTED_KEY)) {
button.setSelected((Boolean) evt.getNewValue());
}
}
});
button.addItemListener(new ItemListener() {
Override
public void itemStateChanged(ItemEvent e) {
boolean value = e.getStateChange() == ItemEvent.SELECTED;
action.putValue(ViewerAbstractAction.SELECTED_KEY, value);
}
});
}
if (button.getIcon() != null) {
button.setText(null);
}
// populate the action map
ActionMap actionMap = button.getActionMap();
if (actionMap != null) {
actionMap.put(action, action);
}
// register accelerator if there is one
KeyStroke accelerator = action.getAccelerator();
if (accelerator != null) {
InputMap inputMap = button.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
inputMap.put(accelerator, action);
}
String shortDescription = action.getShortDescription();
if (shortDescription != null) {
if (accelerator != null) {
shortDescription += ToolTipUI.TIP_DELIMITER
+ action.getAcceleratorText();
}
button.setToolTipText(shortDescription);
}
toolbar.add(button);
buttonUpdater.registerButton(button);
return button;
}
/**
* Overrides <code>addAction()</code> to listen for current view changes.
*/
protected JMenuItem addAction(JMenu menu, ViewerAbstractAction action) {
JMenuItem menuItem = super.addAction(menu, action);
menuUpdater.registerMenuItem(menuItem);
return menuItem;
}
/**
* Creates the Edit menu.
*
* @return The edit menu.
*/
public JMenu createEditMenu() {
JMenu menu = new JMenu(GanttViewerProperties.getString("Menu.Edit"));
menu.setMnemonic(KeyEvent.VK_E);
setStatusText(menu, GanttViewerProperties
.getString("Menu.Edit.Description"));
Viewer viewer = getViewer();
addAction(menu, viewer.getAction(GanttViewerInsertRowAction.ID));
addAction(menu, viewer.getAction(GanttViewerInsertConstraintAction.ID));
menu.addSeparator();
addAction(menu, viewer.getAction(GanttViewerDeleteRowAction.ID));
addAction(menu, viewer.getAction(GanttViewerDeleteConstraintAction.ID));
menu.addSeparator();
addAction(menu, viewer.getAction(GanttViewerEditPropertiesAction.ID));
return menu;
}
/**
* Creates the Style menu.
*
* @return The Style menu.
*/
public JMenu createStyleMenu() {
JMenu menu = new JMenu(GanttViewerProperties.getString("Menu.Style"));
menu.setMnemonic(KeyEvent.VK_S);
setStatusText(menu, GanttViewerProperties
.getString("Menu.Style.Description"));
final Map<Style, JRadioButtonMenuItem> index = new HashMap<Style, JRadioButtonMenuItem>();
ButtonGroup styleGroup = new ButtonGroup();
for (Object element : styleManager.styles()) {
StyleManager.Style style = (StyleManager.Style) element;
SetStyleAction action = new SetStyleAction(style);
setStyleActions.add(action);
JRadioButtonMenuItem menuItem = new JRadioButtonMenuItem(action);
menu.add(menuItem);
styleGroup.add(menuItem);
index.put(style, menuItem);
}
styleManager.addCurrentStyleListener(new CurrentStyleListener() {
Override
public void currentStyleChanged() {
index.get(styleManager.getCurrentStyle()).setSelected(true);
}
});
return menu;
}
/**
* Creates the View menu.
*
* @return The View menu.
*/
public JMenu createViewMenu() {
JMenu menu = new JMenu(GanttViewerProperties.getString("Menu.View"));
menu.setMnemonic(KeyEvent.VK_V);
setStatusText(menu, GanttViewerProperties
.getString("Menu.View.Description"));
// group of items
final ButtonGroup group = new ButtonGroup();
for (View view : getViewer().views()) {
ChangeViewAction changeAction = changeViewActions.get(view.getID());
JRadioButtonMenuItem menuItem = new JRadioButtonMenuItem(changeAction);
menuItem.setToolTipText(null);
menuItem.setIcon(null);
setStatusText(menuItem, changeAction.getLongDescription());
group.add(menuItem);
menu.add(menuItem);
}
// listen to view changes
getViewer().addCurrentViewListener(new CurrentViewListener() {
Override
public void currentViewChanged(CurrentViewChangedEvent event) {
for (Enumeration<AbstractButton> e = group.getElements(); e
.hasMoreElements();) {
AbstractButton button = e.nextElement();
if (button.getAction().equals(
changeViewActions.get(getViewer().getCurrentView().getID()))) {
group.setSelected(button.getModel(), true);
break;
}
}
}
});
return menu;
}
/**
* Creates the list of available views.
*
* @return The toolbar.
*/
public JComponent createViewBar() {
JToolBar viewBar = new JToolBar(SwingConstants.VERTICAL);
viewBar.setBackground(UIManager.getColor("controlShadow"));
viewBar.setFloatable(false);
// group of items
final ButtonGroup group = new ButtonGroup();
// create menu items
Dimension max = new Dimension(0, 0);
for (View view : getViewer().views()) {
ChangeViewAction changeAction = changeViewActions.get(view.getID());
JToggleButton button = new JToggleButton(changeAction);
button.setHorizontalTextPosition(SwingConstants.CENTER);
button.setVerticalTextPosition(SwingConstants.BOTTOM);
button.setToolTipText(changeAction.getShortDescription());
group.add(button);
viewBar.add(button);
if (button.getMaximumSize().getWidth() > max.getWidth()) {
max = button.getMaximumSize();
}
}
// set button sizes
for (Enumeration<AbstractButton> e = group.getElements(); e
.hasMoreElements();) {
e.nextElement().setMaximumSize(max);
}
// listen to view changes
getViewer().addCurrentViewListener(new CurrentViewListener() {
Override
public void currentViewChanged(CurrentViewChangedEvent event) {
for (Enumeration<AbstractButton> e = group.getElements(); e
.hasMoreElements();) {
AbstractButton button = e.nextElement();
if (button.getAction().equals(
changeViewActions.get(getViewer().getCurrentView().getID()))) {
group.setSelected(button.getModel(), true);
break;
}
}
}
});
viewBar.setBorder(BorderFactory.createEtchedBorder());
return viewBar;
}
/**
* Overrides <code>setLookAndFeel</code>.
*
* @param laf
* The look-and-feel object.
*/
Override
protected void setLookAndFeel(LookAndFeelInfo laf) {
super.setLookAndFeel(laf);
if (viewBar != null) {
viewBar.setBackground(UIManager.getColor("controlShadow"));
}
}
/**
* Populates the toolbar.
*
* @param toolbar
* The toolbar to populate.
*/
Override
protected void populateToolBar(JToolBar toolbar) {
Viewer viewer = getViewer();
addAction(toolbar, viewer.getAction(GanttViewerInsertRowAction.ID), false);
addAction(toolbar, viewer.getAction(GanttViewerInsertConstraintAction.ID),
false);
toolbar.addSeparator();
addAction(toolbar, viewer.getAction(GanttViewerDeleteRowAction.ID), false);
addAction(toolbar, viewer.getAction(GanttViewerDeleteConstraintAction.ID),
false);
toolbar.addSeparator();
addAction(toolbar, viewer.getAction(GanttViewerEditPropertiesAction.ID),
false);
toolbar.addSeparator();
addAction(toolbar, viewer.getAction(GanttViewerRowExpandCollapseAction.ID),
false);
addAction(toolbar, viewer.getAction(GanttViewerRowOutdentAction.ID), false);
addAction(toolbar, viewer.getAction(GanttViewerRowIndentAction.ID), false);
addAction(toolbar, viewer.getAction(GanttViewerRowUpAction.ID), false);
addAction(toolbar, viewer.getAction(GanttViewerRowDownAction.ID), false);
toolbar.addSeparator();
// add interactions
addAction(toolbar, viewer.getAction(GanttViewerSelectAction.ID), true)
.setSelected(true);
addAction(toolbar, viewer.getAction(GanttViewerPanAction.ID), true);
addAction(toolbar, viewer.getAction(GanttViewerMagnifyAction.ID), true);
toolbar.addSeparator();
addAction(toolbar, viewer.getAction(GanttViewerZoomInAction.ID), false);
addAction(toolbar, viewer.getAction(GanttViewerZoomOutAction.ID), false);
addAction(toolbar, viewer.getAction(GanttViewerZoomToFitAction.ID), false);
// help
toolbar.addSeparator();
helpButton = new JToggleButton(showHideHelpAction);
helpButton.setText(null);
toolbar.add(helpButton);
toolbar.setBorder(BorderFactory.createEtchedBorder());
}
/**
* View change action of the chart.
*/
class ChangeViewAction extends IlvAction {
/**
* The view.
*/
private View relatedView;
/**
* Builds a <code>ChangeViewAction</code>.
*/
public ChangeViewAction(View relatedView, Icon icon,
String shortDescription, String longDescription) {
super(relatedView.getName(), icon, null, shortDescription,
longDescription);
this.relatedView = relatedView;
}
/**
* Performs the action.
*
* @param event
* The event.
*/
Override
public void actionPerformed(ActionEvent event) {
relatedView.getViewer().setCurrentView(relatedView);
}
/**
* Returns the related view.
*
* @return The view.
*/
public View getRelatedView() {
return relatedView;
}
}
/**
* The show/hide help action.
*/
class ShowHideHelpAction extends IlvAction {
/**
* ID of the action.
*/
public static final String ID = "Action.ShowHideHelp";
/**
* Builds a <code>ShowHideHelpAction</code>.
*/
public ShowHideHelpAction() {
super(GanttViewerProperties.getString(ShowHideHelpAction.ID),
ImageUtilities.getIcon(shared.AbstractExample.class,
GanttViewerProperties.getString(ShowHideHelpAction.ID
.concat(".Icon"))), null, GanttViewerProperties
.getString(ShowHideHelpAction.ID.concat(".Tooltip")),
GanttViewerProperties.getString(ShowHideHelpAction.ID
.concat(".Description")));
}
/**
* Shows/Hides help panel.
*/
Override
public void actionPerformed(ActionEvent arg0) {
helpPanel.setVisible(helpButton.isSelected());
if (helpButton.isSelected()) {
helpPanel.setState(Frame.NORMAL);
helpPanel.toFront();
}
}
}
/**
* Represents the open file action.
*
* @since JViews 8.5
*/
class OpenFileAction extends IlvAction {
/**
* The ID of the action.
*/
public static final String ID = "Action.OpenFile";
/**
* The file chooser.
*/
private JFileChooser fileChooser;
/**
* Builds an <code>OpenFileAction</code> object.
*/
public OpenFileAction() {
super(
GanttViewerProperties.getString(OpenFileAction.ID),
null,
null,
GanttViewerProperties.getString(OpenFileAction.ID.concat(".Tooltip")),
GanttViewerProperties.getString(OpenFileAction.ID
.concat(".Description")));
fileChooser = new JFileChooser(".");
fileChooser.setMultiSelectionEnabled(false);
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
fileChooser.setFileFilter(new FileFilter() {
Override
public boolean accept(File f) {
return f.isDirectory() || f.getName().toLowerCase().endsWith(".sdxl");
}
Override
public String getDescription() {
return "*.sdxl";
}
});
}
/**
* Opens a file.
*/
Override
public void actionPerformed(ActionEvent evt) {
if (fileChooser.showOpenDialog(GanttViewer.this) == JFileChooser.APPROVE_OPTION) {
File file = fileChooser.getSelectedFile();
try {
// set Gantt model
setGanttModel(createGanttModel(file.toURI().toURL().toString(), false));
} catch (AttachModelException e) {
GanttViewerLogger.error(e);
} catch (MalformedURLException e) {
GanttViewerLogger.error(e);
}
}
}
}
/**
* Represents the change style action.
*
* @since JViews 8.5
*/
class SetStyleAction extends IlvAction {
/**
* The ID of the action.
*/
public static final String ID = "Action.SetStyle";
/**
* The style.
*/
private Style style;
/**
* Builds a new <code>SetStyleAction</code> object.
* @param style The style.
*/
public SetStyleAction(Style style) {
super(style.getName(), null, null);
this.style = style;
}
/**
* Returns the style.
* @return The current style.
*/
public Style getStyle() {
return style;
}
/**
* Sets the style.
* @param evt Used to set the style.
*/
Override
public void actionPerformed(ActionEvent evt) {
try {
styleManager.applyStyle(GanttViewer.this.getViewer(), style);
} catch (ApplyStyleException e) {
GanttViewerLogger.error(e);
}
}
}
/**
* Custom activity factory.
*/
protected class ActivityFactory implements IlvActivityFactory {
/**
* The factory method.
*
* @param interval
* The given time interval.
*/
Override
public IlvActivity createActivity(IlvTimeInterval interval) {
IlvGeneralActivity activity = new IlvGeneralActivity("New Activity "
+ (GanttViewer.ACTIVITY_ID_INCR++), "New Activity", interval);
return activity;
}
}
/**
* Custom constraint factory.
*/
protected class ConstraintFactory implements IlvConstraintFactory {
/**
* The factory method.
*
* @param interval
* The given time interval.
*/
Override
public IlvConstraint createConstraint(IlvActivity from, IlvActivity to,
IlvConstraintType type) {
IlvGeneralConstraint constraint = new GanttViewerConstraint(from, to,
type);
constraint
.setProperty(LagTimeHandler.CONSTRAINT_SATISFIED_PROPERTY, true);
return constraint;
}
}
/**
* Entry Point of the Gantt Viewer.
*
* @param args
*/
public static void main(String[] args) {
ExampleFrame.createAndShowGUI(GanttViewer.class,
new ExampleFrame.FrameInitialLocationPolicy() {
Override
public void initPosition(JFrame frame, AbstractExample example) {
frame.setLocation(WindowSizeUtils.getMainWindowLocation());
}
});
}
}