/*
 * BILinking.java
 *
 * Copyright © 1994-2004, Oracle. All rights reserved. Oracle grants
 * you ("Licensee") a non-exclusive, royalty-free, worldwide license to use,
 * modify and redistribute this software in source and binary code form, provided
 * that (i) this copyright notice and license appear on all copies of the
 * software; (ii) Licensee does not utilize the software in a manner disparaging
 * to Oracle; and (iii) Licensee does not utilize the software in a manner that
 * violates the terms of any Licensee agreement with Oracle.
 */
package samples.javaclient;

import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.KeyEvent;

import java.util.Vector;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;

import oracle.dss.crosstab.Crosstab;

import oracle.dss.dataSource.common.Query;
import oracle.dss.dataSource.common.QueryException;
import oracle.dss.dataSource.client.QueryManager;

import oracle.dss.dataView.Dataview;

import oracle.dss.metadataManager.client.MetadataManager;
import oracle.dss.metadataManager.common.MDMeasure;
import oracle.dss.metadataManager.common.MDObject;
import oracle.dss.metadataManager.common.MetadataManagerException;
import oracle.dss.metadataManager.common.MM;

import oracle.dss.metadataUtil.PropertyBag;

import oracle.dss.selection.SelectionException;
import oracle.dss.selection.step.InvalidStepArgException;

import oracle.dss.graph.Graph;

import oracle.dss.table.Table;

/**
 * This sample is designed to show how various views such as crosstabs, tables
 * and graphs can be linked.
 * <P>
 * The BILinking class extends BIFrame.  In addition to the connection dialog
 * provided by BIFrame, BILinking provides UI options that allow different views
 * to be linked in various ways.  This includes the ability to :
 * <ol>
 * <li> specify various combinations of crosstab, table and graph </li>
 * <li> specify a Bi-Directional or Master/Detail relationship between
 *      views</li>
 * <li> specify whether all dimensions (query) or specified dimensions
 *      (selections) are linked </li>
 * </ol>
 *
 * @see BIFrame
 */

public class BILinking extends JFrame {

  /////////////////////
  //
  // Constants
  //
  /////////////////////

  // Default width and height of frame
  private static int FRAME_WIDTH  = 800;
  private static int FRAME_HEIGHT = 600;

  /////////////////////
  //
  // Member Variables
  //
  /////////////////////

  // Menu items
  private JMenu m_sampleMenu;
  private JMenuItem m_crosstabTableMenu;
  private JMenuItem m_crosstabGraphMenu;
  private JMenuItem m_graphTableMenu;
  private JMenuItem m_crosstabTableGraphMenu;
  private JMenuItem m_toggleSelectionMenu;

  // LinkedViewPanel used to display various combinations of views
  private BILinkedViewPanel m_linkViewPanel = null;

  // Default query
  private Query m_query = null;

  // This frame
  private BIFrame m_frame;
  private JPanel m_panel;

  /////////////////////
  //
  // Constructors
  //
  /////////////////////

  /**
   * Constructor for BILinking.
   *
   * @param title The title of the JFrame.
   */
  public BILinking(BIFrame parentFrame, String title) {
    super(title);
    m_frame = parentFrame;
    init();
  }

  /////////////////////
  //
  // Protected Methods
  //
  /////////////////////

  /**
   * Initialize the user interface.
   */
  protected void init() {
    try {
  
      JMenuBar menuBar = new JMenuBar();

      // Add the view menu options
      addViewMenu(menuBar);
            
      m_panel = new JPanel();
      m_panel.setLayout(new BorderLayout());
    
      // put all of these into the frame
      setJMenuBar(menuBar);
      getContentPane().removeAll();
      getContentPane().add(m_panel, BorderLayout.CENTER);
  
      // add a listener to listen for the window closing event
      addWindowListener(new WindowAdapter() {
         public void windowClosing(WindowEvent e) {
          cleanUp();
        }
      });
      
      // Create a crosstab-graph on startup
      createLinkedView(this, m_frame.getDefaultQuery(),
          BILinkedViewPanel.CROSSTAB_GRAPH);

    }

    catch (Exception exception) {
      m_frame.showExceptionDialog(this, exception);
    }
  }


  /**
   * This method cleans up before returning to the main menu
   */
  protected void cleanUp() {
    
    // Free resources associated with the menu items
    
    m_crosstabTableMenu = null;
    m_crosstabGraphMenu = null;
    m_graphTableMenu = null;
    m_crosstabTableGraphMenu = null;
    
    // Free resources associated with any previously linked panel
    
    if (m_linkViewPanel != null) {
      // Remove the panel
      m_panel.remove(m_linkViewPanel);
      m_panel.invalidate();
      m_panel.validate();
      m_panel.repaint();

      // Free any panel resources
      m_linkViewPanel.free();
      m_linkViewPanel = null;
    }

    // Release default query
    if (m_query != null) {
      m_query.close();
      m_query = null;
    }
    dispose();
    }

