/*
 * 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 scheduleChart;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

import javax.swing.ButtonGroup;
import javax.swing.JMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JToolBar;

import ilog.views.gantt.IlvGanttModel;
import ilog.views.gantt.IlvHierarchyChart;
import ilog.views.gantt.IlvScheduleChart;
import ilog.views.gantt.action.IlvAction;
import ilog.views.gantt.graphic.IlvActivityLayout;
import ilog.views.gantt.graphic.IlvActivityLogisticLayout;
import ilog.views.gantt.graphic.IlvActivitySimpleLayout;
import ilog.views.gantt.graphic.IlvActivityTileLayout;
import ilog.views.gantt.graphic.IlvDefaultActivityRendererFactory;
import ilog.views.gantt.graphic.renderer.IlvActivityBar;
import ilog.views.gantt.graphic.renderer.IlvActivityCompositeRenderer;
import ilog.views.gantt.graphic.renderer.IlvActivitySymbol;
import ilog.views.gantt.swing.IlvJTable;
import shared.AbstractGanttExample;
import shared.GanttCommand;
import shared.data.GeneralActivityFactory;
import shared.data.GeneralResourceFactory;
import shared.data.SimpleEngineeringProject;
import shared.swing.ExampleFrame;

/**
 * A Schedule chart example showing how to use <code>IlvScheduleChart</code>.
 */
public class ScheduleExample extends AbstractGanttExample {

  /**
   * The various menu and toolbar actions.
   */
  protected IlvAction makeReservationAction;
  protected IlvAction deleteReservationAction;

  // =========================================
  // Instance Construction and Initialization
  // =========================================

  /**
   * Creates the Schedule chart.
   *
   * @return The Schedule chart.
   */
  Override
  protected IlvHierarchyChart createChart() {
    return new IlvScheduleChart();
  }

  /**
   * Customizes the data model factories and graphic renderers of the Schedule
   * chart.
   */
  Override
  protected void customizeFactories() {
    // Change the default activity and resource factories of the Schedule chart
    // to ones that sequentially number the activities and resources.
    chart.setActivityFactory(new GeneralActivityFactory(chart));
    chart.setResourceFactory(new GeneralResourceFactory(chart));

    // Change the default activity renderer factory of the Schedule chart.
    chart.setActivityRendererFactory(new ActivityRendererFactory(chart));
  }

  /**
   * Customizes the appearance of the Schedule chart.
   */
  Override
  protected void customizeChart() {
    super.customizeChart();

    // Default column widths are 75. Resize some of the columns so that the
    // text is not truncated.
    IlvJTable table = chart.getTable();
    table.getColumn("Name").setPreferredWidth(150);
    table.getColumn("ID").setPreferredWidth(60);
    table.getColumn("Qty").setPreferredWidth(40);
  }

  // =========================================
  // Accessing
  // =========================================

  /**
   * Returns the Schedule chart.
   *
   * @return The Schedule chart.
   */
  public IlvScheduleChart getScheduleChart() {
    return (IlvScheduleChart) getChart();
  }

  /**
   * Returns whether any resources are currently selected.
   *
   * @return Whether any resources are selected.
   */
  public boolean isResourceSelected() {
    return chart.getSelectedRows().length > 0;
  }

  /**
   * Returns whether any reservations are currently selected.
   *
   * @return Whether any reservations are selected.
   */
  public boolean isReservationSelected() {
    return ((IlvScheduleChart) chart).getSelectedReservations().length > 0;
  }

  // =========================================
  // Menus
  // =========================================

  /**
   * Initializes the actions for the Edit menu.
   */
  protected void initEditActions() {
    IlvScheduleChart chart = (IlvScheduleChart) getChart();
    insertRowAction = new GanttCommand.InsertResourceAction(chart);
    deleteRowAction = new GanttCommand.DeleteSelectedRowsAction(chart);
    makeReservationAction = new GanttCommand.MakeActivityAction(chart);
    deleteReservationAction = new GanttCommand.DeleteSelectedReservationsAction(chart);
    deleteAllAction = new GanttCommand.DeleteSelectedAction(chart);
    rowExpandCollapseAction = new GanttCommand.RowExpandCollapseAction(chart);
    rowIndentAction = new GanttCommand.RowIndentAction(chart);
    rowOutdentAction = new GanttCommand.RowOutdentAction(chart);
    rowUpAction = new GanttCommand.RowUpAction(chart);
    rowDownAction = new GanttCommand.RowDownAction(chart);
    if (isExitAllowed()) {
      exitAction = new GanttCommand.ExitAction();
    }
  }

