/* * 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 shared; import ilog.views.IlvManagerViewInteractor; import ilog.views.event.InteractorChangedEvent; import ilog.views.event.InteractorListener; import ilog.views.gantt.*; import ilog.views.gantt.action.IlvAction; import ilog.views.gantt.event.SelectionEvent; import ilog.views.gantt.event.SelectionListener; import ilog.views.gantt.graphic.IlvGanttSheet; import ilog.views.gantt.graphic.interactor.IlvGanttSelectInteractor; import ilog.views.gantt.graphic.interactor.IlvMakeActivityInteractor; import ilog.views.gantt.graphic.interactor.IlvMakeConstraintInteractor; import ilog.views.gantt.model.IlvDefaultGanttModel; import ilog.views.util.time.IlvCalendarUtil; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.util.Calendar; import java.util.Date; import javax.swing.JComponent; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; /** * This class groups a set of very useful action inner classes that can be * applied to a Gantt chart or Schedule chart. These actions can be invoked by a * menu item, a button in a toolbar, or an accelerator keystroke. */ public class GanttCommand { /** * Deletes the specified activity or resource from the data model. */ public static void removeFromGanttModel(IlvGanttModel model, IlvHierarchyNode activityOrResource) { if (!model.contains(activityOrResource)) { return; } if (activityOrResource instanceof IlvResource) { IlvResource r = (IlvResource) activityOrResource; if (model.getRootResource() == r) { model.setRootResource(null); } else { model.removeResource(r); } } else if (activityOrResource instanceof IlvActivity) { IlvActivity a = (IlvActivity) activityOrResource; if (model.getRootActivity() == a) { model.setRootActivity(null); } else { model.removeActivity(a); } } } /** * Deletes the specified constraint from the data model. */ public static void removeFromGanttModel(IlvGanttModel model, IlvConstraint constraint) { if (!model.contains(constraint)) { return; } model.removeConstraint(constraint); } /** * Deletes the specified reservation from the data model. */ public static void removeFromGanttModel(IlvGanttModel model, IlvReservation reservation) { if (!model.contains(reservation)) { return; } model.removeReservation(reservation); } /** * An action that exits the current application. */ public static class ExitAction extends IlvAction { /** * Creates a new <code>ExitAction</code>. */ public ExitAction() { super("Exit", null, KeyStroke.getKeyStroke(KeyEvent.VK_X, KeyEvent.ALT_DOWN_MASK), "Exit", "Exits the example."); } /** * Performs the exit action. */ Override public void actionPerformed(ActionEvent event) { System.exit(0); } } /** * An action that creates an empty default data model for the specified chart. */ public static class NewDataModelAction extends IlvAction { /** * The chart. */ private IlvHierarchyChart chart; /** * Creates a new <code>NewDataModelAction</code>. */ public NewDataModelAction(IlvHierarchyChart chart) { super("New", null, KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.CTRL_DOWN_MASK), "Create New Project", "Creates a new project."); this.chart = chart; setIcon(GanttCommand.class, "images/new.gif"); } /** * Performs the action. */ Override public void actionPerformed(ActionEvent event) { chart.setGanttModel(new IlvDefaultGanttModel()); } } /** * An action that inserts a new activity into the specified Gantt chart. */ public static class InsertActivityAction extends IlvAction { /** * The chart. */ private IlvGanttChart chart; /** * Creates a new <code>InsertActivityAction</code>. */ public InsertActivityAction(IlvGanttChart chart) { super("Insert Activity", null, KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, 0), "Insert Activity", "Inserts a new activity below the selected activity."); this.chart = chart; setIcon(GanttCommand.class, "images/insertrow.gif"); } /** * Performs the action. */ Override public void actionPerformed(ActionEvent event) { IlvGanttModel model = chart.getGanttModel(); if (model == null) { return; } IlvActivityFactory factory = chart.getActivityFactory(); Calendar calendar = Calendar.getInstance(); IlvCalendarUtil.dayFloor(calendar); Date today = calendar.getTime(); IlvTimeInterval interval = new IlvTimeInterval(today, IlvDuration.ONE_DAY.multiply(4)); IlvActivity newact = factory.createActivity(interval); IlvActivity root = model.getRootActivity(); if (root == null) { model.setRootActivity(newact); } else { IlvActivity[] selected = chart.getSelectedActivities(); if (selected.length > 0 && selected[0] != root) { IlvActivity curact = selected[0]; IlvActivity parent = model.getParentActivity(curact); int index = model.getParentActivityIndex(curact); model.addActivity(newact, parent, index + 1); } else { int index = model.getChildActivityCount(root); model.addActivity(newact, root, index); } } chart.deSelectAllRows(); chart.select(newact, true); makeRowDisplayedLater(chart, newact); } } /** * An action that inserts a new milestone into the specified Gantt chart. */ public static class InsertMilestoneAction extends IlvAction { /** * The chart. */ private IlvGanttChart chart; /** * Creates a new <code>InsertMilestoneAction</code>. */ public InsertMilestoneAction(IlvGanttChart chart) { super("Insert Milestone", null, KeyStroke.getKeyStroke(KeyEvent.VK_M, KeyEvent.ALT_DOWN_MASK), "Insert Milestone", "Inserts a new milestone below the selected activity."); this.chart = chart; setIcon(GanttCommand.class, "images/insertmilestone.gif"); } /** * Performs the action. */ Override public void actionPerformed(ActionEvent event) { IlvGanttModel model = chart.getGanttModel(); if (model == null) { return; } IlvActivityFactory factory = chart.getActivityFactory(); Calendar calendar = Calendar.getInstance(); IlvCalendarUtil.dayFloor(calendar); Date today = calendar.getTime(); IlvTimeInterval interval = new IlvTimeInterval(today, today); IlvActivity newact = factory.createActivity(interval); IlvActivity root = model.getRootActivity(); if (root == null) { model.setRootActivity(newact); } else { IlvActivity[] selected = chart.getSelectedActivities(); if (selected.length > 0 && selected[0] != root) { IlvActivity curact = selected[0]; IlvActivity parent = model.getParentActivity(curact); int index = model.getParentActivityIndex(curact); model.addActivity(newact, parent, index + 1); } else { int index = model.getChildActivityCount(root); model.addActivity(newact, root, index); } } chart.deSelectAllRows(); chart.select(newact, true); makeRowDisplayedLater(chart, newact); } } /** * An action that inserts a new resource into the specified Schedule chart. */ public static class InsertResourceAction extends IlvAction { /** * The chart. */ private IlvScheduleChart chart; /** * Creates a new <code>InsertResourceAction</code>. */ public InsertResourceAction(IlvScheduleChart chart) { super("Insert Resource", null, KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, 0), "Insert Resource", "Inserts a new resource below the selected resource."); this.chart = chart; setIcon(GanttCommand.class, "images/insertrow.gif"); } /** * Performs the action. */ Override public void actionPerformed(ActionEvent event) { IlvGanttModel model = chart.getGanttModel(); if (model == null) { return; } IlvResourceFactory factory = chart.getResourceFactory(); IlvResource newres = factory.createResource(); IlvResource root = model.getRootResource(); if (root == null) { model.setRootResource(newres); } else { IlvResource[] selected = chart.getSelectedResources(); if (selected.length > 0 && selected[0] != root) { IlvResource curres = selected[0]; IlvResource parent = model.getParentResource(curres); int index = model.getParentResourceIndex(curres); model.addResource(newres, parent, index + 1); } else { int index = model.getChildResourceCount(root); model.addResource(newres, root, index); } } chart.deSelectAllRows(); chart.select(newres, true); makeRowDisplayedLater(chart, newres); } } /** * An action that deletes all the selected rows and graphics from the * specified charts. */ public static class DeleteSelectedAction extends IlvAction { /** * The array of charts. */ private IlvHierarchyChart[] charts; /** * Creates a new <code>DeleteSelectedAction</code>. * * @param charts The array of charts to which the action applies. */ public DeleteSelectedAction(IlvHierarchyChart... charts) { super("Delete", null, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "Delete", ""); this.charts = charts; setIcon(GanttCommand.class, "images/delete.gif"); setLongDescription(computeLongDescription()); SelectionListener selectionListener = new SelectionListener() { Override public void selectionChanged(SelectionEvent event) { computeEnabled(); } }; for (IlvHierarchyChart chart : charts) { chart.addSelectionListener(selectionListener); } computeEnabled(); } /** * Computes the long description of this action. */ private String computeLongDescription() { boolean activities = false; boolean resources = false; for (IlvHierarchyChart chart : charts) { if (chart.getRowType() == IlvGanttConfiguration.ACTIVITY_ROWS) { activities = true; } else { resources = true; } } if (activities && resources) { return "Deletes the selected activities, resources, constraints, and reservations."; } else if (activities) { return "Deletes the selected activities and constraints."; } else { return "Deletes the selected resources and reservations."; } } /** * Computes whether this action should be enabled or not. */ private void computeEnabled() { for (IlvHierarchyChart chart : charts) { if (chart.getSelectedRows().length > 0 || chart.getSelectedGraphics().length > 0) { setEnabled(true); return; } } setEnabled(false); } /** * Performs the action. * * @param event The event that triggers the action. */ Override public void actionPerformed(ActionEvent event) { for (IlvHierarchyChart chart : charts) { IlvGanttModel model = chart.getGanttModel(); // First, delete all the selected rows. IlvHierarchyNode[] selected = chart.getSelectedRows(); for (IlvHierarchyNode row : selected) { removeFromGanttModel(model, row); } // Next, delete the selected reservations. if (chart instanceof IlvScheduleChart) { IlvReservation[] reservations = ((IlvScheduleChart) chart).getSelectedReservations(); for (IlvReservation reservation : reservations) { removeFromGanttModel(model, reservation); } } // Finally, delete the selected constraints. IlvConstraint[] constraints = chart.getSelectedConstraints(); for (IlvConstraint constraint : constraints) { removeFromGanttModel(model, constraint); } } } } /** * An action that deletes the selected rows from the specified chart. If the * chart is a Gantt chart, the action deletes activities. If the chart is a * Schedule chart, the action deletes resources. */ public static class DeleteSelectedRowsAction extends IlvAction { /** * The chart. */ private IlvHierarchyChart chart; /** * Creates a new <code>DeleteSelectedRowsAction</code>. */ public DeleteSelectedRowsAction(IlvHierarchyChart chart) { super(chart instanceof IlvGanttChart ? "Delete Activity" : "Delete Resource", null, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, KeyEvent.CTRL_DOWN_MASK), chart instanceof IlvGanttChart ? "Delete Activity" : "Delete Resource", chart instanceof IlvGanttChart ? "Deletes the selected activities." : "Deletes the selected resources."); this.chart = chart; setIcon(GanttCommand.class, "images/deleterow.gif"); chart.addSelectionListener(new SelectionListener() { Override public void selectionChanged(SelectionEvent event) { computeEnabled(); } }); computeEnabled(); } /** * Computes whether this action should be enabled or not. */ private void computeEnabled() { setEnabled(chart.getSelectedRows().length > 0); } /** * Performs the action. */ Override public void actionPerformed(ActionEvent event) { IlvGanttModel model = chart.getGanttModel(); IlvHierarchyNode[] selected = chart.getSelectedRows(); for (IlvHierarchyNode row : selected) { removeFromGanttModel(model, row); } } } /** * An action that deletes the selected constraints from the specified * chart. */ public static class DeleteSelectedConstraintsAction extends IlvAction { /** * The chart. */ private IlvHierarchyChart chart; /** * Creates a new <code>DeleteSelectedConstraintsAction</code>. */ public DeleteSelectedConstraintsAction(IlvHierarchyChart chart) { super("Delete Constraint", null, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, KeyEvent.SHIFT_DOWN_MASK), "Delete Constraint", "Deletes the selected constraints."); this.chart = chart; setIcon(GanttCommand.class, "images/deleteconstraint.gif"); chart.addSelectionListener(new SelectionListener() { Override public void selectionChanged(SelectionEvent event) { computeEnabled(); } }); computeEnabled(); } /** * Computes whether this action should be enabled or not. */ private void computeEnabled() { setEnabled(chart.getSelectedConstraints().length > 0); } /** * Performs the action. */ Override public void actionPerformed(ActionEvent event) { IlvGanttModel model = chart.getGanttModel(); IlvConstraint[] constraints = chart.getSelectedConstraints(); for (IlvConstraint constraint : constraints) { removeFromGanttModel(model, constraint); } } } /** * An action that deletes the selected reservations from the specified * Schedule chart. */ public static class DeleteSelectedReservationsAction extends IlvAction { /** * The chart. */ private IlvScheduleChart chart; /** * Creates a new <code>DeleteSelectedReservationsAction</code>. */ public DeleteSelectedReservationsAction(IlvScheduleChart chart) { super("Delete Reservation", null, KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, KeyEvent.SHIFT_DOWN_MASK), "Delete Reservation", "Deletes the selected reservations."); this.chart = chart; setIcon(GanttCommand.class, "images/deleteactivity.gif"); chart.addSelectionListener(new SelectionListener() { Override public void selectionChanged(SelectionEvent event) { computeEnabled(); } }); computeEnabled(); } /** * Computes whether this action should be enabled or not. */ private void computeEnabled() { setEnabled(chart.getSelectedReservations().length > 0); } /** * Performs the action. */ Override public void actionPerformed(ActionEvent event) { IlvGanttModel model = chart.getGanttModel(); IlvReservation[] reservations = chart.getSelectedReservations(); for (IlvReservation reservation : reservations) { removeFromGanttModel(model, reservation); } } } /** * An action that installs the constraint creation interactor on the specified * chart. */ public static class MakeConstraintAction extends IlvAction { /** * The chart. */ private IlvHierarchyChart chart; /** * The ESC key. */ private KeyStroke escKey; /** * The ESC key action. */ private ActionListener escAction; /** * Creates a new <code>MakeConstraintAction</code>. */ public MakeConstraintAction(IlvHierarchyChart chart) { super("Create Constraint", null, KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.ALT_DOWN_MASK), "Create Constraint", "Creates a new constraint using the mouse."); this.chart = chart; setIcon(GanttCommand.class, "images/constraint.gif"); escKey = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); // Define the ESC action that will abort the current make-constraint // interactor. This supplements the built-in ESC key handling of the // interactor itself, since the interactor only receives keystrokes // when the Gantt sheet has the focus. This action will be registered // as an application-wide accelerator. escAction = new ActionListener() { Override public void actionPerformed(ActionEvent actionEvent) { IlvHierarchyChart chart = MakeConstraintAction.this.chart; IlvGanttSheet ganttSheet = chart.getGanttSheet(); IlvManagerViewInteractor current = ganttSheet.getInteractor(); if (current instanceof IlvMakeConstraintInteractor) { ((IlvMakeConstraintInteractor) current).abort(); } } }; // Listen for changes in the Gantt sheet's current interactor. When // a make-constraint interactor is set, we register the ESC action // application-wide. When a make-constraint interactor is unset, we // unregister the ESC action. chart.getGanttSheet().addInteractorListener(new InteractorListener() { Override public void interactorChanged(InteractorChangedEvent event) { IlvHierarchyChart chart = MakeConstraintAction.this.chart; if (event.getOldValue()instanceof IlvMakeConstraintInteractor) { chart.unregisterKeyboardAction(escKey); } if (event.getNewValue()instanceof IlvMakeConstraintInteractor) { chart.registerKeyboardAction(escAction, escKey, JComponent.WHEN_IN_FOCUSED_WINDOW); } } }); } /** * Performs the action by setting the make-constraint interactor onto * the Gantt sheet. */ Override public void actionPerformed(ActionEvent event) { IlvGanttSheet ganttSheet = chart.getGanttSheet(); IlvManagerViewInteractor current = ganttSheet.getInteractor(); if (current instanceof IlvMakeConstraintInteractor) { return; } IlvMakeConstraintInteractor lnkinter = new IlvMakeConstraintInteractor(); ganttSheet.pushInteractor(lnkinter); } } /** * An action that installs the activity creation interactor on the specified * chart. */ public static class MakeActivityAction extends IlvAction { /** * The chart. */ private IlvHierarchyChart chart; /** * Creates a new <code>MakeActivityAction</code>. */ public MakeActivityAction(IlvHierarchyChart chart) { super(chart instanceof IlvGanttChart ? "Create Activity" : "Create Reservation", null, chart instanceof IlvGanttChart ? KeyStroke.getKeyStroke(KeyEvent.VK_A, KeyEvent.ALT_DOWN_MASK) : KeyStroke.getKeyStroke(KeyEvent.VK_R, KeyEvent.ALT_DOWN_MASK), chart instanceof IlvGanttChart ? "Create Activity" : "Create Reservation", chart instanceof IlvGanttChart ? "Creates a new activity using the mouse." : "Creates a new reservation using the mouse."); this.chart = chart; setIcon(GanttCommand.class, "images/newactivity.gif"); } /** * Performs the action. */ Override public void actionPerformed(ActionEvent event) { IlvManagerViewInteractor current = chart.getGanttSheet().getInteractor(); if (current instanceof IlvMakeActivityInteractor) { return; } IlvMakeActivityInteractor inter = new IlvMakeActivityInteractor(); if (current instanceof IlvGanttSelectInteractor) { inter. setGhostMode(!((IlvGanttSelectInteractor) current).isOpaqueMove()); } chart.getGanttSheet().pushInteractor(inter); } } /** * An action that outdents the first selected row of the specified chart to a * higher hierarchy level. If the chart is a Gantt chart, the action outdents * activities. If the chart is a Schedule chart, the action outdents * resources. */ public static class RowOutdentAction extends IlvAction { /** * The chart. */ private IlvHierarchyChart chart; /** * Creates a new <code>RowOutdentAction</code>. */ public RowOutdentAction(IlvHierarchyChart chart) { super(chart instanceof IlvGanttChart ? "Outdent Activity" : "Outdent Resource", null, KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, KeyEvent.CTRL_DOWN_MASK), chart instanceof IlvGanttChart ? "Outdent Activity" : "Outdent Resource", chart instanceof IlvGanttChart ? "Outdents the selected activity." : "Outdents the selected resource."); this.chart = chart; setIcon(GanttCommand.class, "images/outdent.gif"); chart.addSelectionListener(new SelectionListener() { Override public void selectionChanged(SelectionEvent event) { computeEnabled(); } }); computeEnabled(); } /** * Computes whether this action should be enabled or not. */ private void computeEnabled() { setEnabled(chart.getSelectedRows().length > 0); } /** * Performs the action. */ Override public void actionPerformed(ActionEvent event) { IlvHierarchyNode[] selectedRows = chart.getSelectedRows(); if (selectedRows.length == 0) { return; } IlvHierarchyNode row = selectedRows[0]; IlvGanttModelUtil.promote(chart.getGanttModel(), row); makeRowDisplayedLater(chart, row); } } /** * An action that indents the first selected row of the specified chart to a * lower hierarchy level. If the chart is a Gantt chart, the action indents * activities. If the chart is a Schedule chart, the action indents resources. */ public static class RowIndentAction extends IlvAction { /** * The chart. */ private IlvHierarchyChart chart; /** * Creates a new <code>RowIndentAction</code>. */ public RowIndentAction(IlvHierarchyChart chart) { super(chart instanceof IlvGanttChart ? "Indent Activity" : "Indent Resource", null, KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, KeyEvent.CTRL_DOWN_MASK), chart instanceof IlvGanttChart ? "Indent Activity" : "Indent Resource", chart instanceof IlvGanttChart ? "Indents the selected activity." : "Indents the selected resource."); this.chart = chart; setIcon(GanttCommand.class, "images/indent.gif"); chart.addSelectionListener(new SelectionListener() { Override public void selectionChanged(SelectionEvent event) { computeEnabled(); } }); computeEnabled(); } /** * Computes whether this action should be enabled or not. */ private void computeEnabled() { setEnabled(chart.getSelectedRows().length > 0); } /** * Performs the action. */ Override public void actionPerformed(ActionEvent event) { IlvHierarchyNode[] selectedRows = chart.getSelectedRows(); if (selectedRows.length == 0) { return; } IlvGanttModel model = chart.getGanttModel(); IlvHierarchyNode row = selectedRows[0]; IlvGanttModelUtil.demote(model, row); IlvHierarchyNode newParent = model.getParent(row); if (newParent != null && !chart.isRowExpanded(newParent)) { chart.expandRow(newParent); chart.selectRow(row, true); } makeRowDisplayedLater(chart, row); } } /** * An action that moves the first selected row of the specified chart upwards. * If the chart is a Gantt chart, the action moves activities. If the chart is * a Schedule chart, the action moves resources. */ public static class RowUpAction extends IlvAction { /** * The chart. */ private IlvHierarchyChart chart; /** * Creates a new <code>RowUpAction</code>. */ public RowUpAction(IlvHierarchyChart chart) { super(chart instanceof IlvGanttChart ? "Move Activity Up" : "Move Resource Up", null, KeyStroke.getKeyStroke(KeyEvent.VK_UP, KeyEvent.CTRL_DOWN_MASK), chart instanceof IlvGanttChart ? "Move Activity Up" : "Move Resource Up", chart instanceof IlvGanttChart ? "Moves the selected activity up." : "Moves the selected resource up."); this.chart = chart; setIcon(GanttCommand.class, "images/up.gif"); chart.addSelectionListener(new SelectionListener() { Override public void selectionChanged(SelectionEvent event) { computeEnabled(); } }); computeEnabled(); } /** * Computes whether this action should be enabled or not. */ private void computeEnabled() { setEnabled(chart.getSelectedRows().length > 0); } /** * Performs the action. */ Override public void actionPerformed(ActionEvent event) { IlvHierarchyNode[] selectedRows = chart.getSelectedRows(); if (selectedRows.length == 0) { return; } IlvGanttModel model = chart.getGanttModel(); IlvHierarchyNode row = selectedRows[0]; IlvHierarchyNode parent = model.getParent(row); if (parent == null) { return; } int index = model.getParentIndex(row); if (index == 0) { return; } if (row instanceof IlvActivity) { model.moveActivity((IlvActivity) row, (IlvActivity) parent, index - 1); } else { model.moveResource((IlvResource) row, (IlvResource) parent, index - 1); } makeRowDisplayedLater(chart, row); } } /** * An action that moves the first selected row of the specified chart * downwards. * If the chart is a Gantt chart, the action moves activities. If the chart is * a Schedule chart, the action moves resources. */ public static class RowDownAction extends IlvAction { /** * The chart. */ private IlvHierarchyChart chart; /** * Creates a new <code>RowDownAction</code>. */ public RowDownAction(IlvHierarchyChart chart) { super(chart instanceof IlvGanttChart ? "Move Activity Down" : "Move Resource Down", null, KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, KeyEvent.CTRL_DOWN_MASK), chart instanceof IlvGanttChart ? "Move Activity Down" : "Move Resource Down", chart instanceof IlvGanttChart ? "Moves the selected activity down." : "Moves the selected resource down."); this.chart = chart; setIcon(GanttCommand.class, "images/down.gif"); chart.addSelectionListener(new SelectionListener() { Override public void selectionChanged(SelectionEvent event) { computeEnabled(); } }); computeEnabled(); } /** * Computes whether this action should be enabled or not. */ private void computeEnabled() { setEnabled(chart.getSelectedRows().length > 0); } /** * Performs the action. */ Override public void actionPerformed(ActionEvent event) { IlvHierarchyNode[] selectedRows = chart.getSelectedRows(); if (selectedRows.length == 0) { return; } IlvGanttModel model = chart.getGanttModel(); IlvHierarchyNode row = selectedRows[0]; IlvHierarchyNode parent = model.getParent(row); if (parent == null) { return; } int index = model.getParentIndex(row); if (index == model.getChildCount(parent) - 1) { return; } if (row instanceof IlvActivity) { model.moveActivity((IlvActivity) row, (IlvActivity) parent, index + 1); } else { model.moveResource((IlvResource) row, (IlvResource) parent, index + 1); } makeRowDisplayedLater(chart, row); } } /** * An action that toggles the expansion of the selected rows in the * specified charts. */ public static class RowExpandCollapseAction extends IlvAction { /** * The array of charts. */ private IlvHierarchyChart[] charts; /** * Creates a new <code>RowExpandCollapseAction</code>. * * @param charts The array of charts to which the action applies. */ public RowExpandCollapseAction(IlvHierarchyChart... charts) { super("", null, KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, KeyEvent.CTRL_DOWN_MASK), "", ""); this.charts = charts; setIcon(GanttCommand.class, "images/plusminus.gif"); setName(computeShortDescription()); setShortDescription(computeShortDescription()); setLongDescription(computeLongDescription()); SelectionListener selectionListener = new SelectionListener() { Override public void selectionChanged(SelectionEvent event) { computeEnabled(event); } }; for (IlvHierarchyChart chart : charts) { chart.addSelectionListener(selectionListener); } computeEnabled(null); } /** * Computes the short description of this action. */ private String computeShortDescription() { boolean activities = false; boolean resources = false; for (IlvHierarchyChart chart : charts) { if (chart.getRowType() == IlvGanttConfiguration.ACTIVITY_ROWS) { activities = true; } else { resources = true; } } if (activities && resources) { return "Expand/Collapse Activities and Resources"; } else if (activities) { return "Expand/Collapse Activities"; } else { return "Expand/Collapse Resources"; } } /** * Computes the long description of this action. */ private String computeLongDescription() { boolean activities = false; boolean resources = false; for (IlvHierarchyChart chart : charts) { if (chart.getRowType() == IlvGanttConfiguration.ACTIVITY_ROWS) { activities = true; } else { resources = true; } } if (activities && resources) { return "Toggles expansion of the selected activities and resources."; } else if (activities) { return "Toggles expansion of the selected activities."; } else { return "Toggles expansion of the selected resources."; } } /** * Computes whether this action should be enabled or not for the specified chart. * This method returns <code>null</code> if the event cannot be applied to the * chart. */ private Boolean computeEnabled(IlvHierarchyChart chart, SelectionEvent event) { int chartType = chart.getRowType(); if (event != null) { if (event.isAdjusting()) { return null; } Object eventSource = event.getSource(); if (chartType == IlvGanttConfiguration.ACTIVITY_ROWS) { if (!(eventSource instanceof IlvActivity)) { return null; } } else if (chartType == IlvGanttConfiguration.RESOURCE_ROWS) { if (!(eventSource instanceof IlvResource)) { return null; } } } IlvGanttModel model = chart.getGanttModel(); IlvHierarchyNode[] selectedRows = chart.getSelectedRows(); for (IlvHierarchyNode row : selectedRows) { if (IlvGanttModelUtil.hasChildren(model, row)) { return true; } } return false; } /** * Computes whether this action should be enabled or not. */ private void computeEnabled(SelectionEvent event) { Boolean enable = null; for (IlvHierarchyChart chart : charts) { Boolean chartResult = computeEnabled(chart, event); if (chartResult != null) { if (enable == null) { enable = chartResult; } else { enable = enable || chartResult; } } } if (enable != null) { setEnabled(enable); } } /** * Performs the action. */ Override public void actionPerformed(ActionEvent event) { Boolean expanded = null; for (IlvHierarchyChart chart : charts) { IlvGanttModel model = chart.getGanttModel(); IlvHierarchyNode[] selectedRows = chart.getSelectedRows(); for (IlvHierarchyNode row : selectedRows) { if (IlvGanttModelUtil.hasChildren(model, row)) { if (expanded == null) { expanded = chart.isRowExpanded(row); } if (expanded) { chart.collapseRow(row); } else { chart.expandRow(row); } } } } } } /** * An action that changes the height of the rows in the specified charts. */ public static class RowHeightAction extends IlvAction { /** * The array of charts. */ private IlvHierarchyChart[] charts; /** * The amount to change the row height. */ private int delta; /** * The minimum row height. */ private int minRowHeight = 12; /** * The maximum row height. */ private int maxRowHeight = 50; /** * Creates a new <code>RowHeightAction</code>. * * @param delta The number of pixels to change the height of the chart rows by. * @param charts The array of charts to which the action applies. */ public RowHeightAction(int delta, IlvHierarchyChart... charts) { super((delta >= 0) ? "Increase " + delta + " Pixels" : "Decrease " + (-delta) + " Pixels", null, null, (delta >= 0) ? "Increase Row Height " + delta + " Pixels" : "Decrease Row Height " + (-delta) + " Pixels", (delta >= 0) ? "Increases the row height by " + delta + " pixels." : "Decreases the row height by " + (-delta) + " pixels."); this.charts = charts; this.delta = delta; } /** * Returns the amount that the row height will be changed. */ public int getDelta() { return delta; } /** * Returns the minimum row height. */ public int getMinRowHeight() { return minRowHeight; } /** * Sets the minimum row height. */ public void setMinRowHeight(int min) { minRowHeight = min; } /** * Returns the maximum row height. */ public int getMaxRowHeight() { return maxRowHeight; } /** * Sets the maximum row height. */ public void setMaxRowHeight(int max) { maxRowHeight = max; } /** * Performs the action. */ Override public void actionPerformed(ActionEvent event) { for (IlvHierarchyChart chart : charts) { int height = chart.getRowHeight(); height += delta; height = Math.max(height, minRowHeight); height = Math.min(height, maxRowHeight); chart.setRowHeight(height); } } } /** * Ensures that the specified <i>row</i> is displayed, by calling the chart's * <code>makeRowDisplayed()</code> method on the Swing event queue. It is * necessary to use this technique and delay execution of the chart's * <code>makeRowDisplayed()</code> method when row visibilities have * just been modified. This is because the chart also updates its internal * knowledge of which rows are within the display area on the Swing event * queue. */ public static void makeRowDisplayedLater(final IlvHierarchyChart chart, final IlvHierarchyNode row) { SwingUtilities.invokeLater(new Runnable() { Override public void run() { chart.makeRowDisplayed(row); } }); } }