//---------------------------------------------------------------------------- // 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]); } }