  /**
   * Creates the Edit menu.
   *
   * @return The Edit menu.
   */
  Override
  public JMenu createEditMenu() {
    JMenu menu = new JMenu("Edit");
    menu.setMnemonic(KeyEvent.VK_E);
    setHelpID(menu, "Menu.Edit.helpID");
    setStatusText(menu, "Adds, removes, or modifies resources and reservations.");
    initEditActions();

    // Menu item for "Insert new resource".
    int actionCount = 0;
    if (insertRowAction != null) {
      addAction(menu, insertRowAction);
      actionCount++;
    }

    // Menu item for "Delete selected resource".
    if (deleteRowAction != null) {
      addAction(menu, deleteRowAction);
      actionCount++;
    }

    // Menu item for "Create reservation".
    if (makeReservationAction != null) {
      addAction(menu, makeReservationAction);
      actionCount++;
    }

    // Menu item for "Delete selected reservations".
    if (deleteReservationAction != null) {
      addAction(menu, deleteReservationAction);
      actionCount++;
    }

    if (actionCount > 0) {
      menu.addSeparator();
    }

    // Menu item for "Delete all".
    if (deleteAllAction != null) {
      addAction(menu, deleteAllAction);
      menu.addSeparator();
    }

    // Menu item for "Expand/Collapse".
    actionCount = 0;
    if (rowExpandCollapseAction != null) {
      addAction(menu, rowExpandCollapseAction);
      actionCount++;
    }

    // Menu item for "Indent resource".
    if (rowIndentAction != null) {
      addAction(menu, rowIndentAction);
      actionCount++;
    }

    // Menu item for "Outdent resource".
    if (rowOutdentAction != null) {
      addAction(menu, rowOutdentAction);
      actionCount++;
    }

    // Menu item for "Move up".
    if (rowUpAction != null) {
      addAction(menu, rowUpAction);
      actionCount++;
    }

    // Menu item for "Move down".
    if (rowDownAction != null) {
      addAction(menu, rowDownAction);
      actionCount++;
    }

    // Menu item for "Exit".
    if (exitAction != null) {
      if (actionCount > 0) {
        menu.addSeparator();
      }
      addAction(menu, exitAction);
    }

    return menu;
  }

  /**
   * Creates the Row menu.
   *
   * @return The Row menu.
   */
  Override
  public JMenu createRowMenu() {
    JMenu menu = super.createRowMenu();
    setStatusText(menu, "Changes the chart's row height or activity layout.");

    menu.addSeparator();
    ButtonGroup buttonGroup = new ButtonGroup();
    final IlvScheduleChart scheduleChart = getScheduleChart();
    IlvActivityLayout layout = scheduleChart.getActivityLayout();

    // Menu item for "Simple Layout".
    JRadioButtonMenuItem simpleItem = new JRadioButtonMenuItem("Simple Layout");
    simpleItem.setSelected(layout.getClass() == IlvActivitySimpleLayout.class);
    buttonGroup.add(simpleItem);
    menu.add(simpleItem);
    simpleItem.addActionListener(new ActionListener() {
      Override
      public void actionPerformed(ActionEvent event) {
        scheduleChart.setActivityLayout(new IlvActivitySimpleLayout());
        scheduleChart.setRowHeight(scheduleChart.getRowHeight());
      }
    });
    setStatusText(simpleItem, "Uses a Simple Activity Layout for the schedule chart.");

    // Menu item for "Cascade Layout".
    JRadioButtonMenuItem cascadeItem = new JRadioButtonMenuItem("Cascade Layout");
    cascadeItem.setSelected(layout instanceof IlvActivityLogisticLayout
        && ((IlvActivityLogisticLayout) layout).getArrangeMode() == IlvActivityLogisticLayout.CASCADE);
    buttonGroup.add(cascadeItem);
    menu.add(cascadeItem);
    cascadeItem.addActionListener(new ActionListener() {
      Override
      public void actionPerformed(ActionEvent event) {
        scheduleChart.setActivityLayout(new IlvActivityLogisticLayout(IlvActivityLogisticLayout.CASCADE));
        scheduleChart.setRowHeight(scheduleChart.getRowHeight());
      }
    });
    setStatusText(cascadeItem, "Uses a Cascade Activity Layout for the schedule chart.");

    // Menu item for "Pretty Layout".
    JRadioButtonMenuItem prettyItem = new JRadioButtonMenuItem("Pretty Layout");
    prettyItem.setSelected(layout instanceof IlvActivityLogisticLayout
        && ((IlvActivityLogisticLayout) layout).getArrangeMode() == IlvActivityLogisticLayout.PRETTY);
    buttonGroup.add(prettyItem);
    menu.add(prettyItem);
    prettyItem.addActionListener(new ActionListener() {
      Override
      public void actionPerformed(ActionEvent event) {
        scheduleChart.setActivityLayout(new IlvActivityLogisticLayout(IlvActivityLogisticLayout.PRETTY));
        scheduleChart.setRowHeight(scheduleChart.getRowHeight());
      }
    });
    setStatusText(prettyItem, "Uses a Pretty Activity Layout for the schedule chart.");

    // Menu item for "Tile Layout".
    JRadioButtonMenuItem tileItem = new JRadioButtonMenuItem("Tile Layout");
    tileItem.setSelected(layout instanceof IlvActivityTileLayout);
    buttonGroup.add(tileItem);
    menu.add(tileItem);
    tileItem.addActionListener(new ActionListener() {
      Override
      public void actionPerformed(ActionEvent event) {
        scheduleChart.setActivityLayout(new IlvActivityTileLayout());
      }
    });
    setStatusText(tileItem, "Uses a Tile Activity Layout for the schedule chart.");

    return menu;
  }

