products/sources/formale Sprachen/Isabelle/Tools/jEdit/dist/doc/users-guide image not shown  

Quellcode-Bibliothek

© Kompilation durch diese Firma

[Weder Korrektheit noch Funktionsfähigkeit der Software werden zugesichert.]

Datei: macro-analysis.html   Sprache: HTML

Original von: Isabelle©

 products/sources/formale Sprachen/Isabelle/Tools/jEdit/dist/doc/users-guide/macro-analysis.html


<html><head>
      <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
   <title>Analysis of the Macro</title><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><link rel="home" href="index.html" title="jEdit 5.6 User's Guide"><link rel="up" href="dialog-macro.html" title="Chapter 14. A Dialog-Based Macro"><link rel="prev" href="add-prefix-and-suffix.html" title="Listing of the Macro"><link rel="next" href="macro-tips.html" title="Chapter 15. Macro Tips and Techniques"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Analysis of the Macro</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="add-prefix-and-suffix.html">Prev</a> </td><th width="60%" align="center">Chapter 14. A Dialog-Based Macro</th><td width="20%" align="right"> <a accesskey="n" href="macro-tips.html">Next</a></td></tr></table><hr></div><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="macro-analysis"></a>Analysis of the Macro</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="explain-imports"></a>Import Statements</h3></div></div></div><div class="informalexample"><pre class="programlisting">// import statement
import javax.swing.border.*;</pre></div><p>This macro makes use of classes in the
            <code class="literal">javax.swing.border</code> package, which is not
            automatically imported. As we mentioned previously (see <a class="xref" href="first-example.html" title="The Mandatory First Example">the section called “The Mandatory First Example”</a>), jEdit's implementation of BeanShell
            causes a number of classes to be automatically imported. Classes
            that are not automatically imported must be identified by a full
            qualified name or be the subject of an <code class="function">import</code>
            statement.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="explain-create-dialog"></a>Create the Dialog</h3></div></div></div><div class="informalexample"><pre class="programlisting">// create dialog object
title = <span class="quote">“<span class="quote">Add prefix and suffix to selected lines</span>”</span>;
dialog = new JDialog(view, title, false);
content = new JPanel(new BorderLayout());
content.setBorder(new EmptyBorder(12, 12, 12, 12));
dialog.setContentPane(content);</pre></div><p>To get input for the macro, we need a dialog that provides for
            input of the prefix and suffix strings, an <span class="guibutton"><strong>OK</strong></span>
            button to perform text insertion, and a
            <span class="guibutton"><strong>Cancel</strong></spanbutton in case we change our mind. We
            have decided to make the dialog window non-modal. This will allow us
            to move around in the text buffer to find things we may need
            (including text to cut and paste) while the macro is running and the
            dialog is visible.</p><p>The Java object we need is a <code class="classname">JDialog</code>
            object from the Swing package. To construct one, we use the
            <code class="function">new</code> keyword and call a
            <em class="glossterm">constructor</em> function. The constructor we use
            takes three parameters: the owner of the new dialog, the title to be
            displayed in the dialog frame, and a <code class="classname">boolean</code>
            parameter (<code class="constant">true</code> or <code class="constant">false</code>)
            that specifies whether the dialog will be modal or non-modal. We
            define the variable <code class="varname">title</code> using a string literal,
            then use it immediately in the <code class="classname">JDialog</code>
            constructor.</p><p>A <code class="classname">JDialog</codeobject is a window containing
            a single object called a <em class="glossterm">content pane</em>. The
            content pane in turn contains the various visible components of the
            dialog. A <code class="classname">JDialog</code> creates an empty content
            pane for itself as during its construction. However, to control the
            dialog's appearance as much as possible, we will separately create
            our own content pane and attach it to the
            <code class="classname">JDialog</code>. We do this by creating a
            <code class="classname">JPanel</codeobject. A
            <code class="classname">JPanel</code> is a lightweight container for other
            components that can be set to a given size and color. It also
            contains a <em class="glossterm">layout</em> scheme for arranging the
            size and position of its components. Here we are constructing a
            <code class="classname">JPanel</code> as a content pane with a
            <code class="classname">BorderLayout</code>. We put a
            <code class="classname">EmptyBorder</code> inside it to serve as a margin
            between the edge of the window and the components inside. We then
            attach the <code class="classname">JPanel</code> as the dialog's content
            pane, replacing the dialog's home-grown version.

