//----------------------------------------------------------------------------
// COMPONENT NAME: LPEX Editor
//
// © Copyright IBM Corporation 2000, 2007
// All Rights Reserved.
//
// DESCRIPTION:
// MinLpex - sample/test class for the SWT LPEX text-edit widget
//----------------------------------------------------------------------------

package com.ibm.lpex.samples;

import java.io.File;

import com.ibm.lpex.core.LpexCommand;
import com.ibm.lpex.core.LpexView;
import com.ibm.lpex.core.LpexViewAdapter;
import com.ibm.lpex.core.LpexWindow;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;

/**
 * Sample minimal stand-alone editor used to test the LPEX edit widget.
 * Modifying this sample is an easy way to test your extensions to the LPEX widget.
 *
 * <p>Here is the MinLpex <a href="doc-files/MinLpex.java.html">source code</a>.</p>
 *
 * <p>To run this sample from the command line:
 * <pre>
 *   java [<i>Java options</i>] com.ibm.lpex.samples.MinLpex [<i>filename</i>] </pre>
 *
 * Commands and actions defined in here:
 * <ul>
 *  <li><b>e</b> command - open a new MinLpex window
 *  <li><b>quit</b> command - quit the MinLpex window.
 * </ul>
 *
 * <p>Example of opening a file with MinLpex via a user-defined editor command:</p>
 * <table bgcolor="#f0f0f0"><tr><td><pre>&nbsp;
 * lpexView.defineCommand(<font color="#800080">"MinLpex"</font>, <font color="#0000ff"><b>new</b></font> LpexCommand() {
 *  <font color="#0000ff"><b>public boolean</b></font> doCommand(LpexView view, <font color="#0000ff"><b>final</b></font> String parameters)
 *  {
 *   Display display = getDisplay();
 *   display.asyncExec(<font color="#0000ff"><b>new</b></font> Runnable() {
 *    <font color="#0000ff"><b>public void</b></font> run() {
 *     <font color="#0000ff"><b>try</b></font>
 *      {
 *       Class cl = Class.forName(<font color="#800080">"com.ibm.lpex.samples.MinLpex"</font>);
 *       Method mainMethod = cl.getDeclaredMethod(<font color="#800080">"main"</font>, <font color="#0000ff"><b>new</b></font> Class[] {String[].class});&nbsp;
 *       String[] args = <font color="#0000ff"><b>new</b></font> String[] {parameters};
 *       mainMethod.invoke(<font color="#0000ff"><b>null</b></font>, <font color="#0000ff"><b>new</b></font> Object[] {args});
 *      }
 *     <font color="#0000ff"><b>catch</b></font> (Exception e) {}
 *     }});
 *   <font color="#0000ff"><b>return true</b></font>;
 *  }
 * }); </pre></td></tr></table>
 *
 * @see com.ibm.lpex.samples.Lpex
 * @see com.ibm.lpex.samples All the samples
 */
public final class MinLpex
{
 private Shell _shell;
 private LpexWindow _lpexWindow;
 private LpexView _lpexView;

 /**
  * Entry point.
  */
 public static void main(String[] args)
 {
  new MinLpex((args.length == 0)? null : args[0], new Rectangle(10, 10, 648, 711)).run();
 }

 /**
  * Constructor.
  * @param filename file name
  * @param bounds   size and position for the window
  */
 public MinLpex(String filename, Rectangle bounds)
 {
  // ensure canonical file name
  if (filename != null)
   {
    if (filename.trim().length() == 0)
     {
      filename = null;
     }
    else
     {
      try
       {
        filename = new File(filename).getCanonicalPath();
       }
      catch(Exception e) {}
     }
   }

  // create an LpexView for the given file, do the "updateProfile" later
  _lpexView = new LpexView(filename, "" /*auto-detect encoding*/, false);

  // create a new Shell, set its title
  _shell = new Shell();
  String name = _lpexView.query("name");
  if (name == null)
   {
    name = "Untitled Document " + _lpexView.query("documentId");
   }
  _shell.setText("SWT MinLpex - " + name);

  // create & set a window for our LpexView
  _lpexWindow = new LpexWindow(_shell);
  _lpexView.setWindow(_lpexWindow);

  // add an LpexViewListener to handle all the LPEX listening needed here
  _lpexView.addLpexViewListener(new LpexViewAdapter() {
   // called after an "updateProfile" command was run
   public void updateProfile(LpexView lpexView)
   { MinLpex.this.updateProfile(lpexView); }
   // called when the LpexView is disposed
   public void disposed(LpexView lpexView)
   { _lpexView = null; }
  });

  // run the "updateProfile" command
  _lpexView.doDefaultCommand("updateProfile");

  // listen to a few Shell events
  _shell.addListener(SWT.Dispose, new Listener() {
     public void handleEvent(Event event) { disposeShell(event); }});
  _shell.addListener(SWT.Resize, new Listener() {
     public void handleEvent(Event event) { resizeShell(event); }});

  // set Shell's position & size, open it
  _shell.setBounds(bounds);
  _shell.open();

  // display view, set input focus in the edit area
  //_lpexView.doDefaultCommand("screenShow");
  //_lpexWindow.textWindow().setFocus();
 }

 private void run()
 {
  Display display = _shell.getDisplay();
  while (!_shell.isDisposed())
   {
    if (!display.readAndDispatch())
     {
      display.sleep();
     }
   }

  _shell = null;
 }

 /*======================*/
 /*  LPEX notifications  */
 /*======================*/
 // Defines editor commands, actions, and associated keys.
 // Called whenever the "updateProfile" command has been processed.
 private void updateProfile(LpexView lpexView)
 {
  // "e" command - open a MinLpex window
  lpexView.defineCommand("e", new LpexCommand() {
   public boolean doCommand(LpexView view, String parameters)
   { return newWindow(parameters); } });

  // "quit" command - quit this MinLpex window
  // (also needed by base profile vi's ":q" commands)
  lpexView.defineCommand("quit", new LpexCommand() {
   public boolean doCommand(LpexView view, String parameters)
   { view.dispose(); _shell.dispose(); return true; } });
 }

 // Creates a new MinLpex window for a file.
 private boolean newWindow(final String filename)
 {
  _shell.getDisplay().asyncExec(new Runnable() { // à la SwingUtilities#invokeLater()
   public void run()
   {
    Rectangle newBounds = _shell.getBounds();
    newBounds.x += 20;
    newBounds.y += 20;
    new MinLpex(filename, newBounds).run();
   }
  });

  return true;
 }

 /*=============================*/
 /*  Shell event notifications  */
 /*=============================*/
 // Shell being disposed.
 private void disposeShell(Event event)
 {
  // dispose of our view & its resources (document parser, etc.)
  if (_lpexView != null)
   {
    _lpexView.dispose();
   }
 }

 // Shell size was [re-]set.
 private void resizeShell(Event event)
 {
  Rectangle rect = _shell.getClientArea();
  _lpexWindow.setBounds(0, 0, rect.width, rect.height);
 }
}