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

import java.awt.Container;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.IOException;
import java.net.URL;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JLayeredPane;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;

import ilog.views.gantt.IlvGanttModel;
import ilog.views.gantt.IlvHierarchyChart;
import ilog.views.gantt.action.IlvAction;
import ilog.views.util.IlvImageUtil;
import ilog.views.util.styling.IlvStylable;
import ilog.views.util.swing.IlvSwingUtil;
import scheduleChart.ScheduleExample;
import shared.GanttCommand;
import shared.swing.CSSComboBox;
import shared.swing.CustomizerPanel;
import shared.swing.ExampleFrame;
import xml.XMLGanttActions;

/**
 * This is an extension to the Schedule Chart example that illustrates how to
 * style a Schedule chart with CSS.
 */
public class ScheduleCSSExample extends ScheduleExample {

  /**
   * The directory containing the data files (css+xml).
   */
  static final String DATA_DIRECTORY = "data";

  /**
   * The name of the default data file.
   */
  static final String DEFAULT_DATA_FILE = "data.xml";

  /**
   * The sample CSS files. Used in applets.
   */
  static final String[] CSS_FILES = { "activity-completion", "green-look", "standard-look" };

  /**
   * The CSS viewer.
   */
  protected JEditorPane editor;

  /**
   * The scroll pane.
   */
  protected JScrollPane scpane;

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

  /**
   * Creates the Schedule chart.
   *
   * @return The Schedule chart.
   */
  Override
  protected IlvHierarchyChart createChart() {
    IlvHierarchyChart chart = super.createChart();
    // Set the debug mask for CSS.
    chart.setStyleSheetDebugMask(IlvStylable.BAD_PROP_MASK | IlvStylable.BAD_CLASS_MASK
        | IlvStylable.FAILED_CONVERSIONS_MASK | IlvStylable.WARNING_PROP_MASK | IlvStylable.BAD_PROP_WITH_STACK_MASK);

    return chart;
  }

  // =========================================
  // XML Menu and Toolbar Actions
  // =========================================

  /**
   * The various menu and toolbar actions.
   */
  protected IlvAction newAction;
  protected IlvAction openAction;
  protected IlvAction saveAsAction;

  /**
   * Creates the "File" menu.
   *
   * @return The File menu.
   */
  public JMenu createFileMenu() {
    IlvHierarchyChart chart = getChart();
    JMenu menu = new JMenu("File");
    menu.setMnemonic(KeyEvent.VK_F);
    setStatusText(menu, "File operations");

    // Menu item for "New".
    newAction = new GanttCommand.NewDataModelAction(chart);
    addAction(menu, newAction);

    if (isLocalFileAccessAllowed()) {
      // Menu item for "Open ...".
      openAction = new XMLGanttActions.OpenXMLAction(chart);
      addAction(menu, openAction);

      // Menu item for "Save ...".
      saveAsAction = new XMLGanttActions.SaveAsXMLAction(chart);
      addAction(menu, saveAsAction);

      // Initialize the default directory for the file chooser.
      XMLGanttActions.setCurrentDirectory(new File(DATA_DIRECTORY));
    }

    // Menu item for "Exit".
    if (isExitAllowed()) {
      menu.addSeparator();
      addAction(menu, exitAction);
    }

    return menu;
  }

  /**
   * Populates the toolbar file actions.
   *
   * @param toolbar
   *          The toolbar.
   */
  Override
  protected void populateToolBarFileActions(JToolBar toolbar) {
    if (newAction != null) {
      addAction(toolbar, newAction);
    }
    if (openAction != null) {
      addAction(toolbar, openAction);
    }
    if (saveAsAction != null) {
      addAction(toolbar, saveAsAction);
    }
  }

  // =========================================
  // CSS Customizer Panel
  // =========================================

  /**
   * Adds the tabbed pages to the customizer panel.
   *
   * @param customizerPanel
   *          The customizer panel.
   */
  Override
  protected void addCustomizerTabs(JTabbedPane customizerPanel) {
    customizerPanel.addTab("CSS", createCSSCustomizer());
    super.addCustomizerTabs(customizerPanel);
  }

