//----------------------------------------------------------------------------
// COMPONENT NAME: LPEX Editor
//
// © Copyright IBM Corporation 2002, 2008
// All Rights Reserved.
//
// DESCRIPTION:
// Lpex2 - sample/test class for the SWT LPEX widget: split view
//----------------------------------------------------------------------------

package com.ibm.lpex.samples;

import java.io.File;

import com.ibm.lpex.core.LpexCommand;
import com.ibm.lpex.core.LpexMessageConstants;
import com.ibm.lpex.core.LpexMultiWindow;
import com.ibm.lpex.core.LpexResources;
import com.ibm.lpex.core.LpexStringTokenizer;
import com.ibm.lpex.core.LpexView;
import com.ibm.lpex.core.LpexViewAdapter;

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


/**
 * Sample stand-alone editor built on the LPEX edit widget.
 * Displays a split view of the document.
 *
 * <p>Here is the Lpex2 <a href="doc-files/Lpex2.java.html">source code</a>.</p>
 *
 * <p>To run this sample from the command line:
 * <pre>
 *   java [<i>options</i>] com.ibm.lpex.samples.Lpex2 [<i>filename</i>]
 *        [-encoding <i>encoding</i>] </pre>
 * A possible Windows batch program is:
 * <pre>
 *   &#64;start /b java com.ibm.lpex.samples.Lpex2 %1 %2 %3 %4 %5 </pre>
 * To disable the JIT compiler, run it with this option:
 * <pre>
 *   -Djava.compiler= </pre>
 * You can run Lpex in a particular locale.  For example, in order to run it in
 * Simplified Chinese (zh_CN), use these two options:
 * <pre>
 *   -Duser.language=zh -Duser.region=CN </pre></p>
 *
 * Commands defined in here:
 * <ul>
 *  <li><b>hor</b> command - change split orientation to horizontal
 *  <li><b>ver</b> command - change split orientation to vertical.
 * </ul>
 *
 * <p>Example of running Lpex2 via a user-defined editor command:</p>
 * <table bgcolor="#f0f0f0"><tr><td><pre>&nbsp;
 * lpexView.defineCommand(<font color="#800080">"Lpex2"</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.Lpex2"</font>);
 *       Method mainMethod = cl.getDeclaredMethod(<font color="#800080">"main"</font>, <font color="#0000ff"><b>new</b></font> Class[] {String[].class});&nbsp;
 *       String[] args = LpexStringTokenizer.split(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 All the samples
 */
public final class Lpex2
{
 private Shell _shell;
 private LpexMultiWindow _lpexMultiWindow;

 /**
  * Entry point.
  */
 public static void main(String[] args)
 {
  new Lpex2(args).run().close();
 }