  // =========================================
  // Toolbar
  // =========================================

  /**
   * Populates the toolbar edit actions.
   *
   * @param toolbar
   *          The toolbar.
   */
  Override
  protected void populateToolBarEditActions(JToolBar toolbar) {
    super.populateToolBarEditActions(toolbar);
    addAction(toolbar, makeReservationAction);
    addAction(toolbar, deleteReservationAction);
    addAction(toolbar, deleteAllAction);
  }

  // =========================================
  // Data Model
  // =========================================

  /**
   * Creates and returns the Gantt data model.
   *
   * @return The Gantt data model.
   */
  Override
  protected IlvGanttModel createGanttModel() {
    return new SimpleEngineeringProject(chart);
  }

  // =========================================
  // Example Application
  // =========================================

  /**
   * Returns the title of the example.
   *
   * @return The title of the example.
   */
  Override
  public String getTitle() {
    return "Schedule Chart Example";
  }

  /**
   * Application mainline.
   *
   * @param args
   *          The command line arguments.
   */
  public static void main(String[] args) {
    ExampleFrame.createAndShowGUI(ScheduleExample.class);
  }

  /**
   * This class shows how to customize the default activity renderer factory.
   * The factory resets the parent activity renderer and the leaf activity
   * renderer of the <code>IlvDefaultActivityRendererFactory</code>.
   */
  class ActivityRendererFactory extends IlvDefaultActivityRendererFactory {

    /**
     * Creates the activity renderer factory.
     *
     * @param chart
     *          The chart that the factory is associated with.
     */
    public ActivityRendererFactory(IlvHierarchyChart chart) {
      super(chart);

      // Define the new leaf activity renderer.
      IlvActivityBar leafRenderer = new IlvActivityBar();
      leafRenderer.setStyle(IlvActivityBar.RELIEF);
      leafRenderer.setBackground(Color.orange);
      leafRenderer.setThickness(1);
      // Reset the leaf activity renderer
      setLeafActivityRenderer(leafRenderer);

      // Define the parent activity renderer. The new parent
      // activity renderer is composed of an activity bar as
      // the main bar and two diamonds as end symbols.
      IlvActivityCompositeRenderer parentRenderer = new IlvActivityCompositeRenderer();
      IlvActivityBar mainBar = new IlvActivityBar();
      IlvActivitySymbol startSymbol = new IlvActivitySymbol();
      IlvActivitySymbol endSymbol = new IlvActivitySymbol();
      startSymbol.setShape(IlvActivitySymbol.DIAMOND);
      endSymbol.setShape(IlvActivitySymbol.DIAMOND);
      mainBar.setBackground(Color.yellow);
      mainBar.setThickness(0);
      startSymbol.setForeground(Color.cyan);
      endSymbol.setForeground(Color.cyan);
      endSymbol.setAlignment(IlvActivitySymbol.END);
      parentRenderer.addRenderer(mainBar);
      parentRenderer.addRenderer(startSymbol);
      parentRenderer.addRenderer(endSymbol);
      // Resets the parent activity renderer
      setParentActivityRenderer(parentRenderer);
    }
  }
}