| > |
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.
| > |
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, 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 , 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 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:
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:
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 ); |
| > |
| > |
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