  /**
   * Creates and returns a customizer for applying and viewing style sheets.
   *
   * @return The CSS customizer.
   */
  protected JComponent createCSSCustomizer() {
    CustomizerPanel panel = new CustomizerPanel();
    panel.addHeading("Style Sheet");

    // Add a button to see the super-imposed style sheet file.
    String viewSourceIconName = "images/viewcss.gif";
    Icon viewSourceIcon = null;
    try {
      Image image = IlvImageUtil.getImageFromFile(ScheduleCSSExample.class, viewSourceIconName);
      viewSourceIcon = new ImageIcon(image);
    } catch (Exception e) {
      System.err.println("Warning: error during read for image " + viewSourceIconName);
    }
    final JToggleButton button = new JToggleButton("View source", viewSourceIcon);

    button.addActionListener(new ActionListener() {
      Override
      public void actionPerformed(ActionEvent evt) {
        showCSS();
      }
    });
    button.setToolTipText("Show or Hide the Selected Style Sheet source");

    panel.add(button);
    panel.addSeparator(3);

    // Create a JComboBox containing all the available .css files.
    CSSComboBox cssCombo = new CSSComboBox(this, getChart(), DATA_DIRECTORY, CSS_FILES);

    panel.add(cssCombo);

    return panel;
  }

  /**
   * This method is overridden to disable the view customizer for this demo.
   *
   * @return <code>null</code> to disable the view customizer.
   */
  Override
  protected JComponent createViewCustomizer() {
    return null;
  }

  /**
   * Shows or hides the CSS viewer.
   */
  private void showCSS() {
    scpane.setVisible(!scpane.isVisible());
  }

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

  /**
   * Creates and returns the Gantt data model.
   *
   * @return The Gantt data model.
   */
  Override
  protected IlvGanttModel createGanttModel() {
    URL url;
    try {
      url = getResourceURL(DATA_DIRECTORY + File.separator + DEFAULT_DATA_FILE);
    } catch (IOException ex) {
      IlvSwingUtil.showErrorDialog(this, ex);
      return null;
    }
    return XMLGanttActions.readXMLURL(url, this);
  }

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

  /**
   * Initializes the example's user interface 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);
    // We want the chart to be in a JLayeredPane to be able to add the
    // superimposed editor.
    container.remove(chart);

    JLayeredPane layeredPane = new JLayeredPane();
    layeredPane.add(chart, JLayeredPane.DEFAULT_LAYER);
    layeredPane.setPreferredSize(chart.getPreferredSize());

    // Creates the CSS viewer, a JEditorPane subclass with transparency.
    editor = new CSSViewerPane(chart);
    scpane = new JScrollPane(editor);
    scpane.getViewport().setOpaque(false);
    scpane.setOpaque(false);
    layeredPane.addComponentListener(new ComponentAdapter() {
      Override
      public void componentResized(ComponentEvent evt) {
        scpane.setSize(evt.getComponent().getSize());
        scpane.revalidate();
        chart.setSize(evt.getComponent().getSize());
        chart.revalidate();
      }
    });
    layeredPane.add(scpane, JLayeredPane.PALETTE_LAYER);
    scpane.setVisible(false);

    container.add(layeredPane);
  }

  /**
   * Creates the menu bar.
   *
   * @return The menu bar.
   */
  Override
  public JMenuBar createMenuBar() {
    JMenuBar menubar = new JMenuBar();
    setHelpID(menubar, "Menu.helpID");
    JMenu menu;

    menu = createEditMenu();
    if (menu != null) {
      menubar.add(menu);
    }
    menu = createRowMenu();
    if (menu != null) {
      menubar.add(menu);
    }
    menu = createLAFMenu();
    if (menu != null) {
      menubar.add(menu);
    }
    menu = createHelpMenu();
    if (menu != null) {
      menubar.add(menu);
    }
    // Remove the Exit menu item from the Edit menu.
    if (isExitAllowed()) {
      // Remove the Exit menu item.
      JMenu edit = menubar.getMenu(0);
      edit.remove(edit.getItemCount() - 1);
      edit.remove(edit.getItemCount() - 1);
    }

    // Add the File menu.
    menubar.add(createFileMenu(), 0);

    return menubar;
  }

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

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