A BorderLayout is one of the simpler
            layout schemes available for container objects like
            <code class="classname">JPanel</code>. A <code class="classname">BorderLayout</code>
            divides the container into five sections: <span class="quote">“<span class="quote">North</span>”</span>,
            <span class="quote">“<span class="quote">South</span>”</span>, <span class="quote">“<span class="quote">East</span>”</span>, <span class="quote">“<span class="quote">West</span>”</span> and
            <span class="quote">“<span class="quote">Center</span>”</span>. Components are added to the layout using the
            container's add method, specifying the
            component to be added and the section to which it is assigned.
            Building a component like our dialog window involves building a set
            of nested containers and specifying the location of each of their
            member components. We have taken the first step by creating a
            <code class="classname">JPanel</code> as the dialog's content pane.

Create the Text Fields

// add the text fields
fieldPanel = new JPanel(new GridLayout(4, 1, 0, 6));
prefixField = new HistoryTextField("macro.add-prefix");
prefixLabel = new JLabel(<span class="quote">“<span class="quote">Prefix to add</span>”</span>:);
suffixField = new HistoryTextField(<span class="quote">“<span class="quote">macro.add-suffix</span>”</span>);
suffixLabel = new JLabel(<span class="quote">“<span class="quote">Suffix to add:</span>”</span>);
fieldPanel.add(prefixLabel);
fieldPanel.add(prefixField);
fieldPanel.add(suffixLabel);
fieldPanel.add(suffixField);
content.add(fieldPanel, <span class="quote">“<span class="quote">Center</span>”</span>);</pre></div><p>Next we shall create a smaller panel containing two fields for
            entering the prefix and suffix text and two labels identifying the
            input fields.</p><p>For the text fields, we will use jEdit's HistoryTextField
            class. It is derived from the Java Swing class
            <code class="classname">JTextField</code>. This class offers the enhancement
            of a stored list of prior values used as text input. When the
            component has input focus, the up and down keys scroll through the
            prior values for the variable. </p><p>To create the <a class="ulink" href="../api/org/gjt/sp/jedit/gui/HistoryTextField.html" target="_top">HistoryTextField</a>
            objects we use a constructor method that takes a single parameter:
            the name of the tag under which history values will be stored. Here
            we choose names that are not likely to conflict with existing jEdit
            history items.</p><p>The labels that accompany the text fields are
            <code class="classname">JLabel</code> objects from the Java Swing package.
            The constructor we use for both labels takes the label text as a
            single <code class="classname">String</code> parameter.</p><p>We wish to arrange these four components from top to bottom,
            one after the other. To achieve that, we use a
            <code class="classname">JPanel</code> container object named
            <code class="varname">fieldPanel</code> that will be nested inside the
            dialog's content pane that we have already created. In the
            constructor for <code class="varname">fieldPanel</code>, we assign a new
            <code class="classname">GridLayout</code> with the indicated parameters:
            four rows, one column, zero spacing between columns (a meaningless
            element of a grid with only one column, but nevertheless a required
            parameter) and spacing of six pixels between rows. The spacing
            between rows spreads out the four <span class="quote">“<span class="quote">grid</span>”</span> elements.
            After the components, the panel and the layout are specified, the
            components are added to <code class="varname">fieldPanel</code> top to bottom,
            one <span class="quote">“<span class="quote">grid cell</span>”</span> at a time. Finally, the complete
            <code class="varname">fieldPanel</code> is added to the dialog's content pane
            to occupy the <span class="quote">“<span class="quote">Center</span>”</spansection of the content
            pane.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="explain-button-panel"></a>Create the Buttons</h3></div></div></div><div class="informalexample"><pre class="programlisting">// add the buttons
