//----------------------------------------------------------------------------
// COMPONENT NAME: LPEX Editor
//
// © Copyright IBM Corporation 2003, 2007
// All Rights Reserved.
//
// DESCRIPTION:
// CopyLineAction - sample user-defined action (copyLine)
//----------------------------------------------------------------------------

package com.ibm.lpex.samples;

import com.ibm.lpex.core.LpexAction;
import com.ibm.lpex.core.LpexView;

/**
 * Sample action <b>copyLine</b> - copy selection / current line to clipboard.
 * This action is similar to the <b>copy</b> default editor action, but it
 * will copy the current element to the clipboard if there is no selection
 * in the current view.
 *
 * <p>Here is the CopyLineAction
 * <a href="doc-files/CopyLineAction.java.html">source code</a>.</p>
 *
 * <p>To run this sample:
 * <ul>
 *  <li>Define this user action via an editor preference page, where available,
 *   or from the editor command line:
 *   <pre>set actionClass.copyLine com.ibm.lpex.samples.CopyLineAction</pre>
 *  <li>Run it from the editor command line:
 *   <pre>action copyLine</pre>
 *   or associate it with a key (here, <b>Ctrl+C</b> in the text and prefix areas):
 *   <pre>set keyAction.c-c.t.p copyLine</pre>
 * </ul></p>
 *
 * @see com.ibm.lpex.samples All the samples
 */
public class CopyLineAction implements LpexAction
{
 /**
  * Runs the action.
  * Copies selection / current line to the clipboard.
  */
 public void doAction(LpexView lpexView)
 {
  // if there is a selection, in this view, do the default "copy" action
  if (lpexView.queryOn("block.inView"))
   {
    lpexView.doAction(lpexView.actionId("copy"));
    return;
   }

  // first save any selection in another (view of the) document
  PreserveBlock oldSelection = new PreserveBlock(lpexView);
  // select the current element
  lpexView.doCommand("block set element");
  // do a regular clipboard copy
  lpexView.doAction(lpexView.actionId("copy"));
  // clear this selection
  lpexView.doCommand("block clear");
  // restore any original selection in another (view of the) document
  oldSelection.restore();
 }

 /**
  * Returns the availability of this action.  This action can
  * run whenever there are visible elements in the view.
  */
 public boolean available(LpexView lpexView)
 {
  return lpexView.currentElement() != 0;
 }
}


/**
 * Preserves information of any existing block,
 * in order to restore it shortly afterwards.
 */
final class PreserveBlock
{
 LpexView blockView;
 String blockType;
 String forceAllVisible;
 String cursorRow;
 int blockTopElement, blockTopPosition;
 int blockBottomElement, blockBottomPosition;

 /**
  * Constructor to save the current block, if any.
  */
 PreserveBlock(LpexView lpexView)
 {
  blockView = lpexView.getBlockView();
  if (blockView != null)
   {
    // ensure all elements are visible for the jumps and set blocks in restore
    cursorRow = blockView.query("cursorRow");
    forceAllVisible = blockView.query("forceAllVisible");
    blockView.doCommand("set forceAllVisible on");

    blockType = blockView.query("block.type");
    blockTopElement = blockView.queryInt("block.topElement");
    blockBottomElement = blockView.queryInt("block.bottomElement");
    blockTopPosition = blockView.queryInt("block.topPosition");
    blockBottomPosition = blockView.queryInt("block.bottomPosition");
   }
 }

 /**
  * Restores the saved block, if any.
  */
 void restore()
 {
  if (blockView != null)
   {
    int currentElement = blockView.currentElement();
    int currentPosition = blockView.currentPosition();
    // set in the right order, in case it's a stream block
    if (currentElement == blockTopElement && currentPosition == blockTopPosition)
     {
      blockView.jump(blockBottomElement, blockBottomPosition);
      blockView.doCommand("block set " + blockType);
      blockView.jump(blockTopElement, blockTopPosition);
      blockView.doCommand("block set");
     }
    else
     {
      blockView.jump(blockTopElement, blockTopPosition);
      blockView.doCommand("block set " + blockType);
      blockView.jump(blockBottomElement, blockBottomPosition);
      blockView.doCommand("block set");
      // may have to restore blockView's cursor position
      if (currentElement != blockBottomElement ||
          currentPosition != blockBottomPosition)
       {
        blockView.jump(currentElement, currentPosition);
       }
     }

    blockView.doCommand("set forceAllVisible " + forceAllVisible);
    blockView.doCommand("set cursorRow " + cursorRow);

    // 'dispose'
    blockView = null;
   }
 }
}