>   

Maple 8 and Maplets: A New Use of Computer Algebra for Teaching Mathematics and Science

Douglas B. Meade

University of South Carolina

E-mail: meade@math.sc.edu

WWW: http://www.math.sc.edu/~meade/

with assistance from

Jason Schattman

Waterloo Maple, Inc.

E-mail: jschattman@maplesoft.com

WWW: http://www.maplesoft.com/ 

22 November 2002

>   

Overview

This workshop is designed to

There is not enough time to completely address everything in this worksheet. I will attempt to highlight the essentials. You are encouraged to let your interests guide your exploration.

Please stop me at any time to ask questions. I do not mind repeating myself or providing additional explanations. My goal is for you to learn as much about Maplets as you want -- within the time constraints.

>   

Introduction

To begin this exploration of Maplets, you should be aware that some of the new features in Maple 8 are implemented as Maplets. For example, the new interactive command in the plots package:

>    restart;

>    plots[interactive]( x*sin(x) );

>   

As seen above, a Maplet can be used to provide an intuitive graphical user interface to Maple. More generally, Maplets are Maple-based applets. Most applets found on the WWW are written in Java. Maplets are written in Maple; each Maplet element is, in turn, a Java Swing class. Two reasons to implement an applet as a Maplet and not directly in Java are