buttonPanel = new JPanel();
buttonPanel.setLayout(new BoxLayout(buttonPanel,
    BoxLayout.X_AXIS));
buttonPanel.setBorder(new EmptyBorder(12, 50, 0, 50));
buttonPanel.add(Box.createGlue());
ok = new JButton(<span class="quote">“<span class="quote">OK</span>”</span>);
cancel = new JButton(<span class="quote">“<span class="quote">Cancel</span>”</span>);
ok.setPreferredSize(cancel.getPreferredSize());
dialog.getRootPane().setDefaultButton(ok);
buttonPanel.add(ok);
buttonPanel.add(Box.createHorizontalStrut(6));
buttonPanel.add(cancel);
buttonPanel.add(Box.createGlue());
content.add(buttonPanel, <span class="quote">“<span class="quote">South</span>”</span>);</pre></div><p>To create the dialog's buttons, we follow repeat the
            <span class="quote">“<span class="quote">nested container</span>”</span> pattern we used in creating the text
            fields. First, we create a new, nested panel. This time we use a
            <code class="classname">BoxLayout</code> that places components either in a
            single row or column, depending on the parameter passed to its
            constructor. This layout object is more flexible than a
            <code class="classname">GridLayout</code> in that variable spacing between
            elements can be specified easily. We put an
            <code class="classname">EmptyBorder</code> in the new panel to set margins
            for placing the buttons. Then we create the buttons, using a
            <code class="classname">JButton</code> constructor that specifies the button
            text. After setting the size of the <span class="guilabel"><strong>OK</strong></spanbutton
            to equal the size of the <span class="guilabel"><strong>Cancel</strong></spanbutton, we
            designate the <span class="guilabel"><strong>OK</strong></spanbutton as the default button
            in the dialog. This causes the <span class="guilabel"><strong>OK</strong></spanbutton to be
            outlined when the dialog if first displayed. Finally, we place the
            buttons side by side with a 6 pixel gap between them (for aesthetic
            reasons), and place the completed <code class="varname">buttonPanel</code> in
            the <span class="quote">“<span class="quote">South</span>”</spansection of the dialog's content
            pane.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="explain-add-listeners"></a>Register the Action Listeners</h3></div></div></div><div class="informalexample"><pre class="programlisting">// register this method as an ActionListener for
// the buttons and text fields
ok.addActionListener(this);
cancel.addActionListener(this);
prefixField.addActionListener(this);
suffixField.addActionListener(this);</pre></div><p>In order to specify the action to be taken upon clicking a
            button or pressing the <code class="keycap">Enter</code> key, we must register
            an <code class="classname">ActionListener</code> for each of the four active
            components of the dialog - the two <a class="ulink" href="../api/org/gjt/sp/jedit/HistoryTextField.html" target="_top">HistoryTextField</a>
            components and the two buttons. In Java, an
            <code class="classname">ActionListener</code> is an
            <em class="glossterm">interface</em> - an abstract specification for a
            derived class to implement. The
            <code class="classname">ActionListener</code> interface contains a single
            method to be implemented:</p><div class="funcsynopsis"><table border="0" class="funcprototype-table" summary="Function synopsis" style="cellspacing: 0; cellpadding: 0;"><tr><td><code class="funcdef">public void
                    <b class="fsfunc">actionPerformed</b>(</code></td><td>ActionEvent <var class="pdparam">e</var><code>)</code>;</td></tr></table><div class="funcprototype-spacer"> </div></div><p>BeanShell does not permit a script to create derived classes.
            However, BeanShell offers a useful substitute: a method can be used
            as a scripted object that can include nested methods implementing a
            number of Java interfaces. The method
            <code class="function">prefixSuffixDialog()</code> that we are writing can
            thus be treated as an <code class="classname">ActionListener</codeobject.
            To accomplish this, we call <code class="function">addActionListener()</code>
            on each of the four components specifying <code class="varname">this</code> as
            the <code class="classname">ActionListener</code>. We still need to
            implement the interface. We will do that shortly.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="explain-set-visible"></a>Make the Dialog Visible</h3></div></div></div><div class="informalexample"><pre class="programlisting">// locate the dialog in the center of the
