//----------------------------------------------------------------------------
// COMPONENT NAME: LPEX Editor
//
// © Copyright IBM Corporation 2004, 2007
// All Rights Reserved.
//
// DESCRIPTION:
// SetDateAction - sample user-defined action, command (setDate)
//----------------------------------------------------------------------------
package com.ibm.lpex.samples;
import com.ibm.lpex.core.LpexAction;
import com.ibm.lpex.core.LpexCommand;
import com.ibm.lpex.core.LpexDocumentLocation;
import com.ibm.lpex.core.LpexStringTokenizer;
import com.ibm.lpex.core.LpexView;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Sample action <b>setDate</b> - set the sequence-numbers date in the selected
* range. Use this action to modify the textual part of the sequence numbers in
* all the currently-selected visible lines. The user is prompted for the new
* text. Note that LPEX doesn't record changes to the sequence numbers in its
* undo stack.
*
* <p>Here is the SetDateAction
* <a href="doc-files/SetDateAction.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.setDate com.ibm.lpex.samples.SetDateAction</pre></li>
* <li>Run it from the editor command line:
* <pre>action setDate</pre>
* or associate it with a key (here, <b>Ctrl+T</b> in the text area):
* <pre>set keyAction.c-t setDate</pre></li>
* </ul></p>
*
* @see com.ibm.lpex.samples All the samples
*/
public class SetDateAction implements LpexAction
{
/**
* Sample command <b>setDate</b> - set the sequence-numbers date in the
* selected range. Use this command to modify the textual part of the sequence
* numbers in all the currently-selected visible lines. If you do not specify
* the new text via the command parameter, you will be prompted for it. Note
* that LPEX doesn't record changes to the sequence numbers in its undo stack.
*
* <p>This is an alternative to the <b>setDate</b> sample action, for cases in
* which the user prefers the command approach, or is running out of available
* keys to assign to actions.</p>
*
* <p>Defined as a separate, named class inside {@link SetDateAction} (where
* you can also see its <a href="doc-files/SetDateAction.java.html#line47">
* source code</a>), it can be registered in the editor with, for example:
* <pre> set commandClass.setDate com.ibm.lpex.samples.SetDateAction$SetDate</pre></p>
* and run from the command line:
* <pre> setDate [ <i>newDate</i> ]</pre></p>
*/
public static class SetDate implements LpexCommand
{
/**
* Runs this command.
* Uses the specified date, or otherwise prompts the user for one, and updates
* the sequence numbers of all the visible selected lines.
*
* @param lpexView the document view in which the command was issued
* @param parameters optional new date to set
*/
public boolean doCommand(LpexView lpexView, String parameters)
{
if (lpexView != null)
{
if ("?".equals(parameters.trim())) // command help
{
lpexView.doCommand("set messageText Syntax: setDate [<new date>]");
return true;
}
if (lpexView.queryOn("readonly"))
{
lpexView.doDefaultCommand("set messageText Document is read only.");
}
else if (sequenceNumbersTextLength(lpexView) == 0)
{
lpexView.doDefaultCommand("set messageText Document has no sequence-numbers text part.");
}
else if (lpexView.currentElement() == 0)
{
lpexView.doDefaultCommand("set messageText No visible elements.");
}
else
{
// (a) use the user-supplied parameter as the new date
if (parameters.length() != 0)
{
return doSetDateCommand.doCommand(lpexView, parameters);
}
// (b) no parameters: do what the SetDateAction does (prompt user, etc.)
return internalDoAction(lpexView);
}
}
return true;
}
}
/**
* Runs the action.
* Prompts the user for a new date, then updates the sequence numbers for all
* the visible selected lines.
*
* <p>Uses the <b>input</b> built-in editor command, which in turn issues the
* <b>doSetDate</b> helper command defined in here. It checks for, and if
* needed registers, an instance of the <b>doSetDate</b> command in the view.</p>
*/
public void doAction(LpexView lpexView)
{
internalDoAction(lpexView);
}
/**
* Returns the availability of this action.
* The action can be run in any visible, writable view of a document with
* sequence numbers which have a textual part.
*/
public boolean available(LpexView lpexView)
{
return canSetSequenceNumbersText(lpexView);
}
/**
* Variation of SetDateAction that can be used, for example from a user profile,
* when the <b>doSetDate</b> helper command has already been defined in the view.
* It does not check for, nor defines, the <b>doSetDate</b> command.
*/
public static LpexAction setDateAction = new LpexAction() {
public void doAction(LpexView lpexView) {
LpexView.doGlobalCommand("set status");
lpexView.doDefaultCommand(getInputCommandString(lpexView));
}
public boolean available(LpexView lpexView) {
return canSetSequenceNumbersText(lpexView);
}
};
/**
* Helper command, issued by our prompt's <b>input</b> command, to set the new
* sequence-numbers text (specified in <code>parameters</code>), in all the
* visible selected lines, or in the current line if there is no selection.
* This command must be registered in a view with the name <b>doSetDate</b>.
*/
public static LpexCommand doSetDateCommand = new LpexCommand() {
public boolean doCommand(LpexView lpexView, String parameters) {
// determine the range of elements to set
int firstElement, lastElement;
// 1.- visible selection in this view
if (lpexView.queryOn("block.inView") && lpexView.queryOn("block.anythingSelected"))
{
int linesBeforeStart = lpexView.queryInt("lines.beforeStart");
firstElement = lpexView.queryInt("block.topElement") - linesBeforeStart;
lastElement = lpexView.queryInt("block.bottomElement") - linesBeforeStart;
}
// 2.- no selected text (is visible) in this view
else
{
firstElement = lastElement = lpexView.currentElement();
}
// record whether any changes done
boolean dirty = false;
// go through all visible lines in range
LpexDocumentLocation loc = new LpexDocumentLocation(1, 1);
for (int i = firstElement; i <= lastElement; i++)
{
if (!lpexView.show(i))
{
loc.element = i;
if (lpexView.queryOn("visible", loc))
{
if (!dirty)
{
dirty = !parameters.equals(lpexView.query("sequenceText"));
}
lpexView.doCommand(loc, "set sequenceText " + parameters);
}
}
}
// some editor applications won't save a document unless it's marked dirty
if (dirty)
{
lpexView.doCommand("set dirty on");
}
return true;
}
};
// Optionally registers helper command, prompts user, sets sequence numbers.
private static boolean internalDoAction(LpexView lpexView)
{
// ensure our set-date command is defined in the view in which this action runs
if (lpexView.command("doSetDate") != doSetDateCommand)
{
lpexView.defineCommand("doSetDate", doSetDateCommand);
}
// prompt user for the new date, update visible selected lines
LpexView.doGlobalCommand("set status");
return lpexView.doDefaultCommand(getInputCommandString(lpexView));
}
// Returns the input command to use for prompting and setting the date (see
// the "input" editor command), e.g., input "New date:" "040630" "doSetDate ".
private static String getInputCommandString(LpexView lpexView)
{
int sequenceNumbersTextLength = sequenceNumbersTextLength(lpexView);
// prompt - specify YYMMDD if the sequence numbers are iSeries style
String prompt = (sequenceNumbersTextLength == 6)? "New date (YYMMDD):" : "New date:";
prompt = LpexStringTokenizer.addQuotes(prompt);
// prompt initialization - default text if set / today's date if room for it / 0s
String initialText = lpexView.query("current.sequenceDefaultText");
if (initialText == null || initialText.trim().length() == 0)
{
// iSeries style - use today's date, in YYMMDD format
if (sequenceNumbersTextLength == 6)
{
initialText = new SimpleDateFormat("yyMMdd").format(new Date());
}
// otherwise - initialize to 0s
else
{
initialText = "0";
while (initialText.length() < sequenceNumbersTextLength)
{
initialText += '0';
}
}
}
initialText = LpexStringTokenizer.addQuotes(initialText);
// build the entire "input" command
return "input " + prompt + ' ' + initialText + " \"doSetDate \"";
}
// Checks whether we can set sequence-numbers text in the given view:
// this should be the writable, visible view of a document with sequence
// numbers which have a textual part.
private static boolean canSetSequenceNumbersText(LpexView lpexView)
{
return lpexView.currentElement() != 0 && !lpexView.queryOn("readonly") &&
sequenceNumbersTextLength(lpexView) != 0;
}
// Returns the length of the document's sequence-numbers text part.
private static int sequenceNumbersTextLength(LpexView lpexView)
{
return Integer.parseInt(lpexView.query("current.sequenceNumbers").split(" ")[3]);
}
}