 /**
  * Constructor.
  * @param parms file name and parameters
  */
 private Lpex2(String[] parms)
 {
  String filename = null;
  String encoding = ""; // default to autodetect file's encoding

  // extract file name and parameters
  int i = 0;
  if (i < parms.length && !parms[i].startsWith("-") && !parms[i].startsWith("/"))
   {
    filename = LpexStringTokenizer.trimQuotes(parms[i++]);
   }

  while (i < parms.length-1 && (parms[i].startsWith("-") || parms[i].startsWith("/")))
   {
    String parm = parms[i++].substring(1);
    if ("encoding".equals(parm) || "enc".equals(parm))
     {
      encoding = parms[i++];
     }
    else
     {
      break;
     }
   }

  // 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 a new Shell, have the LpexMultiWindow fill it (so we don't
  // have to listen to & handle shell SWT.Resize events)
  _shell = new Shell();
  _shell.setLayout(new FillLayout());

  // listen to the closing of the Shell
  _shell.addListener(SWT.Close, new Listener() {
   public void handleEvent(Event event) { closeShell(event); }
   });

  // create LpexViews for the given file name, do explicit "updateProfile"s later
  LpexView lpexView0, lpexView1 = null;
  lpexView0 = new LpexView(filename, encoding, false); // new document
  try
   {
    lpexView1 = new LpexView(lpexView0, false);        // 2nd view on same document
   }
  catch (LpexView.ViewInstantiationException e) {}

  // create & set windows for our LpexViews
  _lpexMultiWindow = new LpexMultiWindow(_shell, 0);
  _lpexMultiWindow.newWindow(lpexView0, SWT.BORDER);
  _lpexMultiWindow.newWindow(lpexView1, SWT.BORDER | SWT.CLOSE);

  // set Shell title
  _shell.setText("Lpex2 - " + documentName());

  // listen to the views
  LpexViewAdapter lpexViewAdapter = new LpexViewAdapter() {
   // called after an "updateProfile" command was run
   public void updateProfile(LpexView lpexView)
   { Lpex2.this.updateProfile(lpexView); }
   };
  lpexView0.addLpexViewListener(lpexViewAdapter);
  lpexView1.addLpexViewListener(lpexViewAdapter);

  // run the "updateProfile" command on each view
  lpexView0.doCommand("set updateProfile.palette gray"); // break symmetry
  lpexView0.doCommand("updateProfile");
  lpexView1.doCommand("updateProfile");

  // set Shell's position & size, open it
  Rectangle bounds = new Rectangle(10, 10, 1000, 711);
  _shell.setBounds(bounds);
  _shell.open();
 }

 private String documentName()
 {
  LpexView lpexView = _lpexMultiWindow.getFirstWindow().getLpexView();
  String name = lpexView.query("name");
  return (name != null)? name : LpexResources.message(LpexMessageConstants.MSG_UNTITLED_DOCUMENT,
                                                      lpexView.query("documentId"));
 }

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

  return this;
 }

 /**
  * Close shop - ensure the shell is disposed.
  */
 private Lpex2 close()
 {
  if ((_shell != null) && !_shell.isDisposed())
   {
    _shell.dispose();
   }

  _shell = null;
  return this;
 }

 /*======================*/
 /*  LPEX notifications  */
 /*======================*/
 /**
  * Define editor commands, actions, and associated keys.
  * Called whenever the <b>updateProfile</b> command has been processed.
  *
  * In this example, all the views of this same document are processed in an
  * identical manner - that is, the same actions and commands are defined in
  * all these views, etc.
  */
 void updateProfile(LpexView lpexView)
 {
  // "ver" command - change split orientation to vertical
  lpexView.defineCommand("ver", new LpexCommand() {
   public boolean doCommand(LpexView view, String parameters)
   { return view.doCommand("set splitWindow.orientation vertical"); }
  });

  // "hor" command - change split orientation to horizontal
  lpexView.defineCommand("hor", new LpexCommand() {
   public boolean doCommand(LpexView view, String parameters)
   { return view.doCommand("set splitWindow.orientation horizontal"); }
  });
 }

 /*=======================*/
 /*  Shell notifications  */
 /*=======================*/
 // Shell close request.
 private void closeShell(Event event)
 {
  event.doit = closeWindow();
 }

 // Check whether this Lpex window can be safely closed (saved / user-abandoned).
 private boolean closeWindow()
 {
  boolean close = true;

  LpexView lpexView = _lpexMultiWindow.getFirstWindow().getLpexView();
  if (lpexView != null &&
      (lpexView.queryInt("changes") != 0 || lpexView.queryOn("dirty")))
   {
    MessageBox box = new MessageBox(_shell, SWT.ICON_QUESTION | SWT.YES | SWT.NO | SWT.CANCEL);
    box.setText(_shell.getText());
    box.setMessage(LpexResources.message(LpexMessageConstants.MSG_FILE_SAVE_CHANGES,
                                         documentName()));
    int rc = box.open();

    if (rc == SWT.YES)
     {
      lpexView.doCommand("save");
      if (lpexView.query("status") != null) // save failed / was cancelled
       {
        close = false;
       }
     }
    else if (rc == SWT.CANCEL)
     {
      close = false;
     }
   }

  return close;
 }
}