// editing pane and make it visible
dialog.pack();
dialog.setLocationRelativeTo(view);
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setVisible(true);</pre></div><p>Here we do three things. First, we activate all the layout
            routines we have established by calling the
            <code class="function">pack()</code> method for the dialog as the top-level
            window. Next we center the dialog's position in the active jEdit
            <code class="varname">view</code> by calling
            <code class="function">setLocationRelativeTo()</code> on the dialog. We also
            call the <code class="function">setDefaultCloseOperation()</code> function to
            specify that the dialog box should be immediately disposed if the
            user clicks the close box. Finally, we activate the dialog by
            calling <code class="function">setVisible()</code>with the state parameter
            set to <code class="constant">true</code>.</p><p>At this point we have a decent looking dialog window that
            doesn't do anything. Without more code, it will not respond to user
            input and will not accomplish any text manipulation. The remainder
            of the script deals with these two requirements.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="explain-action-listener"></a>The Action Listener</h3></div></div></div><div class="informalexample"><pre class="programlisting">// this method will be called when a button is clicked
// or when ENTER is pressed
void actionPerformed(e)
{
    if(e.getSource() != cancel)
    {
        processText();
    }
    dialog.dispose();
}</pre></div><p>The method <code class="function">actionPerformed()</code> nested
            inside <code class="function">prefixSuffixDialog()</code> implements the
            implicit <code class="classname">ActionListener</code> interface. It looks
            at the source of the <code class="classname">ActionEvent</code>, determined
            by a call to <code class="function">getSource()</code>. What we do with this
            return value is straightforward: if the source is not the
            <span class="guibutton"><strong>Cancel</strong></spanbutton, we call the
            <code class="function">processText()</code> method to insert the prefix and
            suffix text. Then the dialog is closed by calling its
            <code class="function">dispose()</code> method.</p><p>The ability to implement interfaces like
            <code class="classname">ActionListener</code> inside a BeanShell script is
            one of the more powerful features of the BeanShell package. this
            technique is discussed in the next chapter; see <a class="xref" href="macro-tips-BeanShell.html#macro-tips-BeanShell-class" title="Implementing Classes and Interfaces">the section called “Implementing Classes and Interfaces”</a>.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="explain-process-text"></a>Get the User's Input
