Contents Previous Next Index
|
13 Programming Interactive Elements
|
|
The Maple standard interface provides several tools for building interactive mathematical content. It includes a set of embedded components, which are configurable graphical controls, buttons, meters, and other interactive components that you can insert in a Maple document to analyze, manipulate, and visualize equations and Maple commands. For example, several task templates in Maple use embedded components to demonstrate mathematical concepts.
The Maple library also includes a package called Maplets for building custom user interfaces to allow users to perform analysis tasks related to your mathematics. Several Maple commands, such as the tutors in the Student package, use Maplets that allow users to perform various tasks.
|
13.1 In This Chapter
|
|
•
|
Programming embedded components
|
|
|
13.2 Programming Embedded Components
|
|
In the Maple standard interface, embedded components are available in the Components palette. These components include boxes, lists, gauges, and dials.
|
Adding Embedded Components to a Document
|
|
When you click an icon in the Components palette, the corresponding embedded component is inserted in your document at the current cursor location. For example, you can insert a button
within a paragraph, or you can include a series of plot components, sliders, and check boxes that function together.
You can use a table to lay out the components in your document. To insert a table, from the Insert menu, select Table. You can then insert buttons, plots, gauges, math, text, and so on in each table cell.
|
|
Editing Component Properties
|
|
Embedded components can be programmed to accomplish specific tasks when mouse actions are performed. For example, button components and sliders can be programmed to display information when they are clicked or dragged, and a plot component can be programmed to display points when it is clicked. To program an embedded component to perform a task, you must edit the properties of the embedded component and, in most cases, provide the code needed to accomplish the task.
For example, if you want to provide code for a button component, you would right-click (Control-click for Macintosh) the button component that you inserted in your document and select Properties. You would then click the Edit button beside Action When Clicked to display a window in which you can enter the code (see Figure 13.1). By default, this window contains sample code that you can start with.
|
Figure 13.1: Code Region for an Embedded Component
|
|
|
Each embedded component has different properties that you can edit. For more information about the properties for a specific component, refer to the EmbeddedComponents help page and browse to the page of the component that you want to use.
Tip: If you are working with multiple components in a document, you may find it easier to include the code for all of the component actions in one area, for example, the startup code region of your document. For more information, see the worksheet,documenting,startupcode help page.
|
|
Example: Creating a Tic-Tac-Toe Game
|
|
In the following example, a tic-tac-toe game will be created using embedded components in Maple. This example contains nine list boxes that are organized in a 3 by 3 table.
It is possible to associate code with each of the list boxes individually. However, if you want to change this code in the future, you would need to change it in nine places. A simpler approach is to write a Maple module that contains the code to perform the action and call that code from each list box.
1.
|
Open a new Maple document.
|
2.
|
To insert a table, from the Insert menu, select Table...
|
3.
|
In the Rows and Columns fields, enter 3, and click OK.
|
4.
|
Place your cursor in the top-left cell of your table.
|
5.
|
On the left side of the Maple window, open the Components palette and click the list box component icon.
|
6.
|
In your document, right-click (Control-click for Macintosh) the list box component that you inserted and select Component Properties...
|
7.
|
Click the Edit button beside Item List.
|
8.
|
In the item list, double-click ListBox, replace this value with a hyphen character (-), and press Enter.
|
9.
|
Click the Add button, double-click the new field, enter X in this field, and press Enter. Repeat this step to add a list item for O.
|
10.
|
To close the dialog box, click OK.
|
11.
|
Click the Edit button beside Action When Selection Changes and replace the default code with TicTacToe:-Select( %this);, and click OK.
|
12.
|
In the Name field, specify the name ListBox0 for the component.
|
Tip: Make sure that all of the embedded components in your document have unique names.
13.
|
To close the Properties dialog box, click OK.
|
14.
|
In the document, select the list box, and then copy and paste it into all of the remaining cells.
|
Note: You can copy and paste embedded components within a document or from one document to another. A unique name is assigned to each pasted component - the number in the component name is incremented. Other details associated with the component, for example, properties and actions, are copied in their original form.
15.
|
Below the table, enter the following module to perform the action.
|
>
|
TicTacToe := module()
uses DT = DocumentTools;
export Select;
Select := proc( what )
if DT:-GetProperty( what, 'value' ) <> "-" then
DT:-SetProperty( what, 'enabled', false );
end if;
end proc;
end module;
|
The %this argument, which is passed as the value of the what parameter to the TicTacToe:-Select procedure, is set to the name of the component that generates the action. Therefore, the result is that if you select either the "X" or the "O" list element, the list box is dimmed and the user's selection cannot be changed.
For more information about modules, see Programming with Modules.
Alternatively, you can save this module in a Maple library archive, which is a separate file in which you can store Maple procedures, modules, and other data. For more information, refer to the repository help page.
|
|
Retrieving and Updating Component Properties
|
|
The examples above use commands from the DocumentTools package to retrieve information from components and update component properties. This package includes the following commands.
•
|
GetProperty: Retrieve information from a component.
|
•
|
SetProperty: Update a component.
|
•
|
Do: An alternate interface to both GetProperty and SetProperty. This command can be used to retrieve and update components.
|
For more information about the properties that can be retrieved and set for each component, refer to the EmbeddedComponents help page and browse to the help page of the component that you want to use.
|
|
Using the GetProperty Command to Retrieve Properties
|
|
You can specify two arguments for the DocumentTools:-GetProperty command: the name of the component and the property (or option) to be retrieved. Note: The value returned by the GetProperty command will either be a number or a string. For example, the command DocumentTools:-GetProperty( component_name, 'visible' ) returns a value of "true" or "false". To retrieve the corresponding Boolean value, the result must be processed by the parse command: parse( DocumentTools:-GetProperty( component_name, 'visible' ) ) returns a value of true or false. However, in many cases, this extra step is not necessary. For example, the comparison
>
|
if DocumentTools:-GetProperty( component_name, 'visible' ) = "true" then
|
will be faster than
>
|
if parse( DocumentTools:-GetProperty( component_name, 'visible' ) ) then
|
|
|
Using the SetProperty Command to Update Properties
|
|
You can specify the following arguments for the DocumentTools:-SetProperty command: the name of the component to update, the property to update, the new value for that property, and an optional parameter to indicate whether the update occurs immediately.
Code associated with a component can perform many different tasks. In particular, it can update other components. For example, you can create a plot component that returns certain values displayed in TextArea components or makes changes to other plots when the plot component is clicked.
When code is run as a result of a mouse event that updates other components, those updates occur after that code runs successfully. While this process is efficient, in some cases, you might want these updates to occur immediately. In such cases, you can use the optional refresh = true parameter, or simply refresh.
|
|
Using the Do Command to Retrieve and Update Component Properties
|
|
The DocumentTools:-Do command is a convenient interface to both the DocumentTools:-GetProperty and DocumentTools:-SetProperty commands. Components can be referenced as variables in expressions. For example, suppose that you have a math container component, two text area components, a button, and a plot component. You can enter a math expression in the variable x in the math container, numbers in each of the text areas and click the button, causing the expression to be plotted over the range specified by the numbers. Assuming the components that you inserted in your document are named MathContainer0, TextArea0, TextArea1, Button0, and Plot0, respectively, you can accomplish this task by using the single command DocumentTools:-Do( %Plot0 = plot( %MathContainer0, 'x' = %TextArea0 .. %TextArea1 ) ).
Consider the following points when deciding whether to use the DocumentTools:-Do command to retrieve or update components.
•
|
The embedded component type determines the default property retrieved or set by the Do command. For most components, the value property is the default property that is retrieved or set. This means that the Do command must query the GUI to determine which information to retrieve. The GetProperty and SetProperty commands avoid this step by requiring you to specify which property to retrieve. However, if you are working with a small number of components, this extra step will usually be insignificant.
|
•
|
The names of components appearing in the first argument to Do must be literal names prefixed by %. That is, you cannot use the Do command to access or update a component with a name that is determined programmatically.
|
|
|
|
13.3 Programming Maplets
|
|
You can use Maplet technology to build custom interfaces for any Maple functionality. Maplets can be run in the Maple standard interface. In Windows, you can also run Maplets in the Maplet Viewer, which is an application that you can run outside of the Maple standard interface. For more information about the Maplet Viewer, refer to the MapletViewer help page.
Maplets support standard UI elements including buttons, drop lists, text fields, and sliders. Some of the available UI elements are specific to Maple, for example, math fields and plot regions. For more information about these elements, refer to the Maplets,Elements help page.
Before creating a Maplet, familiarize yourself with the features of the various layout managers, which define how the elements of your Maplets are positioned and laid out.
This section describes basic information related to laying out elements in Maplets. For advanced information, refer to the examples,AdvancedMapletsLayout worksheet.
|
Layout Managers
|
|
A layout manager defines the locations and positions of the UI elements in a Maplet window. Three layout managers are available.
•
|
Box layout (BoxLayout): this layout manager can be used to create boxes that contain elements positioned horizontally or vertically relative to other elements.
|
•
|
Grid layout (GridLayout): this layout manager positions elements in a specific cells in a grid, similar to a spreadsheet.
|
•
|
Border layout (BorderLayout): this layout manager allows you to lay out elements in specific regions, according to compass directions.
|
For simple Maplets, using a layout manager is often sufficient; however, for more complex Maplets, you may need to use multiple layout managers or nest layout managers one inside the other.
Note: For clarity, the full command for each layout control is used in this chapter.
The three layout managers are available in the Maplets,Elements subpackage of the Maplets package. In this chapter, assume that the following command has been run.
>
|
with(Maplets:-Elements):
|
This command allows the Maplets:-Elements package commands to be used without prefixing them with Maplets:-Elements:-....
|
|
Box Layout
|
|
The box layout is the most commonly used layout manager. It is a nested construct of containers where elements can be displayed either horizontally or vertically in the Maplet window. For example,
>
|
mlet := Maplet(BoxLayout(border=true, caption="outer",
BoxColumn(border=true, caption="inner1",
Button("OK1", onclick=Shutdown()),
Button("OK2", onclick=Shutdown())
),
BoxColumn(border=true, caption="inner2",
TextBox("Misc. Text", height=5)
)
)):
Maplets:-Display(mlet);
|
As shown in the example above, you can use a BoxColumn element to specify a column in a box layout. You can also use a BoxRow element to specify a row in a box layout.
For detailed information about box layouts, refer to the Maplets,Elements,BoxLayout help page.
|
Controlling the Spacing in a Box Layout
|
|
In a box layout, box row, or box column you can use the inset option to specify the amount of spacing between the border of the box element and its contents.
In a row or column of a box layout, you can also use the spacing option to specify the amount of spacing that separates individual elements in that row or column.
The following examples demonstrate the use of these options.(Note: In both cases, the outer BoxLayout element has the inset option set to 0 so that the formatting of the BoxColumn element can be displayed more easily):
Example 1: Using the inset Option
In this example, the spacing option is set to 0, so the buttons are positioned close to each other in the generated Maplet window. The buttons are positioned in the center of the Maplet because the inset value displays space between the buttons and the border of the box element.
>
|
mlet := Maplet(BoxLayout(inset=0,
BoxColumn(inset=10, spacing=0,
Button("OK1", onclick=Shutdown()),
Button("OK2", onclick=Shutdown())
)
)):
Maplets:-Display(mlet);
|
Example 2: Using the spacing Option
In this example, the spacing option displays space between the buttons in the generated Maplet window. Also, since the inset option is set to 0, no spacing is displayed between the border of the box element and the buttons. As a result, the buttons are closely aligned with the top and bottom borders of the box element.
>
|
mlet := Maplet(BoxLayout(inset=0,
BoxColumn(inset=0, spacing=10,
Button("OK1", onclick=Shutdown()),
Button("OK2", onclick=Shutdown())
)
)):
Maplets:-Display(mlet);
|
|
|
Displaying Elements Vertically and Horizontally in a Box Layout
|
|
The vertical option can be specified for box layouts only. When the vertical option is set to false, elements are displayed horizontally in the Maplet window; when the vertical option is set to true, elements are displayed vertically. For more control over the spacing of the elements in a box layout, use the box layout with either a BoxRow element (when the vertical option is set to false) or a BoxColumn element (when the vertical option is set to true).
The following example shows two buttons that are positioned vertically and closely spaced.
>
|
mlet := Maplet(BoxLayout(inset=0, vertical=true,
Button("OK1", onclick=Shutdown()),
Button("OK2", onclick=Shutdown())
)):
Maplets:-Display(mlet);
|
In the following example, the spacing has been removed by nesting the buttons in a BoxColumn element.
>
|
mlet := Maplet(BoxLayout(inset=0,
BoxColumn(inset=0, spacing=0,
Button("OK1", onclick=Shutdown()),
Button("OK2", onclick=Shutdown())
)
)):
Maplets:-Display(mlet);
|
|
|
|
Grid Layout
|
|
In a grid layout, all of the elements are displayed in a rectangular grid.
Each grid layout must contain one or more GridRow elements which must, in turn, contain one or more GridCell elements.
Note: Each row or column of the grid is sized according to the maximum height or width of all the elements in that row or column. By default, no spacing is displayed between the largest elements in a grid layout.
The following is a simple example of a grid layout.
>
|
mlet := Maplet(GridLayout(border=true, caption="grid",
GridRow(
GridCell(Label("Button1:")),
GridCell(Button("OK1", onclick=Shutdown()))
),
GridRow(
GridCell(Label("Button2:")),
GridCell(Button("OK2", onclick=Shutdown()))
)
)):
Maplets:-Display(mlet);
|
For detailed information about grid layouts, refer to the Maplets,Elements,GridLayout help page.
|
Specifying the Width and Height of Grid Cells
|
|
You can specify the width and height of a GridCell element. The GridCell element must be added in the top-left cell in the grid. For example, if you want to create a GridCell element with a height of two grid cells, the element must appear in the first GridRow that contains it, and the GridRow element that follows it will be adjusted to allow it to fit.
>
|
mlet := Maplet(GridLayout(
GridRow(
GridCell(height=2,
Button("2h", width=52, height=2*25,
onclick=Shutdown())
),
GridCell(
Button("1a", width=52, height=25,
onclick=Shutdown())
),
GridCell(
Button("1b", width=52, height=25,
onclick=Shutdown())
)
),
GridRow(
# This is where the button above extends into
GridCell(
Button("1c", width=52, height=25,
onclick=Shutdown())
),
GridCell(
Button("1d", width=52, height=25,
onclick=Shutdown())
)
),
GridRow(
GridCell(
Button("1e", width=52, height=25,
onclick=Shutdown())
),
GridCell(width=2,
Button("2w", width=2*52, height=25,
onclick=Shutdown())
)
)
)):
Maplets:-Display(mlet);
|
In the following example, the full alignment option is used, so it is not necessary to specify a size for each button.
>
|
mlet := Maplet(GridLayout(halign=full, valign=full,
GridRow(
GridCell(height=2,
Button("2h", onclick=Shutdown())
),
GridCell(
Button("1a", onclick=Shutdown())
),
GridCell(
Button("1b", onclick=Shutdown())
)
),
GridRow(
# This is where the button above extends into
GridCell(
Button("1c", onclick=Shutdown())
),
GridCell(
Button("1d", onclick=Shutdown())
)
),
GridRow(
GridCell(
Button("1e", onclick=Shutdown())
),
GridCell(width=2,
Button("2w", onclick=Shutdown())
)
)
)):
Maplets:-Display(mlet);
|
|
|
|
Border Layout
|
|
Unlike the other layout managers, the border layout is a container element for other layout managers, though, it can be used for simple Maplets.
Five positions in the layout can be filled: north, south, west, east, and center, each of which has its own layout rules. See Figure 13.2.
|
Figure 13.2: Border Layout Diagram
|
|
|
In terms of resizing, north and south extend horizontally, east and west extend vertically, and center extends in both directions.
|
Positioning Elements in a Border Layout
|
|
The constraint option can be used in GridCell elements to indicate where its elements should be placed in the Maplet window. Valid options are north, south, west, east, and center.
The following is a simple example of a border layout.
>
|
mlet := Maplet(BorderLayout(
GridCell2(constraint=north,
Label("This is a long title")),
GridCell2(constraint=south,
Label("This could be a status bar")),
GridCell2(constraint=east,
Button("East", onclick=Shutdown())),
GridCell2(constraint=west,
Button("West", onclick=Shutdown())),
GridCell2(constraint=center,
Button("Center", onclick=Shutdown()))
)):
Maplets:-Display(mlet);
|
Not all constraint options need to be specified; however, including more than one of the same constraint returns an error.
Example:
>
|
mlet := Maplet(BorderLayout(border=true, caption="borderlayout",
GridCell2(constraint=north,
Label("This is a long title")),
GridCell2(constraint=south,
Label("This could be a status bar")),
GridCell2(constraint=east,
Button("East", onclick=Shutdown())),
GridCell2(constraint=west,
Button("West", onclick=Shutdown())),
GridCell2(constraint=center,
Button("Center", onclick=Shutdown()))
)):
Maplets:-Display(mlet);
|
For detailed information about border layouts, refer to the Maplets,Elements,BorderLayout help page.
|
|
Aligning Elements in a Border Layout
|
|
In a BorderLayout the north, south, and center cells can extend horizontally, and the east, west, and center cells can extend vertically. As a result, the elements in the border layout can be stretched. Unlike the other layout managers, the elements are stretched to fit within the layout, so alignment must occur in the elements themselves. Note that horizontal alignment options (halign) can only be specified for the elements in the north, south, and center GridCell2 elements, and vertical alignment options (valign) can only be specified for the elements in the east, west, and center GridCell2 elements.
Examples
The following example is the same as the example above, except that the halign option has been specified for the north and south labels (note the alignment is specified in the Label elements):
>
|
mlet := Maplet(BorderLayout(
GridCell2(constraint=north,
Label("This is a long title", halign=left)),
GridCell2(constraint=south,
Label("This could be a status bar", halign=left)),
GridCell2(constraint=east,
Button("East", onclick=Shutdown())),
GridCell2(constraint=west,
Button("West", onclick=Shutdown())),
GridCell2(constraint=center,
Button("Center", onclick=Shutdown()))
)):
Maplets:-Display(mlet);
|
In the following example, the element in the center cell stretches to fit a larger layout.
>
|
mlet := Maplet(BorderLayout(
GridCell2(constraint=north,
Label("This is a very long title which causes "
"the center to stretch")
),
GridCell2(constraint=east, Button("East", onclick=Shutdown())),
GridCell2(constraint=west, Button("West", onclick=Shutdown())),
GridCell2(constraint=center, Button("Center", onclick=Shutdown()))
)):
Maplets:-Display(mlet);
|
|
|
|
|
Contents Previous Next Index
|