Maplets can be executed within a Maple worksheet, from the "command line" with the MapletViewer , or via the WWW with MapleNet. (MapleNet is a new product of Waterloo Maple that allows users who do not have Maple on their local machine to access Maplets via the WWW. For detailed information, please visit http://maplenet.maplesoft.com/.)

>   

Maplets Demonstration

Maplets, Worksheets, MapletViewer, and MapleNet

A Maple worksheet ( .mws  file) is the easiest format to use to develop a Maplet. The MapletViewer can be used to directly access a Maplet from the desktop, local file system, or the WWW. The only modification required to create this functionality is to save the worksheet as a file with type Maplet (file extension .maplet ).

For example, consider the simple Maplet contained in the Maple worksheet demo1.mws .

To demonstrate Maplet access via MapleNet, select one of the [maplenet] links in the list of Maplets in the next section. These Maplets were created earlier this semester for my current Calculus I course at the University of South Carolina. (Firewall and other security issues might prevent access to these Maplets via MapleNet. If so, clicking on the link to the corresponding .maplet  file should launch the Maplet in MapletViewer.)

>   

Examples for Calculus I

Prior to learning some of the fundamentals of Maplet programming, please look at some of the following Maplets. The first set of 19 Maplets were created by Waterloo Maple, Inc., and can be obtained from the MaplePrimes website. The second set of Maplets are ones that I have created for use this semester in my Calculus I course at The University of South Carolina. (Note that some of the WMI-prepared Maplets cannot be accessed via MapleNet. Each of my Maplets is MapleNet-compatible.)

Calculus I Maplets prepared by Waterloo Maple

Many of the above Maplets provide convenient interfaces to commands in the Student[Calculus1]  package (new to Maple 8). The following Maplets were implemented before I learned about the Student[Calculus1]  package. That is the reason these Maplets come from the first part of the course. Still, I like them and I believe they provide good examples of what can be done.

Calculus I Maplets prepared by Douglas Meade

>   

These Maplets demonstrate the use of a few of the features available with the Maplets module, including:

>   

>   

Resources for Maplet Programmers

This workshop has only scratched the surface of what can be done with Maplets. Maple's online help system contains extensive information about Maplets, including many examples. Two of the first places I suggest you visit are

>    ?Maplets,Index

>    ?Maplets,Roadmap

These help documents contain similar information organized in different ways. (The Maplets Style Guide  is also quite useful.)

>   

For a complete list of Maplets elements, see

>    ?Maplets,Elements

A compact listing of all options available within each element is provided at

>    ?Maplets,ElementOptions

>   

A collection of Maplet examples are provided within Maple 8. For a complete listing, see the help document

>    ?Maplets,Examples

>   

>    with( Maplets[Examples] );

>   

>    Integration();

>   

>    Integration( sin(x^3)*x^2 );

>   

Introduction to Maplet Programming

Lesson 1. A First Maplet: Calculus is Great!  

To begin, we will create a very simple Calculus is Great!  Maplet.

The Maplet  command is the basic command for creating a Maplet. By default, the first argument to the Maplet  command defines the layout of the Maplet. (Other features of a Maplet can be defined as optional arguments.)

>    use Maplets[Elements] in
 maplet1 :=
  Maplet(
   [ # col 1
    "Calculus is Great!",
    Button( "OK", Shutdown() )
   ] # end col 1
  ); # end Maplet
end use:

>    Maplets[Display]( maplet1 );

The objects introduced in this Maplet are:

  • The Maplet( ... )  command,
  • Some text ( "Calculus is Great!" )
  • A button which says "OK"  which, when clicked, shuts down the Maplet.
  • The use Maplets[Elements] in ... end use:  statement.

The Maplet , Button , and Shutdown  commands are referred to as Maplet elements .  Each element corresponds to a Java  class which is instantiated when the Maplet is displayed, and the button further instantiates a Swing   JButton  class which appears on the screen.

The object in the Maplet is a list containing the string and button.  This indicates that the two objects should be displayed in a column, one on top of the other.  Layouts will be explored in greater detail in Lesson 2.

The Shutdown  element can take a list of references, and it will return the values of those references when the Maplet terminates. But, in this first Maplet, there is no return value. (Return values are of no use when the Maplet is executed with the MapletViewer or via MapletNet.)

Technical Tip ( with  and :- )

In this workshop we are assuming that you will want to program Maplets.  It is also possible to launch Maplets from within procedures.  While executing a procedure you do not want to use the with  command as this impacts the user's environment after the procedure exits.  The use  statement behaves in many ways like a with  which is in effect only to the end of the use  statement.

>    use LinearAlgebra in
    Determinant( <<3,5>|<5,2>> );
end use;
Determinant( <<3,5>|<5,2>> );

versus

>    with( LinearAlgebra ):

>    Determinant( <<3,5>|<5,2>> );

Consider the following where a procedure calls with , which then changes the user's environment.

>    arrow := 3;

>    f := proc(x, y, z)
   with( plots );
   implicitplot( x, y = -1..1, z=-1..1, color=red, view=[-1..1, -1..1] );
end proc:

>    f( x^2 + 3*y^2 = 1, x, y );

>    arrow;

>    restart;

>   

Additional tips on how to make your code impervious to the manner in which it is called will be made as appropriate throughout this workshop.  These are not essential to learning Maplets, and beginners in Maple should not spend too much time with them if they are not yet comfortable.

Exercise 1

Now, just to get you using Maplets, modify the maplet1  Maplet to have two buttons. Both buttons will terminate the Maplet. One button should display the text "I agree!" and return the value "true"; the other button should display "No way!" and return the value "false". Select one of the three categories, beginner, intermediate, or advanced, and create the Maplet.

Beginner

>    use Maplets[Elements] in
 maplet1e :=
  Maplet(
   [
    "Calculus is great!",
    %?("%?", %?("true")),
    %?("%?", %?("false"))
   ]
  );
end use:
Maplets[Display]( maplet1e );

>   

Intermediate

>    use Maplets[Elements] in
 maplet1e :=
  Maplet(
    [
     %?,
     %?,
     %?
    ]
  );
end use:
Maplets[Display]( maplet1e );

>   

Advanced

>    use Maplets[Elements] in
 maplet1e :=
  Maplet(
    ?%
  );
end use:
Maplets[Display]( maplet1e );

>   

A Solution

>    use Maplets[Elements] in
 maplet1e :=
  Maplet(
   [ # col 1
    "Calculus is Great!",
    Button( "I agree!", Shutdown( "true" ) ),
    Button( "No way!", Shutdown( "false" ) )
   ] # end col 1
  ); # end Maplet
end use:

Maplets[Display]( maplet1e );

>   

>   

>   

Lesson 2. The TextField and ComboBox Elements

The Calculus is Great!  Maplet is only marginally interactive.  To increase the interactivity of the Maplet, we introduce two new Maplet elements: the TextField  element, which allows the user to enter in text, and the ComboBox  element, which allows users to select one option from a list.  We will also show how a Maplet can return the value of an element when the Maplet terminates.

>    use Maplets[Elements] in
 maplet2 :=
  Maplet(
  [                          # col 1
   [                         # row 1 (contains 4 columns)
    "Calculus",
    ComboBox[CB1]( "with", [ "with", "without" ] ),
    "Maple is",
    TextField['TF1']()
   ],                        # end row 1
   [                         # row 2 (contains two columns)
    Button("OK", Shutdown(['CB1', 'TF1'])),
    Button("Cancel", Shutdown())
   ]                        # end row 2
  ]                         # end col 1
 );                         # end Maplet
end use:
Maplets[Display]( maplet2 );

>   

The new objects in this Maplet are:

  • The ComboBox  element.
  • The TextField  element.
  • A Shutdown  element which references the combo box and the text field.

The names 'CB1'  and 'TF1'  are references which you, the Maplet programmer, can use to refer to the current contents of the combo box and text field. Note how these references are used to return contents of one or more Maplet elements to the calling environment.

The first nested list indicates that these four elements should be grouped together on the first row of the Maplet. The second nested list indicates that these two buttons should be grouped together on the second row of the Maplet.  Any further nesting of lists is interpreted alternatively as columns and rows.

Example of Formatting

>    use Maplets[Elements] in
  maplet2a :=
    Maplet(
     [   # col 1 (containing 4 rows)
      ">>Top<<",      # row 1
      ">>Middle<<",   # row 2
      [               # row 3 (containing 3 columns)
       [                     # col 1 (containing 3 rows)
        ">>Top of Bottom Left<<",
        ">>Middle of Bottom Left<<",
        [
         ">>Left Side<<",
         ">>Right Side<<"
        ]
       ],                    # end col 1
       ">>Bottom Middle<<",  # col 2
      [                      # col 3
        ">>Top of Bottom Right<<",
        ">>Bottom of Bottom Right<<"
      ]                      # end col 3
     ],               # end row 3
     Button("OK", Shutdown())
    ]   # end col 1
   );   # end Maplet
end use:
Maplets[Display]( maplet2a );

>   

Further Formating - BoxColumns and BoxRows with borders

Instead of using lists of lists, you could replace, for example,

>    use Maplets[Elements] in
  maplet2b :=
    Maplet(
     [
      "OK?",
      [
       Button("OK", Shutdown("OK")),
       Button("Not OK", Shutdown("no"))
      ]
     ]
    );
end use:
Maplets['Display']( maplet2b );

with the objects they actually represent, that is, BoxColumns  and BoxRow  elements.

>    use Maplets[Elements] in
  maplet2c :=
    Maplet(
     BoxColumn(
      "OK?",
      BoxRow(
       Button("OK", Shutdown("OK")),
       Button("Not OK", Shutdown("no"))
      )
     )
    );
end use:
Maplets['Display']( maplet2c );

Why use the explicit objects?  These objects have options which you can modify:

>    use Maplets[Elements] in
  maplet2d :=
    Maplet(
     [
      "OK?",
      BoxRow( 'border', 'caption' = "Which one do you choose?",
       Button("OK", Shutdown("OK")),
       Button("Not OK", Shutdown("no"))
      )
     ]
    );
end use:
Maplets['Display']( maplet2d );

>   

For additional information on layout elements, please see ?Maplets,LayoutElements .

>   

Technical Tip - options

Each element has numerous options to control options about its display, possibly including parameters to adjust the size, colors, visibility, enabledness, etc.  The best listing of all available options can be found at ?Maplets,ElementOptions .

>   

>   

Technical Tip - quoting names

If the quotes were not present, and a user assigned a value to the name TF1 , then your Maplet would break.

If you are writing a procedure which generates a Maplet, it is recommended that you do not declare your references as locals to a procedure, as it will be difficult to get other procedures to get the value of those references.  You can declare the references as locals to a
module  so long as all procedures using the reference are exports of the same module.

You can also use strings instead of symbols, but some short cuts in the Evaluate  element will not be available to you.

>   

Fixed Return Values

A Shutdown  element can also have a return value as a string.

>    use Maplets[Elements] in
  maplet2b :=
    Maplet(
     [
      TextField['TF1'](),
      [
       Button( "OK", Shutdown("left", ['TF1']) ),
       "  ",
       Button( "Cancel", Shutdown("right") )
      ]
     ]
    );
end use:
Maplets[Display]( maplet2b );

>   

A Shutdown  element can return both a fixed string and parameters.

Exercise 2

Create a Maplet that collects all information needed to compute either the derivative or antiderivative of a function with respect to a variable. Thus, the Maplet needs to collect three values from the user: the operation, the function, and the independent variable. In addition to a button that returns the problem to be solved, the Maplet should include a button that resets all fields on the Maplet. The "reset" button needs to perform several actions. To implement this, use the 'onclick' option for the Button  element and create an Action  element (see ?Maplets[Elements,Action] ).

If the width of the text fields is too great, you can give it an integer option which is interpreted as the width of the text field, e.g., TextField[TF]('width'=10) .

>   

Beginner

>    use Maplets[Elements] in
 maplet2e :=
  Maplet(
  [                          # col 1
   [                         # row 1 (contains 5 columns)
    "The",
    %?['operation']( %?, [ "derivative", "antiderivative" ] ),
    "of",
    %?['function'](),
    "with respect to",
    %?['variable'](),
    "is"
   ],                        # end row 1
   [                         # row 2 (contains two columns)
    %?("%?", 'onclick'='reset' ),
    %?("%?", %?)
   ]                        # end row 2
  ],                        # end col 1

  Action['reset'](SetOption('operation'="derivative"),
                  SetOption('function'=""),
                  SetOption('variable'="") )

 );                         # end Maplet
end use:
Maplets[Display]( maplet2e );

>   

Intermediate

>    use Maplets[Elements] in
 maplet2e :=
  Maplet(
  [                          # col 1
   [                         # row 1 (contains 5 columns)
    "The",
    %?['operation']( %? ),
    "of",
    %?['function'](),
    "with respect to",
    %?['variable'](),
    "is"
   ],                        # end row 1
   [                         # row 2 (contains two columns)
    %?("%?", 'onclick'='reset' ),
    %?("%?", %?)
   ]                        # end row 2
  ],                        # end col 1

  Action['reset'](SetOption('operation'=%?),
                  SetOption('function'=%?),
                  SetOption('variable'=%?) )

 );                         # end Maplet
end use:
Maplets[Display]( maplet2e );

>   

Advanced

>    use Maplets[Elements] in
 maplet2e :=
  Maplet(
  [                          # col 1
   [                         # row 1 (contains 5 columns)
    %?
   ],                        # end row 1
   [                         # row 2 (contains two columns)
    %?
   ]                        # end row 2
  ],                        # end col 1

  Action['reset'](SetOption('operation'=%?),
                  SetOption('function'=%?),
                  SetOption('variable'=%?) )

 );                         # end Maplet
end use:
Maplets[Display]( maplet2e );

>   

A Solution

>    use Maplets[Elements] in
 maplet2e :=
  Maplet(
  [                          # col 1
   [                         # row 1 (contains 5 columns)
    "The",
    ComboBox['operation']( "derivative", [ "derivative", "antiderivative" ] ),
    "of",
    TextField['function'](),
    "with respect to",
    TextField['variable']('width'=3),
    "is"
   ],                        # end row 1
   [                         # row 2 (contains two columns)
    Button("Reset", 'onclick'='reset' ),
    Button("Return", Shutdown(['operation','function','variable']))
   ]                        # end row 2
  ],                        # end col 1

  Action['reset'](SetOption('operation'="derivative"),
                  SetOption('function'=""),
                  SetOption('variable'="") )

 );                         # end Maplet
end use:
Maplets[Display]( maplet2e );

>   

>   

Lesson 3. Communicating with the Maple Kernel

Up until now, all interactions have been limited to the Maplet itself.  When you click on a button, the Shutdown  element closes the Maplet, returning the contents of a text field located on the Maplet.

The following Maplet has a text field which allows the user to enter an expression and a button which, when selected calculates the derivative of the contents of the text field and display the result in a text box.

>    use Maplets[Elements] in
  maplet3 :=
    Maplet(
    [    # col 1 (contains 4 rows)
     "Enter an expression to differentiate (wrt x):",
     TextField['input'](),
     TextBox['output'](3..40),
     [   # row 4 (contains 2 columns)
      Button( "Differentiate",
              Evaluate( 'output' = 'diff(input, x)' )
            ),
      Button( "OK", Shutdown() )
     ]   # end row 4
    ]    # end col 1
   );    # end Maplet
end use:
Maplets[Display](maplet3);

>   

The new objects in this Maplet are:

  • The TextBox  element.
  • The Evaluate  element.

A text box is like a text field, but it can contain multiple rows of text.  The dimensions of the text box are given as a range of integers.  Refer to the help page ( ?Maplets[Elements,TextBox] ) to see other features of text boxes.

The Evaluate  element is the means of communicating with the Maple kernel.  The contents of the input text field is placed into the expression
      
diff( ..., x )
which is then parsed by the Maple kernel. Note that this command can be a user-defined or built-in Maple command.

>   

Technical Tip - unevaluation

Note that the expression given to Evaluate is within unevaluation quotes ( 'output' = 'diff(input, x)' .)  This is important as otherwise, Maple would immediately evaluate the right hand side. To illustrate, compare:

>    diff( input, x );

>    'diff( input, x )';

>   

Exercise 3

Modify the Maplet created in Exercise 2 to include a TextBox  containing the result of the operation specified by the user. This will require the implementation of a user-defined command that translates the user input into the appropriate Maple command. The following procedure uses the try ... catch ... end try  construct to intercept any errors that might arise; this is a good technique to adopt whenever a procedure receives user-entered input.

>    mycommand := proc( op, fn, var )
  try
    if op='derivative' then
      return Diff( fn, var ) = diff( fn, var );
    elif op='antiderivative' then
      return Int( fn, var ) = int( fn, var ) + C;
    end if;
  catch:
    return "error detected, please retry"
  end try
end proc:

>   

>    mycommand( derivative, x^2, x );

>   

Beginner

>    use Maplets[Elements] in
 maplet3e :=
  Maplet(
  [                          # col 1
   [                         # row 1 (contains 5 columns)
    "The",
    ComboBox['operation']( "derivative", [ "derivative", "antiderivative" ] ),
    "of",
    TextField['function'](),
    "with respect to",
    TextField['variable']('width'=3),
    "is"
   ],                        # end row 1
   %?['result']( %?..%? ),
   [                         # row 3 (contains two columns)
    Button("Reset", 'onclick'='reset' ),
    Button("Calculate",
           Evaluate( '%?' = '%?' )
          ),
    Button("Return", Shutdown( ) )
   ]                        # end row 3
  ],                        # end col 1

  Action['reset'](SetOption('operation'="derivative"),
                  SetOption('function'=""),
                  SetOption('variable'=""),
                  SetOption('result'="") )

 );                         # end Maplet
end use:
Maplets[Display]( maplet3e );

>   

Intermediate

>    use Maplets[Elements] in
 maplet3e :=
  Maplet(
  [                          # col 1
   [                         # row 1 (contains 5 columns)
    "The",
    ComboBox['operation']( "derivative", [ "derivative", "antiderivative" ] ),
    "of",
    TextField['function'](),
    "with respect to",
    TextField['variable']('width'=3),
    "is"
   ],                        # end row 1
   %?['result']( %? ),
   [                         # row 3 (contains two columns)
    Button("Reset", 'onclick'='reset' ),
    Button("Calculate",
           %?
          ),
    Button("Return", Shutdown( ) )
   ]                        # end row 3
  ],                        # end col 1

  Action['reset'](SetOption('operation'="derivative"),
                  SetOption('function'=""),
                  SetOption('variable'=""),
                  SetOption('result'="") )

 );                         # end Maplet
end use:
Maplets[Display]( maplet3e );

>   

Advanced

The solution to Exercise 2 is provided as your starting point.

>    use Maplets[Elements] in
 maplet3e :=
  Maplet(
  [                          # col 1
   [                         # row 1 (contains 5 columns)
    "The",
    ComboBox['operation']( "derivative", [ "derivative", "antiderivative" ] ),
    "of",
    TextField['function'](),
    "with respect to",
    TextField['variable']('width'=3),
    "is"
   ],                        # end row 1
   [                         # row 2 (contains two columns)
    Button("Reset", 'onclick'='reset' ),
    Button("Return", Shutdown( ) )
   ]                        # end row 2
  ],                        # end col 1

  Action['reset'](SetOption('operation'="derivative"),
                  SetOption('function'=""),
                  SetOption('variable'="")
                 )

 );                         # end Maplet
end use:
Maplets[Display]( maplet3e );

>   

 A Solution

>    use Maplets[Elements] in
 maplet3e :=
  Maplet(
  [                          # col 1
   [                         # row 1 (contains 5 columns)
    "The",
    ComboBox['operation']( "derivative", [ "derivative", "antiderivative" ] ),
    "of",
    TextField['function'](),
    "with respect to",
    TextField['variable']('width'=3),
    "is"
   ],                        # end row 1
   TextBox['result']( 3.. 20 ),
#   MathMLViewer['result']( ),
   [                         # row 3 (contains 3 columns)
    Button("Reset", 'onclick'='reset' ),
    Button("Calculate",
           Evaluate( 'result' = 'mycommand( operation, function, variable )' )
          ),
#    Button("Calculate",
#           Evaluate( 'result' = 'MathMLViewer( 'value' = MathML[Export](mycommand( operation, function, variable )) )' )
#          ),
    Button("Return", Shutdown( ) )
   ]                        # end row 3
  ],                        # end col 1

  Action['reset'](SetOption('operation'="derivative"),
                  SetOption('function'=""),
                  SetOption('variable'=""),
                  SetOption('result'="")
                 )

 );                         # end Maplet
end use:
Maplets[Display]( maplet3e );

>   

>   

Lesson 4: Plots

The following Maplet has a text field, a button, and a plotting region with which the user can display the graph of an expression. A check box  is used to determine the value of the discont  parameter in the plot function call.

Instead of a button to terminate the Maplet, a pulldown menu , File , in the menu bar provides options to clear the plot or exit the Maplet.  In order to include this menu in the menu bar it is necessary to use the Window  element. The overall layout of the Maplet is included in this element.

>   

>    use Maplets[Elements] in
  maplet5 :=
    Maplet(
     Window('menubar' = 'MB',
      [
       "Enter a function to plot w.r.t. x:",
       TextField['TF'](),
       [
        "Check for discontinuities before plotting:",
        CheckBox['CB']()
       ],
       Plotter['PL'](),
       Button( "Plot",
               Evaluate( 'PL = plot(TF, x=-10..10, discont=CB)' )
             )
      ]
     ),           # end Window

     MenuBar[MB](
      Menu(
        "File",
        MenuItem( "Clear",
                  Evaluate( 'PL' = 'plot(0, axes=none, color=white)' )
                ),
        MenuItem( "Exit",
                  Shutdown()
                )
      )            # end Menu
     )             # end MenuBar
    );             # end Maplet
end use:
Maplets[Display](maplet5);

>   

The new objects in the Maplet are:

  • The Window  element
  • The MenuBar , Menu , and MenuItem  elements
  • The Plotter  element.
  • The CheckBox  element.


Up until now, we've only used lists to represent what is to appear in the Maplet.  The
Maplet  routine was intelligent enought to determine that this was meant to be a window.  Now we want to add a title to that window.  In this case, we must now explicitly state the Window  element, and give it a title (the string) and the content of the window (the lists).  Again, like BoxRow , we have access to all the options available for windows which are set to default values if you simply use lists of lists.

The menu is reasonably straightforward.  Like a button, each menu item has an action associated with it.


The plotter element displays any Maple plot.

A check box may be selected or unselected by the user.

>   

Technical Tip - option values

While in this exercise we just use the option discont = CB , unfortunately, not all options of the form option_name = true  take an option of the form option_name = false , so if the box is not selected, the command will fail.  E.g.,

>    plot( sin(x), x=0..Pi, filled = false );

This can be remedied in one of two ways:

1.  Use the more verbose:

>    'plot( TF, x=0..Pi, `if`( CB, filled = true, NULL ) )';

>   

2.  Create a service routine which takes

>    MyPlot := proc(expr, fill)
    if fill then
      plot( expr, x=0..Pi, filled = true );
    else
      plot( sin(x), x=0..Pi );
    end if;
  end proc;

>   

and then use 'MyPlot( TF, CB )' .  This second method may appear to be more verbose, but it also helps in some cases to simplify your interface.  For example, the option scaling  takes to values, constrained  and unconstrained .  Instead of having a drop down box with the words constrained and unconstrained, instead, it would be better to have a check box with a caption Use constrained scaling: [ ]  ?  Again, you could do this with

>    'plot( TF, x = 0..Pi, `if`( CB, 'scaling' = 'constrained', NULL ) )';

>   

but you can imagine that pretty soon, your statements will look very verbose, and difficult to maintain.  It would be better to have a procedure:

>    MyPlot := proc(expr, fill, scale)
    local opts;
    opts := NULL;

    if fill then
      opts := opts, 'filled' = 'true';
    end if;

    if scale then
      opts := opts, 'scaling' = 'constrained';
    end if;

    plot( expr, opts );
  end proc:

>   

This second form tends to be more maintainable.  You can also debug MyPlot  outside the context of the Maplet, while you cannot as easily debug the inline routine.

Also note that
`if`  is not very good for anything other than boolean valued options.

>   

Exercise 4

Modify this Maplet so that you can enter a upper and a lower bound for the x-axis and the y-axis. You could use TextField elements to enter the data.  (Use default bounds of [-10,10] for both axes.)  Also, add an Edit  menu, and move the Clear  menu item from File  to Edit , and replace the Plot  button with a Plot  menu item under Edit . Draw a line between the Clear  and Plot  entries using a MenuSeparator()  element.

Also, by default have the check box for discontinuities selected.  This can be done by giving the option
'true'  to the check box.

>   

Technical Tip - menu separators

Don't separate all menu items with menu separators.  Separators should be used for grouping logical items together.  If no logical groups exist, then it is better to have no separators.

>   

>   

Beginner

>    use Maplets[Elements] in
  maplet5e :=
    Maplet(
     Window('menubar' = 'MB',
      [
       [         # row 1
        "Function (of x) to be plotted",
        TextField['TF']()
       ],        # end row 1
       [         # row 2
        "Plot the function from x=",
        TextField['Xlower']('width'=5, "%?"),
        " to x=",
        TextField['Xupper']('width'=5, "%?")
       ],        # end row 2
       [         # row 3
        "Display the function from y=",
        TextField['Ylower']('width'=5, "%?"),
        " to y=",
        TextField['Yupper']('width'=5, "%?")
       ],        # end row 3
       [         # row 4
         "Check for discontinuities before plotting:",
         CheckBox['CB'](%?)     # set the default value
       ],        # end row 4
       Plotter['PL']()
     ]
    ),           # end Window

    MenuBar['MB'](
      Menu( "File",
            MenuItem("Exit", Shutdown())
          ),     # end Menu
      Menu( "Edit",
            MenuItem("Plot", 'onclick' = %?),
            MenuSeparator(),
            MenuItem("Clear", 'onclick' = %?)
          )      # end Menu
      ),         # end MenuBar

    Action['showplot'](
     Evaluate(
      'PL' = 'plot(TF, x=Xlower..Xupper, y=Ylower..Yupper, discont=CB)'
             ) ),

    Action['clearplot'](
     Evaluate(
      'PL' = 'plot(0, axes=none, color=white)'
             ) )
  );             # end Maplet
end use:
Maplets[Display](maplet5e);

>   

Intermediate

>    use Maplets[Elements] in
  maplet5e :=
    Maplet(
     Window('menubar' = 'MB',
      [
       [         # row 1
        "Function (of x) to be plotted",
        TextField['TF']()
       ],        # end row 1
       [         # row 2
        "Plot the function from x=",
        TextField['Xlower']('width'=5, "%?"),
        " to x=",
        TextField['Xupper']('width'=5, "%?")
       ],        # end row 2
       [         # row 3
        %?,
        %?,
        %?,
        %?
       ],        # end row 3
       [         # row 4
         "Check for discontinuities before plotting:",
         CheckBox['CB'](%?)     # set the default value
       ],        # end row 4
       Plotter['PL']()
     ]
    ),           # end Window

    MenuBar['MB'](
      Menu( "File",
            MenuItem("Exit", Shutdown())
          ),     # end Menu
      Menu( "Edit",
            MenuItem("Plot", 'onclick' = %?),
            MenuSeparator(),
            MenuItem("Clear", 'onclick' = %?)
          )      # end Menu
      ),         # end MenuBar

    Action['showplot'](
     Evaluate(
      'PL' = 'plot(TF, x=%?..%?, y=%?..%?, discont=%?)'
             ) ),

    Action['clearplot'](
     Evaluate(
      'PL' = 'plot(0, axes=none, color=white)'
             ) )
  );             # end Maplet
end use:
Maplets[Display](maplet5e);

>   

Advanced

>    use Maplets[Elements] in
  maplet5e :=
    Maplet(
     Window('menubar' = 'MB',
      [
       [         # row 1
        "Function (of x) to be plotted",
        TextField['TF']()
       ],        # end row 1
       [         # row 2
        %?
       ],        # end row 2
       [         # row 3
        %?
       ],        # end row 3
       [         # row 4
         "Check for discontinuities before plotting:",
         CheckBox['CB'](%?)     # set the default value
       ],        # end row 4
       Plotter['PL']()
     ]
    ),           # end Window

    MenuBar['MB'](
      Menu( "File",
            MenuItem("Exit", Shutdown())
          ),     # end Menu
      Menu( "Edit",
            %?,
            %?,
            %?
          )      # end Menu
      ),         # end MenuBar

    Action['showplot'](
     Evaluate(
      %? = %?
             ) ),

    Action['clearplot'](
     Evaluate(
      'PL' = 'plot(0, axes=none, color=white)'
             ) )
  );             # end Maplet
end use:
Maplets[Display](maplet5e);

>   

A Solution

>    use Maplets[Elements] in
  maplet5e :=
    Maplet(
     Window('menubar' = 'MB',
      [
       [         # row 1
        "Function (of x) to be plotted",
        TextField['TF']()
       ],        # end row 1
       [         # row 2
        "Plot the function from x=",
        TextField['Xlower']('width'=5, "-10"),
        " to x=",
        TextField['Xupper']('width'=5, "10")
       ],        # end row 2
       [         # row 3
        "Display the function from y=",
        TextField['Ylower']('width'=5, "-10"),
        " to y=",
        TextField['Yupper']('width'=5, "10")
       ],        # end row 3
       [         # row 4
         "Check for discontinuities before plotting:",
         CheckBox['CB']('true')     # set the default value
       ],        # end row 4
       Plotter['PL']()
     ]
    ),           # end Window

    MenuBar['MB'](
      Menu( "File",
            MenuItem("Exit", Shutdown())
          ),     # end Menu
      Menu( "Edit",
            MenuItem("Plot", 'onclick' = 'showplot'),
            MenuSeparator(),
            MenuItem("Clear", 'onclick' = 'clearplot')
          )      # end Menu
      ),         # end MenuBar

    Action['showplot'](
     Evaluate(
      'PL' = 'plot(TF, x=Xlower..Xupper, y=Ylower..Yupper, discont=CB)'
             ) ),

    Action['clearplot'](
     Evaluate(
      'PL' = 'plot(0, axes=none, color=white)'
             ) )
  );             # end Maplet
end use:
Maplets[Display](maplet5e);

>   

>   

>   

Lesson 5: MathML output

The text-based output of the Maplet produced in Exercise 3 is not attractive.  Maple's provides support for displaying results with MathML. The MathMLViewer  element and the MathML[Export]  command can be used to display results in MathML. The following Maplet differs from the previous one in only two elements.

>   

>    use Maplets[Elements] in
 maplet4 :=
  Maplet(
  [                          # col 1
   [                         # row 1 (contains 5 columns)
    "The",
    ComboBox['operation']( "derivative", [ "derivative", "antiderivative" ] ),
    "of",
    TextField['function'](),
    "with respect to",
    TextField['variable']('width'=3),
    "is"
   ],                        # end row 1
#   TextBox['result']( 3.. 20 ),
   MathMLViewer['result']( ),
   [                         # row 3 (contains 3 columns)
    Button("Reset", 'onclick'='reset' ),
#    Button("Calculate",
#           Evaluate( 'result' = 'mycommand( operation, function, variable )' )
#          ),
    Button("Calculate",
           Evaluate( 'result' = 'MathMLViewer( 'value' = MathML[Export](mycommand( operation, function, variable )) )' )
          ),
    Button("Return", Shutdown( ) )
   ]                        # end row 3
  ],                        # end col 1

  Action['reset'](SetOption('operation'="derivative"),
                  SetOption('function'=""),
                  SetOption('variable'=""),
                  SetOption('result'="")
                 )

 );                         # end Maplet
end use:
Maplets[Display]( maplet4 );

>   

Lesson 6: Examining the Interactive Plot Builder

The interactive plots builder  is probably the most complex Maplet shipped with Maple 8.  It contains different layouts and options for many of the plotting routines.

>    plots[interactive]( sin(1/x) );

>    plots[interactive]( sin(x*y) );

>   

In general, it is nice to avoid Mapleisms where possible on a Maplet -- for example, initially, instead of writting The domain of x from [     ] to [     ] , the implementers wrote, x = [     ] .. [     ] .  This was, we believe, a mistake.  A new user to Maple does not know that ..  indicates a range, and the
   
x =
gives very little indication as to what it actually means.  Is it assigning something to
x ?  If you are an experienced Maple user and you are writing Maplets for novice users, it's a good idea to keep this in mind.

While it is possible to directly place options in a Maplet drop-down box, radio button, or check box using the standard Maple names and syntax, the plots builder has almost none of that.  For example, the light model as an option to plot has descriptive values such as light1 , light2 , light3 , and light4 .  After looking at each individual light model, the terms green-red , red-blue-yellow , red-turquoise , and gray-white  are seen to be more descriptive.  For point style, dash-dot  is used instead of the option name DASHDOT  (it is a weakness within Maple that you cannot use the lower case dashdot ).  Even for obvious options like axes , a substitution of string for name is used rather than just parsing the string.

The logic used to decide what does and does not appear in the Maplet and how to deal with what is returned is significant, and comprises 90% of the code.  On the other hand, it is quite easy to get a Maplet which looks something like an interactive plot builder:

>   

>    use Maplets[Elements] in
  styles1 := ["solid", "dash", "dot", "dash-dot"]:
  styles2 := ["thin", "1 pixel", "2 pixel", "3 pixel"]:
  symbols := ["box", "circle", "cross", "diamond", "point"]:
  sizes := ["2", "4", "6", "8", "10", "12", "15", "20"]:
  fonts := ["courier", "helvetica", "symbol", "times"]:
  coords := ["cartesian", "polar", "tangent"]:
  maplet6 :=
    Maplet(
     Window( "My Plots Interactive",
      [
       TextField( "(x) -> sin(x)", editable = false ),
       [
        "Domain of x from ",
        TextField['TF1']( 5, "-10" ),
        " to ",
        TextField['TF2']( 5, "10" ),
        " with label ",
        TextField['TF3']( 5, "x" ),
        DropDownBox['DDB0']( ["horizontal", "vertical"] )
       ],
       [
        [
         BoxRow( 'border', 'caption' = "Style",
                 DropDownBox['DDB1']( ["line", "point"] )
               ),
         BoxRow( 'border', 'caption' = "Line Style",
                 DropDownBox['DDB2']( styles1 ),
                 DropDownBox['DDB3']( styles2 )
               ),
         BoxRow( 'border', 'caption' = "Symbol",
                 DropDownBox['DDB4']( "cross", symbols ),
                 DropDownBox['DDB5']( "10", sizes )
               )
        ],
        [
         BoxColumn( 'border', 'caption' = "Title",
                    TextField[TF4](),
                    [
                     DropDownBox['DDB6']( "times", fonts ),
                     DropDownBox['DDB7']( "10", sizes ),
                     ToggleButton['TB1']( "B" ),
                     ToggleButton['TB2']( "I" )
                    ]
                  ),
         BoxRow( 'border', 'caption' = "View",
                 "Constrained Scaling   ",
                 CheckBox[ChB1]()
               ),
         BoxRow( 'border', 'caption' = "Coordinate System",
                 DropDownBox['DDB8']( coords )
               )
        ]
       ],
       [
        Button( "Clear", Action() ),
        Button( "Cancel", Shutdown("cancel") ),
        "   ",
        Button( "Command",
                Shutdown("command",
                         [
                          'TF1, TF2, TF3, DDB0,
                           DDB1,
                           DDB2, DDB3,
                           DDB4, DDB5,
                           TF4, DDB6, DDB7, TB1, TB2,
                           ChB1,
                           DDB8'
                         ]
                        )
              ),
        Button( "Plot",
                Shutdown("plot",
                         [
                          'TF1, TF2, TF3, DDB0,
                           DDB1,
                           DDB2, DDB3,
                           DDB4, DDB5,
                           TF4, DDB6, DDB7, TB1, TB2,
                           ChB1,
                           DDB8'
                          ]
                         )
              )
       ]
      ]
     )
  );
end use:

Maplets[Display]( maplet6 );

>   

>   

Additional Exploration

Please use the remaining time (if any) in this workshop to begin to implement a Maplet for a topic of interest to you.

Here are a few suggestions for Maplet programming projects involving modifications to Maplets presented in this worksheet:

A common way to start writing a Maplet is to find an existing Maplet with a similar layout or functionality. In addition to the Maplets encountered previously in this worksheet, take a look at the Maplets in Maplette.mws (created by Sylvain Muise and Doug Harder for a course at the 2002 Maple Summer Workshop).

>   

>   

Maple TM is a registered trademark of Waterloo Maple Inc.
Math rendered by WebEQ