// this is where the work gets done to insert
// the prefix and suffix
void processText()
{
    prefix = prefixField.getText();
    suffix = suffixField.getText();
    if(prefix.length() == 0 && suffix.length() == 0)
        return;
    prefixField.addCurrentToHistory();
    suffixField.addCurrentToHistory();</pre></div><p>The method <code class="function">processText()</code> does the work of
            our macro. First we obtain the input from the two text fields with a
            call to their <code class="function">getText()</code> methods. If they are
            both empty, there is nothing to do, so the method returns. If there
            is input, any text in the field is added to that field's stored
            history list by calling <code class="function">addCurrentToHistory()</code>.
            We do not need to test the <code class="varname">prefixField</code> or
            <code class="varname">suffixField</code> controls for
            <code class="constant">null</code> or empty values because
            <code class="function">addCurrentToHistory()</code> does that
            internally.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="explain-jedit-calls"></a>Call jEdit Methods to Manipulate Text</h3></div></div></div><div class="informalexample"><pre class="programlisting">    // text manipulation begins here using calls
    // to jEdit methods
    buffer.beginCompoundEdit();
    selectedLines = textArea.getSelectedLines();
    for(i = 0; i < selectedLines.length; ++i)
    {
        offsetBOL = textArea.getLineStartOffset(
            selectedLines[i]);
        textArea.setCaretPosition(offsetBOL);
        textArea.goToStartOfWhiteSpace(false);
        textArea.goToEndOfWhiteSpace(true);
        text = textArea.getSelectedText();
        if(text == null) text = "";
        textArea.setSelectedText(prefix + text + suffix);
    }
    buffer.endCompoundEdit();
}</pre></div><p>The text manipulation routine loops through each selected line
            in the text buffer. We get the loop parameters by calling
            <code class="function">textArea.getSelectedLines()</code>, which returns an
            array consisting of the line numbers of every selected line. The
            array includes the number of the current line, whether or not it is
            selected, and the line numbers are sorted in increasing order. We
            iterate through each member of the <code class="varname">selectedLines</code>
            array, which represents the number of a selected line, and apply the
            following routine:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>Get the buffer position of the start of the line
                    (expressed as a zero-based index from the start of the
                    buffer) by calling
                    <code class="function">textArea.getLineStartOffset(selectedLines[i])</code>;</p></li><li class="listitem"><p>Move the caret to that position by calling
                    <code class="function">textArea.setCaretPosition()</code>;</p></li><li class="listitem"><p>Find the first and last non-whitespace characters on
                    the line by calling
                    <code class="function">textArea.goToStartOfWhiteSpace()</code> and
                    <code class="function">textArea.goToEndOfWhiteSpace()</code>;</p><p>The <code class="function">goTo...</code> methods in <a class="ulink" href="../api/org/gjt/sp/jedit/textarea/JEditTextArea.html" target="_top">JEditTextArea</a>
                    take a single parameter which tells jEdit whether the text
                    between the current caret position and the desired position
                    should be selected. Here, we call
                    <code class="function">textArea.goToStartOfWhiteSpace(false)</code>
                    so that no text is selected, then call
                    <code class="function">textArea.goToEndOfWhiteSpace(true)</code> so
                    that all of the text between the beginning and ending
                    whitespace is selected.</p></li><li class="listitem"><p>Retrieve the selected text by storing the return value
                    of <code class="function">textArea.getSelectedText()</code> in a new
                    variable <code class="function">text</code>.</p><p>If the line is empty,
                    <code class="function">getSelectedText()</code> will return
                    <code class="constant">null</code>. In that case, we assign an empty
                    string to <code class="varname">text</code> to avoid calling methods
                    on a null object.</p></li><li class="listitem"><p>Change the selected text to <code class="varname">prefix + text +
                    suffix</code> by calling
                    <code class="function">textArea.setSelectedText()</code>. If there is
                    no selected text (for example, if the line is empty), the
                    prefix and suffix will be inserted without any intervening
                    characters.</p></li></ul></div><div class="sidebar"><div class="titlepage"><div><div><p class="title"><b>Compound edits</b></p></div></div></div><p>Note the <code class="function">beginCompoundEdit()</code> and
                <code class="function">endCompoundEdit()</code> calls. These ensure that
                all edits performed between the two calls can be undone in one
                step. Normally, jEdit automatically wraps a macro call in these
                methods; however if the macro shows a non-modal dialog box, as
                far as jEdit is concerned the macro has finished executing by
                the time the dialog is shown, since control returns to the event
                dispatch thread.</p><p>If you do not understand this, don't worry; just keep it
                in mind if your macro needs to show a non-modal dialog box for
                some reason; Most macros won't.

The Main Routine

// this single line of code is the script's main routine
prefixSuffixDialog();</pre></div><p>The call to <code class="function">prefixSuffixDialog()</code>is the
            only line in the macro that is not inside an enclosing block.
            BeanShell treats such code as a top-level <code class="function">main</code>
            method and begins execution with it.</p><p>Our analysis of <code class="filename">Add_Prefix_and_Suffix.bsh</code>
            is now complete. In the next section, we look at other ways in which
            a macro can obtain user input, as well as other macro writing
            techniques.</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="add-prefix-and-suffix.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="dialog-macro.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="macro-tips.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Listing of the Macro </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 15. Macro Tips and Techniques</td></tr></table></div></body></html>

¤ Dauer der Verarbeitung: 0.24 Sekunden  (vorverarbeitet)  ¤





Download des
Quellennavigators
Download des
sprechenden Kalenders

in der Quellcodebibliothek suchen




Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.


Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.


Bot Zugriff