/* * 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 dualChart; import java.awt.BorderLayout; import java.awt.Container; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.util.Date; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JPanel; import javax.swing.JSplitPane; import javax.swing.JToolBar; import javax.swing.KeyStroke; import ilog.views.gantt.IlvActivity; import ilog.views.gantt.IlvDuration; import ilog.views.gantt.IlvGanttChart; import ilog.views.gantt.IlvGanttModel; import ilog.views.gantt.IlvHierarchyChart; import ilog.views.gantt.IlvResource; import ilog.views.gantt.IlvScheduleChart; import ilog.views.gantt.IlvTimeInterval; import ilog.views.gantt.IlvTimeScrollController; import ilog.views.gantt.IlvTimeUtil; import ilog.views.gantt.action.IlvAction; import ilog.views.gantt.action.IlvZoomToFitAction; import ilog.views.gantt.event.ChartDividerEvent; import ilog.views.gantt.event.ChartDividerListener; import ilog.views.gantt.graphic.grid.IlvWeekendGrid; import ilog.views.gantt.model.IlvDefaultGanttModel; import ilog.views.gantt.swing.IlvJTable; import ilog.views.util.IlvProductUtil; import shared.AbstractExample; import shared.GanttCommand; import shared.data.GeneralActivityFactory; import shared.data.GeneralResourceFactory; import shared.data.SimpleEngineeringProject; import shared.swing.ExampleFrame; import xml.XMLGanttActions; /** * An example of synchronized Gantt and Schedule charts that display the same * data model. */ public class DualChartExample extends AbstractExample { /** * The Gantt chart. */ protected IlvGanttChart gantt; /** * The Schedule chart. */ protected IlvScheduleChart schedule; /** * The data model used for the charts. */ protected IlvGanttModel model; /** * The various menu and toolbar actions. */ protected IlvAction newAction; protected IlvAction openAction; protected IlvAction saveAsAction; protected IlvAction exitAction; protected IlvAction insertActivityRowAction; protected IlvAction deleteActivityRowAction; protected IlvAction makeConstraintAction; protected IlvAction deleteConstraintAction; protected IlvAction insertResourceRowAction; protected IlvAction deleteResourceRowAction; protected IlvAction makeReservationAction; protected IlvAction deleteReservationAction; protected IlvAction deleteAllAction; protected IlvAction rowExpandCollapseAction; protected IlvZoomToFitAction zoomToFitAction; protected IlvAction increaseRowHeightAction; protected IlvAction decreaseRowHeightAction; { // 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); } /** * Initializes the user interface of the example in the specified container. * * @param container * The container that the example is running in. This will be the * <code>contentPane</code> of the <code>JApplet</code> or the * <code>JFrame</code>, depending on whether the example is run as an * applet or as an application. */ Override public void init(Container container) { super.init(container); container.setLayout(new BorderLayout()); // Create the charts. gantt = new IlvGanttChart(); schedule = new IlvScheduleChart(); // Customize the data model factories and graphic renderers of the charts. customizeFactories(); // Create the Gantt data model. model = createGanttModel(); // Set the data model of the charts. gantt.setGanttModel(model); schedule.setGanttModel(model); // Create the horizontal split pane and its 2 panels. JPanel ganttPanel = new JPanel(new BorderLayout()); JPanel schedulePanel = new JPanel(new BorderLayout()); JSplitPane horizontalSplitter = new JSplitPane(JSplitPane.VERTICAL_SPLIT, ganttPanel, schedulePanel); horizontalSplitter.setResizeWeight(0.5); horizontalSplitter.setOneTouchExpandable(true); // If the example is running as an applet, the container will have a defined // fixed height already. In this case, we set the divider location to the // approximate mid-point, not counting the menu bar, toolbar, or status bar // components. If the example is running as an application, the container // will not have a defined size yet. In this case, the preferred sizes of // the gantt and schedule charts will be respected when the frame is packed. int containerHeight = container.getHeight(); if (containerHeight > 0) { horizontalSplitter.setDividerLocation(containerHeight / 2); } // Customize the appearance of the charts. customizeCharts(); // Synchronize the behavior of the charts. synchronizeCharts(gantt, schedule); // Create and install the menu bar. JMenuBar menuBar = createMenuBar(); setJMenuBar(menuBar); // Create the status bar. JLabel status = createStatusBar(); // Create the toolbars. JToolBar mainToolBar = createMainToolBar(); JToolBar ganttToolBar = createGanttToolBar(); JToolBar scheduleToolBar = createScheduleToolBar(); ganttPanel.add(ganttToolBar, BorderLayout.LINE_START); ganttPanel.add(gantt, BorderLayout.CENTER); schedulePanel.add(scheduleToolBar, BorderLayout.LINE_START); schedulePanel.add(schedule, BorderLayout.CENTER); container.add(horizontalSplitter, BorderLayout.CENTER); JPanel toolbarPanel = new JPanel(); toolbarPanel.add(mainToolBar); container.add(toolbarPanel, BorderLayout.NORTH); container.add(status, BorderLayout.SOUTH); } /** * Customizes the data model factories and graphic renderers of the charts. */ protected void customizeFactories() { // Change the default activity and resource factories of the Gantt chart // to ones that sequentially number the activities and resources. gantt.setActivityFactory(new GeneralActivityFactory(gantt)); gantt.setResourceFactory(new GeneralResourceFactory(gantt)); // Set the Schedule chart to use the same data factories as the Gantt chart. schedule.setActivityFactory(gantt.getActivityFactory()); schedule.setResourceFactory(gantt.getResourceFactory()); schedule.setConstraintFactory(gantt.getConstraintFactory()); schedule.setReservationFactory(gantt.getReservationFactory()); } /** * Customizes the appearance of the Gantt and Schedule charts. The charts are * not yet synchronized when this method is invoked. */ protected void customizeCharts() { // Expand several activities in the Gantt chart so their children // are visible. IlvActivity ganttRoot = model.getRootActivity(); for (int i = 0; i <= 1; i++) { if (model.getChildActivityCount(ganttRoot) > i) { gantt.expandAllRows(model.getChildActivity(ganttRoot, i)); } } // Expand several resources in the Schedule chart so their children // are visible. IlvResource scheduleRoot = model.getRootResource(); for (int i = 0; i <= 1; i++) { if (model.getChildResourceCount(scheduleRoot) > i) { schedule.expandAllRows(model.getChildResource(scheduleRoot, i)); } } // Default column widths are 75. Resize some of the columns so that the // text is not truncated. IlvJTable table; table = gantt.getTable(); table.getColumn("Name").setPreferredWidth(175); table.getColumn("Start").setPreferredWidth(90); table.getColumn("End").setPreferredWidth(90); table = schedule.getTable(); table.getColumn("Name").setPreferredWidth(150); table.getColumn("ID").setPreferredWidth(60); table.getColumn("Qty").setPreferredWidth(40); // Set the initially displayed time span to start 1 day before the beginning // of the schedule and extend for 3 weeks. Later, the Schedule chart will be // synchronized to the Gantt chart, so we only need to set the time span for // the Gantt chart here. Date visibleStartTime = IlvTimeUtil.subtract(model.getRootActivity().getStartTime(), IlvDuration.ONE_DAY); gantt.setVisibleTime(visibleStartTime); gantt.setVisibleDuration(IlvDuration.ONE_WEEK.multiply(3)); // Use a vertical grid in both charts that colors the weekends. IlvWeekendGrid grid = new IlvWeekendGrid(); gantt.getGanttSheet().setVerticalGrid(grid); grid = new IlvWeekendGrid(); schedule.getGanttSheet().setVerticalGrid(grid); } /** * Synchronizes the behavior of the second specified chart to that of the * first specified chart. * * @param chart1 * The primary chart. * @param chart2 * The secondary chart that will be synchronized with the primary * chart. */ protected void synchronizeCharts(final IlvHierarchyChart chart1, final IlvHierarchyChart chart2) { // Use an IlvTimeScrollController to synchronize the visible time intervals // of the two charts. This will only give the right effect if we also ensure // that both charts always have their vertical scroll bar visible. IlvTimeInterval visibleInterval = chart1.getVisibleInterval(); IlvTimeScrollController timeController = new IlvTimeScrollController(); timeController.addTimeScrollable(chart1); timeController.addTimeScrollable(chart2); timeController.setVisibleInterval(visibleInterval.getStart(), visibleInterval.getDuration()); chart1.setVerticalScrollBarPolicy(IlvHierarchyChart.VERTICAL_SCROLLBAR_ALWAYS); chart2.setVerticalScrollBarPolicy(IlvHierarchyChart.VERTICAL_SCROLLBAR_ALWAYS); // Synchronize the vertical splitters of both charts. chart1.addChartDividerListener(new ChartDividerListener() { Override public void chartDividerLocationChanged(ChartDividerEvent evt) { int location = evt.getDividerLocation(); if (location != chart2.getDividerLocation()) { chart2.setDividerLocation(location); } } }); chart2.addChartDividerListener(new ChartDividerListener() { Override public void chartDividerLocationChanged(ChartDividerEvent evt) { int location = evt.getDividerLocation(); if (location != chart1.getDividerLocation()) { chart1.setDividerLocation(location); } } }); } /** * Creates the menu bar. * * @return The menu bar. */ public JMenuBar createMenuBar() { JMenuBar menu = new JMenuBar(); menu.add(createFileMenu()); menu.add(createEditMenu()); menu.add(createRowMenu()); menu.add(createLAFMenu()); return menu; } /** * Creates the "File" menu. * * @return The File menu. */ public JMenu createFileMenu() { JMenu menu = new JMenu("File"); menu.setMnemonic(KeyEvent.VK_F); setStatusText(menu, "File operations"); // Menu item for "New". newAction = new GanttCommand.NewDataModelAction(gantt) { Override public void actionPerformed(ActionEvent event) { IlvGanttModel model = new IlvDefaultGanttModel(); gantt.setGanttModel(model); schedule.setGanttModel(model); } }; addAction(menu, newAction); if (isLocalFileAccessAllowed()) { // Menu item for "Open ...". openAction = new XMLGanttActions.OpenXMLAction(gantt) { Override public void actionPerformed(ActionEvent event) { IlvGanttModel model = readXMLFile(); // Change the Gantt model of the Gantt chart if (model != null) { gantt.setGanttModel(model); schedule.setGanttModel(model); zoomToFit(); } } }; addAction(menu, openAction); // Menu item for "Save ...". saveAsAction = new XMLGanttActions.SaveAsXMLAction(gantt); addAction(menu, saveAsAction); } // Menu item for "Exit". if (isExitAllowed()) { menu.addSeparator(); exitAction = new GanttCommand.ExitAction(); addAction(menu, exitAction); } return menu; } /** * Creates the Edit menu. * * @return The Edit menu. */ public JMenu createEditMenu() { JMenu menu = new JMenu("Edit"); menu.setMnemonic(KeyEvent.VK_E); setStatusText(menu, "Adds, removes, or modifies activities, constraints, resources, and reservations."); // Menu item for "Insert new activity". insertActivityRowAction = new GanttCommand.InsertActivityAction(gantt); addAction(menu, insertActivityRowAction); // Menu item for "Delete selected activity". deleteActivityRowAction = new GanttCommand.DeleteSelectedRowsAction(gantt); deleteActivityRowAction.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0)); addAction(menu, deleteActivityRowAction); // Menu item for "Create new constraint". makeConstraintAction = new GanttCommand.MakeConstraintAction(gantt); addAction(menu, makeConstraintAction); // Menu item for "Delete selected constraints". deleteConstraintAction = new GanttCommand.DeleteSelectedConstraintsAction(gantt); deleteConstraintAction.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_DOWN_MASK)); addAction(menu, deleteConstraintAction); menu.addSeparator(); // Menu item for "Insert new resource". insertResourceRowAction = new GanttCommand.InsertResourceAction(schedule); insertResourceRowAction.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, KeyEvent.SHIFT_DOWN_MASK)); addAction(menu, insertResourceRowAction); // Menu item for "Delete selected resource". deleteResourceRowAction = new GanttCommand.DeleteSelectedRowsAction(schedule); deleteResourceRowAction.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, KeyEvent.SHIFT_DOWN_MASK)); addAction(menu, deleteResourceRowAction); // Menu item for "Create reservation". makeReservationAction = new GanttCommand.MakeActivityAction(schedule); addAction(menu, makeReservationAction); // Menu item for "Delete selected reservations". deleteReservationAction = new GanttCommand.DeleteSelectedReservationsAction(schedule); deleteReservationAction.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, KeyEvent.CTRL_DOWN_MASK)); addAction(menu, deleteReservationAction); menu.addSeparator(); // Menu item for "Delete all". deleteAllAction = new GanttCommand.DeleteSelectedAction(gantt, schedule); deleteAllAction.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, KeyEvent.CTRL_DOWN_MASK)); addAction(menu, deleteAllAction); menu.addSeparator(); // Menu item for "Expand/Collapse". rowExpandCollapseAction = new GanttCommand.RowExpandCollapseAction(gantt, schedule); addAction(menu, rowExpandCollapseAction); return menu; } /** * Creates the Row menu. * * @return The Row menu. */ public JMenu createRowMenu() { JMenu menu = new JMenu("Row"); menu.setMnemonic(KeyEvent.VK_R); setStatusText(menu, "Changes the chart's row height."); // Menu item for "Increase 2 pixels". increaseRowHeightAction = new GanttCommand.RowHeightAction(2, gantt, schedule); increaseRowHeightAction.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_2, KeyEvent.CTRL_DOWN_MASK)); addAction(menu, increaseRowHeightAction, // Add an alternate keystroke, since Ctrl-2 is not available on some // national keyboards. new KeyStroke[] { KeyStroke.getKeyStroke(KeyEvent.VK_NUMPAD2, KeyEvent.CTRL_DOWN_MASK) }); // Menu item for "Decrease 2 pixels". decreaseRowHeightAction = new GanttCommand.RowHeightAction(-2, gantt, schedule); decreaseRowHeightAction .setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_2, KeyEvent.CTRL_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK)); addAction(menu, decreaseRowHeightAction, new KeyStroke[] { KeyStroke.getKeyStroke(KeyEvent.VK_NUMPAD2, KeyEvent.CTRL_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK) }); return menu; } /** * Creates the main toolbar. * * @return The main application toolbar. */ protected JToolBar createMainToolBar() { JToolBar toolbar = new JToolBar(JToolBar.HORIZONTAL); toolbar.setFloatable(false); addAction(toolbar, newAction); if (openAction != null) { addAction(toolbar, openAction); } if (saveAsAction != null) { addAction(toolbar, saveAsAction); } toolbar.addSeparator(); addAction(toolbar, deleteAllAction); toolbar.addSeparator(); addAction(toolbar, rowExpandCollapseAction); toolbar.addSeparator(); addAction(toolbar, gantt.getZoomOutAction()); addAction(toolbar, gantt.getZoomInAction()); zoomToFitAction = new IlvZoomToFitAction(gantt, "Zoom To Fit", KeyStroke.getKeyStroke(KeyEvent.VK_F, KeyEvent.CTRL_DOWN_MASK), "Zoom To Fit", "Zooms the time scale to fit the data."); addAction(toolbar, zoomToFitAction); return toolbar; } /** * Creates the toolbar of the Gantt chart. * * @return The Gantt chart toolbar. */ protected JToolBar createGanttToolBar() { JToolBar toolbar = new JToolBar(JToolBar.VERTICAL); toolbar.setFloatable(false); addAction(toolbar, insertActivityRowAction); addAction(toolbar, deleteActivityRowAction); addAction(toolbar, makeConstraintAction); addAction(toolbar, deleteConstraintAction); return toolbar; } /** * Creates the toolbar of the Schedule chart. * * @return The Schedule chart toolbar. */ protected JToolBar createScheduleToolBar() { JToolBar toolbar = new JToolBar(JToolBar.VERTICAL); toolbar.setFloatable(false); addAction(toolbar, insertResourceRowAction); addAction(toolbar, deleteResourceRowAction); addAction(toolbar, makeReservationAction); addAction(toolbar, deleteReservationAction); return toolbar; } /** * Creates and returns the Gantt data model. * * @return The data model. */ protected IlvGanttModel createGanttModel() { return new SimpleEngineeringProject(gantt); } // ========================================= // Example Application // ========================================= /** * Returns the title of the example. * * @return The title of the example. */ Override public String getTitle() { return "Synchronized Gantt and Schedule Chart Example"; } /** * Application mainline. * * @param args * The command line arguments. */ public static void main(String[] args) { ExampleFrame.createAndShowGUI(DualChartExample.class); } }