  /**
   * Creates linked views based on the <code>Query</code> and linked view type.
   *
   * @param frameParent   The Frame that the panel is inserted into.
   * @param query         The Query associated with the linked view.
   * @param nLinkedView   The views to display and link.  Use the constants
   *                      <code>LinkedViewPanel.CROSSTAB_TABLE</code>,
   *                      <code>LinkedViewPanel.CROSSTAB_GRAPH </code>,
   *                      <code>LinkedViewPanel.GRAPH_TABLE</code>,
   *                      <code>LinkedViewPanel.CROSSTAB_TABLE_GRAPH</code>.
   *
   * @see bibeans.javaclient.linkingPresentations#CROSSTAB_TABLE
   * @see bibeans.javaclient.linkingPresentations#CROSSTAB_GRAPH
   * @see bibeans.javaclient.linkingPresentations#GRAPH_TABLE
   * @see bibeans.javaclient.linkingPresentations#COLUMN_EDGE
   * @see bibeans.javaclient.linkingPresentations#CROSSTAB_TABLE_GRAPH
   */
  protected void createLinkedView(Frame frameParent, Query query,
    int nLinkedViews) {

    // Free resources associated with any previously linked panel
    if (m_linkViewPanel != null) {
      m_panel.remove(m_linkViewPanel);
      m_linkViewPanel.free();
      m_linkViewPanel = null;
    }

    try {
      // Create a new LinkedViewPanel
      m_linkViewPanel = new BILinkedViewPanel(frameParent, query, nLinkedViews);
    }

    catch (Exception exception) {
      m_frame.showExceptionDialog(this, exception);
    }

    // Initialize the new LinkedViewPanel
    m_linkViewPanel.setVisible(true);
    m_linkViewPanel.revalidate();
    m_panel.add(m_linkViewPanel, BorderLayout.CENTER);
    m_panel.revalidate();
  }
  /**
   * Retrieves the current frame.
   *
   * @return <code>Frame</code> which represents the current frame.
   */
  protected Frame getFrame() {
    return this;
  }

  /////////////////////
  //
  // Private Methods
  //
  /////////////////////

  /**
   * Adds the view menu to the specified <code>JMenuBar</code>.
   *
   * @param menuBar       Menu bar to attach view menu to.
   *
   * @throws Exception
   */
  private void addViewMenu(JMenuBar menuBar) throws Exception {
    // View menu
    m_sampleMenu = new JMenu("Linking presentations");
    m_sampleMenu.setMnemonic(KeyEvent.VK_V);
    menuBar.add(m_sampleMenu);

    // Crosstab-Table views
    m_crosstabTableMenu = new JMenuItem("Crosstab-Table");
    m_crosstabTableMenu.setMnemonic(KeyEvent.VK_C);

    // Crosstab-Graph views
    m_crosstabGraphMenu = new JMenuItem("Crosstab-Graph");
    m_crosstabGraphMenu.setMnemonic(KeyEvent.VK_G);

    // Graph-Table views
    m_graphTableMenu = new JMenuItem("Graph-Table");
    m_graphTableMenu.setMnemonic(KeyEvent.VK_T);

    // Crosstab-Table-Graph views
    m_crosstabTableGraphMenu = new JMenuItem("Crosstab-Table-Graph");
    m_crosstabTableGraphMenu.setMnemonic(KeyEvent.VK_R);

    // Toggle Selections
    m_toggleSelectionMenu = new JMenuItem("Toggle Selection");
    m_toggleSelectionMenu.setMnemonic(KeyEvent.VK_S);

    // Add each menu item to menu.
    m_sampleMenu.add(m_crosstabTableMenu);
    m_sampleMenu.add(m_crosstabGraphMenu);
    m_sampleMenu.add(m_graphTableMenu);
    m_sampleMenu.add(m_crosstabTableGraphMenu);
    m_sampleMenu.insertSeparator(4);
    m_sampleMenu.add(m_toggleSelectionMenu);

    // Add Listener to m_crosstabTableMenu
    m_crosstabTableMenu.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent event) {
        createLinkedView(getFrame(), m_frame.getDefaultQuery(),
          BILinkedViewPanel.CROSSTAB_TABLE);

        // Enable ability to toggle selection
        if (m_toggleSelectionMenu != null) {
          m_toggleSelectionMenu.setEnabled(true);
        }
      }
    });

    // Add Listener to m_crosstabGraphMenu
    m_crosstabGraphMenu.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent event) {
        createLinkedView(getFrame(), m_frame.getDefaultQuery(),
          BILinkedViewPanel.CROSSTAB_GRAPH);

        // Enable ability to toggle selection
        if (m_toggleSelectionMenu != null) {
          m_toggleSelectionMenu.setEnabled(true);
        }
      }
    });

    // Add Listener to m_graphTableMenu
    m_graphTableMenu.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent event) {
        createLinkedView(getFrame(), m_frame.getDefaultQuery(),
          BILinkedViewPanel.GRAPH_TABLE);

        // Enable ability to toggle selection
        if (m_toggleSelectionMenu != null) {
          m_toggleSelectionMenu.setEnabled(true);
        }
      }
    });

    // Add Listener to m_crosstabTableGraphMenu
    m_crosstabTableGraphMenu.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent event) {
        createLinkedView(getFrame(), m_frame.getDefaultQuery(),
          BILinkedViewPanel.CROSSTAB_TABLE_GRAPH);

        // Enable ability to toggle selection
        if (m_toggleSelectionMenu != null) {
          m_toggleSelectionMenu.setEnabled(true);
        }
      }
    });

    // Add Listener to m_toggleSelectionMenu
    m_toggleSelectionMenu.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent event) {
        try { 
          // Verify that we have some linked panels        
          if (m_linkViewPanel != null) {

            // Retrieve the Master Dataview
            Dataview dataviewMaster = m_linkViewPanel.getDataviewMaster();

            // Attempt to update the selection on all linked views
            m_linkViewPanel.updateSelection(dataviewMaster);
          }
        } 
        
        catch (Exception exception) {    
          m_frame.showExceptionDialog(getFrame(), exception);
        }
      }
    });

  }
}
