Computer Science 2574
Intro to Data Structures & Soft Eng

Amulet Code Examples

Contents

The following brief code examples demonstrate how to use various Amulet interface features in your program. Click on the links below to quickly reach the desired example:

Amulet & C++ Classes

When integrating Amulet with C++ classes that are using namespace std; MSVC must be informed that you are going to be combining the standard namespace with Amulet code that does not use the standard namespace. This is essentially what MS has done for all of the common C.h header files. Looking in the MSVC include directory and viewing one of the namepsace header files (without the .h), e.g., Ctime, (not time.h), one will see the compiler directives that MS has included to inform the compiler of the integration of the old time.h code with code that is using the standard namespace. The same compiler directive "wrapper" code is needed for "amulet.h". Therefore one must use the following" camulet" header in place of "amulet.h" when using amulet with standard namespace code.

Right click and choose "Save Target As..." to download the camulet header file.


// camulet standard namespace header

#if _MSC_VER > 1000
#pragma once
#endif

#ifndef _CAMULET_
#define _CAMULET_
#ifdef _STD_USING
#undef _STD_USING
#include <amulet.h>
#define _STD_USING
#else
#include <amulet.h>
#endif /* _STD_USING */
#endif /* _CAMULET_ */


Amulet Menubar Example

The following Amulet code creates an application with one File menu with the usual options. Attached to a few of the options are callback functions defined as Amulet methods using the Amulet Define Method macro as my_<file menu option>_do functions. The callback functions do nothing except print out that they have been called. To view the callback function output, the Amulet "console.cc" and "console.h" files from the d:\amulet\src\gem\ directory should be copied into your project folder and added to your project, (rename "console.cc" to "console.cpp" so that MSVC will recognize it as a C++ file).

Right click and choose "Save Target As..." to download the Amulet menubar example code file.

 
#include <amulet.h>

#include <iostream.h>

//compile with amulet files: "console.cpp" & "console.h" for console output

//Define callback function for File menu Open... option
Am_Define_Method(Am_Object_Method, void, my_open_do, (Am_Object self))
{
cout << endl << "my_open_do() called" << endl << flush;
}

//Define callback function for File menu Save As... option
Am_Define_Method(Am_Object_Method, void, my_saveas_do, (Am_Object self))
{
cout << endl << "my_saveas_do() called" << endl << flush;
}

//Define callback function for File menu Close option
Am_Define_Method(Am_Object_Method, void, my_close_do, (Am_Object self))
{
cout << endl << "my_close_do() called" << endl << flush;
}

void InitMenus (Am_Object& my_menu_bar);


int main (void)
{

Am_Initialize (); //Initialize Amulet

//Create an Amulet Window
Am_Object my_win = Am_Window.Create ("my_win")
.Set (Am_LEFT, 20)
.Set (Am_TOP, 50)
.Set (Am_WIDTH, 500)
.Set (Am_HEIGHT, 500)
.Set (Am_TITLE, "My Window");

Am_Object my_menu_bar;

InitMenus (my_menu_bar);

my_win.Add_Part(my_menu_bar);

Am_Screen.Add_Part (my_win);


Am_Main_Event_Loop ();
Am_Cleanup ();

return 0;
}


void InitMenus (Am_Object& my_menu_bar)
{
my_menu_bar = Am_Menu_Bar.Create("my_menu_bar")
.Set(Am_FILL_STYLE, Am_Motif_Gray)
.Set(Am_ITEMS, Am_Value_List ()
.Add (Am_Command.Create("File_Command")
.Set(Am_LABEL, "File")
.Set(Am_IMPLEMENTATION_PARENT, true) //not undoable //File menu has no callback Fn
.Set(Am_ITEMS, Am_Value_List ()
.Add (Am_Command.Create("New_Command")
.Set(Am_LABEL, "New...")
.Set(Am_ACCELERATOR, "^n")
.Set(Am_ACTIVE, false)
.Set(Am_IMPLEMENTATION_PARENT, true) ) //not undoable //New option has no callback Fn
.Add (Am_Command.Create("Open_Command")
.Set(Am_LABEL, "Open...")
.Set(Am_ACCELERATOR, "^o")
.Set(Am_ACTIVE, true)
.Set(Am_DO_METHOD, my_open_do)) //callback Fn for Open option
.Add (Am_Menu_Line_Command.Create("my menu line")) //menu spacer line
.Add (Am_Command.Create("Save_Command")
.Set(Am_LABEL, "Save")
.Set(Am_ACCELERATOR, "^s")
.Set(Am_ACTIVE, false)
.Set(Am_IMPLEMENTATION_PARENT, true) ) //not undoable //Save option has no callback Fn
.Add (Am_Command.Create("Save_As_Command")
.Set(Am_LABEL, "Save As...")
.Set(Am_ACCELERATOR, "^a")
.Set(Am_DO_METHOD, my_saveas_do)) //callback Fn for Save As... option
.Add (Am_Command.Create("Close_Command")
.Set(Am_LABEL, "Close")
.Set(Am_ACCELERATOR, "^w")
.Set(Am_DO_METHOD, my_close_do)) //callback Fn for Close option
.Add (Am_Menu_Line_Command.Create("my menu line")) //menu spacer line
.Add (Am_Quit_No_Ask_Command.Create() ) //Amulet Quit FN callback
)
)
) ;

} // InitMenus


Amulet Text Field Example

The following Amulet code creates an application with one alley menu with a few options options. Two amulet text fields are created in the window. An alley label field, which is never changed, and an alley field which is set to the alley menu option that is selected by the user. The code uses the camulet header file discussed above in order to use the standard namespace header files with Amulet. The code demonstrates how to define slots and register them with Amulet so that they can later be used to store/create an Amulet object and added to an existing object for display. (Some of the code in this example was generated by Gilt and modified.)

Right click and choose "Save Target As..." to download the Amulet text field example code file.


#include "camulet.h" //use MSVC wrapper directives for use with standard namespace

//#include <iostream> //included by "console.h" and "am_io.h"
#include <fstream>
#include <iomanip>

//compile with amulet files: "console.cpp" & "console.h" for console output

using namespace std;

Am_Object my_win; //define window to be global so callback functions have access

//Define slot/part objects and register with amulet
Am_Slot_Key AlleyLabel = Am_Register_Slot_Name ("AlleyLabel");
Am_Slot_Key AlleyField = Am_Register_Slot_Name ("AlleyField");

//Define callback function for Alley menu Hilltop option
Am_Define_Method(Am_Object_Method, void, hilltop_do, (Am_Object self))
{
cout << endl << "hilltop_do() called" << endl << flush;
//change alleyfield text to object - get the AlleyField object and set its Am_Text value
my_win.Get_Object(AlleyField).Set(Am_TEXT, "Hilltop Lanes");
}

//Define callback function for Alley menu Mountaineer option
Am_Define_Method(Am_Object_Method, void, mountaineer_do, (Am_Object self))
{
cout << endl << "mountaineer_do() called" << endl << flush;
//change alleyfield text to object - get the AlleyField object and set its Am_Text value
my_win.Get_Object(AlleyField).Set(Am_TEXT, "Mountaineer Lanes");
}

void InitMenus (Am_Object& my_menu_bar);

int main (void)
{

Am_Initialize (); //Initialize Amulet


my_win = Am_Window.Create ("my_win") //Create an Amulet Window
.Set (Am_LEFT, 20)
.Set (Am_TOP, 50)
.Set (Am_WIDTH, 500)
.Set (Am_HEIGHT, 500)
.Set (Am_TITLE, "My Window");

//add the alley label & AlleyField objects to the window
my_win.Add_Part(AlleyLabel, Am_Text.Create("AlleyLabel")
.Set(Am_LEFT, 10)
.Set(Am_TOP, 37)
.Set(Am_WIDTH, 42)
.Set(Am_HEIGHT, 14)
.Set(Am_TEXT, "Alley:")
.Set(Am_LINE_STYLE, Am_Black)
.Set(Am_FILL_STYLE, Am_No_Style)
)
.Add_Part(AlleyField, Am_Text.Create("AlleyField")
.Set(Am_LEFT, 58)
.Set(Am_TOP, 37)
.Set(Am_WIDTH, 119)
.Set(Am_HEIGHT, 14)
.Set(Am_TEXT, "Mountaineer Lanes")
.Set(Am_LINE_STYLE, Am_Black)
.Set(Am_FILL_STYLE, Am_No_Style)
);


Am_Object my_menu_bar;

InitMenus (my_menu_bar);

my_win.Add_Part(my_menu_bar);

Am_Screen.Add_Part (my_win);

cout << endl << "Start Event Loop" << endl << flush ;

Am_Main_Event_Loop ();
Am_Cleanup ();

return 0;
}


void InitMenus (Am_Object& my_menu_bar)
{
my_menu_bar = Am_Menu_Bar.Create("my_menu_bar")
.Set(Am_FILL_STYLE, Am_Motif_Gray)
.Set(Am_ITEMS, Am_Value_List ()
.Add (Am_Command.Create("Alley_Command")
.Set(Am_LABEL, "Alleys")
.Set(Am_IMPLEMENTATION_PARENT, true) //not undoable //Alley menu has no callback Fn
.Set(Am_ITEMS, Am_Value_List ()
.Add (Am_Command.Create("Hilltop_Command")
.Set(Am_LABEL, "Hilltop")
.Set(Am_ACTIVE, true)
.Set(Am_DO_METHOD, hilltop_do)) //callback Fn for Hilltop option
.Add (Am_Command.Create("Mountaineer_Command")
.Set(Am_LABEL, "Mountaineer")
.Set(Am_ACTIVE, true)
.Set(Am_DO_METHOD, mountaineer_do)) //callback Fn for Mountaineer option
.Add (Am_Command.Create("Triangle_Command")
.Set(Am_LABEL, "Triangle")
.Set(Am_ACTIVE, false)
.Set(Am_IMPLEMENTATION_PARENT, true) ) //not undoable //Triangle option has no callback Fn
.Add (Am_Menu_Line_Command.Create("my menu line"))
.Add (Am_Quit_No_Ask_Command.Create() ) //Amulet Quit FN callback
)
)
) ;

} // InitMenus


Amulet Buttton and Text Input Field Example

The following Amulet code creates an application with one button, text output label & field, and a input text field with a label. The input text field is hidden until the user presses the "Open File..." button. The user can double click in the un-hidden input text field to select the field's text and type a string representing a file name . Upon hitting return, the input text field is hidden again and the text output field is set to display the entered string (file name). The entered string is then converted from a Am_String object to a C style string (char* pointer) to a C++ string object which is then output in the console window.

The code demonstrates how to define a button object, a text input widget. It also shows how to attach callback functions, to hide and unhide objects and access the object's values to make then interact.

Right click and choose "Save Target As..." to download the Amulet button and text input field example code file.


#include "camulet.h" //use MSVC wrapper directives for use with standard namespace

//#include <iostream> //included by "console.h" and "am_io.h"
#include <fstream>
#include <iomanip>
#include <string>

//compile with amulet files: "console.cpp" & "console.h" for console output

using namespace std;

Am_Object my_win; //define window to be global so callback functions have access


//Define slot/part objects and register with amulet
Am_Slot_Key OpenFileLabel = Am_Register_Slot_Name ("OpenFileLabel");
Am_Slot_Key OpenFileField = Am_Register_Slot_Name ("OpenFileField");

Am_Slot_Key OpenButton = Am_Register_Slot_Name ("OpenButton");

Am_Slot_Key ReadFile = Am_Register_Slot_Name ("ReadFile");


//Define callback function for Open File button
Am_Define_Method(Am_Object_Method, void, OpenButton_do, (Am_Object self))
{
cout << endl << "OpenButton_do() called" << endl << flush;
//make the input text field visible - get the ReadFile object and set its Am_VISIBLE flag
my_win.Get_Object(ReadFile).Set(Am_VISIBLE, true);
}

//Define callback function for ReadFile text inpuit field
Am_Define_Method(Am_Object_Method, void, ReadFile_do, (Am_Object self))
{
cout << endl << "ReadFile_do() called" << endl << flush;
//change OpenFileField text to entered filename
//get the ReadFile text input object and get its Am_VALUE
//Am_String InFileName = my_win.Get_Object(ReadFile).Get(Am_VALUE);
Am_String InFileName = self.Get(Am_VALUE); //equivalent to preceding commented line
//get the OpenFileField object and set its Am_Text value
my_win.Get_Object(OpenFileField).Set(Am_TEXT, InFileName);

//hide the text input box
my_win.Get_Object(ReadFile).Set(Am_VISIBLE, false);

//convert entered Am_String to string object
char* fstr = InFileName ;
string filestring(fstr);
cout << "Entered file name: " << filestring.c_str() << endl << flush;
}

void InitMenus (Am_Object& my_menu_bar);

int main (void)
{

Am_Initialize (); //Initialize Amulet


my_win = Am_Window.Create ("my_win") //Create an Amulet Window
.Set (Am_LEFT, 20)
.Set (Am_TOP, 50)
.Set (Am_WIDTH, 500)
.Set (Am_HEIGHT, 500)
.Set (Am_TITLE, "My Window");

//add the OpenFileLabel label & OpenFileField objects to the window
my_win.Add_Part(OpenFileLabel, Am_Text.Create("OpenFileLabel")
.Set(Am_LEFT, 175)
.Set(Am_TOP, 45)
.Set(Am_WIDTH, 42)
.Set(Am_HEIGHT, 14)
.Set(Am_TEXT, "File:")
.Set(Am_LINE_STYLE, Am_Black)
.Set(Am_FILL_STYLE, Am_No_Style)
)
.Add_Part(OpenFileField, Am_Text.Create("OpenFileField")
.Set(Am_LEFT, 225)
.Set(Am_TOP, 45)
.Set(Am_WIDTH, 119)
.Set(Am_HEIGHT, 14)
.Set(Am_TEXT, "* no open file *")
.Set(Am_LINE_STYLE, Am_Black)
.Set(Am_FILL_STYLE, Am_No_Style)
);

//create & add the OpenButton object to the window
my_win.Add_Part(OpenButton, Am_Button.Create("OpenButton")
.Set(Am_LEFT, 10)
.Set(Am_TOP, 37)
.Set(Am_WIDTH, 130)
.Set(Am_HEIGHT, 30)
.Set(Am_FILL_STYLE, Am_Motif_Gray)
.Get_Object(Am_COMMAND)
.Set(Am_LABEL, "Open File...")
.Set(Am_ACTIVE, true)
.Set(Am_DO_METHOD, OpenButton_do) //button callback function
.Get_Owner() //must identify button command object owner "OpenButton" when adding as a part
); //to my_win, otherwise Add_Part() will try & treat the owner as my_win

//create & add the ReadFile text input field widget object to the window
my_win.Add_Part(ReadFile, Am_Text_Input_Widget.Create("ReadFile")
.Set(Am_VALUE, "filename.bam") //set default value
.Set(Am_LEFT, 175)
.Set(Am_TOP, 100)
.Set(Am_WIDTH, 250)
.Set(Am_HEIGHT, 25)
.Set(Am_FILL_STYLE, Am_White)
// .Set(Am_WANT_PENDING_DELETE, true) //double mouse click selects entire string for replacement
.Set(Am_VISIBLE, false)
.Get_Object(Am_COMMAND)
.Set(Am_LABEL, "Enter Filename")
.Set(Am_DO_METHOD, ReadFile_do) //callback Fn for ReadFile text input - executes on return key
.Get_Owner()
)
// .Add_Part(Am_Tab_To_Next_Widget_Interactor.Create()) //allows tabbing between input fields - unnecessary
;

Am_Object my_menu_bar;

InitMenus (my_menu_bar);

my_win.Add_Part(my_menu_bar);

Am_Screen.Add_Part (my_win);

cout << endl << "Start Event Loop" << endl << flush ;

Am_Main_Event_Loop ();
Am_Cleanup ();

return 0;
}


void InitMenus (Am_Object& my_menu_bar)
{
my_menu_bar = Am_Menu_Bar.Create("my_menu_bar")
.Set(Am_FILL_STYLE, Am_Motif_Gray)
.Set(Am_ITEMS, Am_Value_List ()
.Add (Am_Command.Create("File_Command")
.Set(Am_LABEL, "File")
.Set(Am_IMPLEMENTATION_PARENT, true) //not undoable //File menu has no callback Fn
.Set(Am_ITEMS, Am_Value_List ()
.Add (Am_Quit_No_Ask_Command.Create() ) //Amulet Quit FN callback
)
)
) ;

} // InitMenus

 


Amulet Text Input Dialog Box Example

The following Amulet code creates an application with a text output field and label, a file menu with an open option, and a input text dialog box. The input text dialog box is activated from the open option callback function. The parameters for the dialog box are setup prior to the call. Following the dialog box call, the returned string is checked for a missing value which is returned when the user presses the cancel button. If a string has been entered it is converted to a string object that is displayed in the console and then the string object is assigned to the text output field.

The code demonstrates how to use the Amulet input text dialog box widget, and how to convert between Amulet Am_Strings, C-style srings and C++ object strings. Note that the dialog is setup as a Modal dialog. Modal dialogs prevent users from executing other application commands until the modal dialog has been answered. (If a non-modal dialog was instantiated the open option callback function would need to deactivate itself until the dialog was completed to prevent the user from accidentally opening multiple dialog boxes with possible weird results.)

Right click and choose "Save Target As..." to download the Amulet text input dialog box example code file.

 


#include "camulet.h" //use MSVC wrapper directives for use with standard namespace

//#include <iostream> //included by "console.h" and "am_io.h"
#include <fstream>
#include <iomanip>
#include <string>

//compile with amulet files: "console.cpp" & "console.h" for console output

using namespace std;

Am_Object my_win; //define window to be global so callback functions have access


//Define slot/part objects and register with amulet
Am_Slot_Key OpenFileLabel = Am_Register_Slot_Name ("OpenFileLabel");
Am_Slot_Key OpenFileField = Am_Register_Slot_Name ("OpenFileField");


//Define callback function for File menu Open option
Am_Define_Method(Am_Object_Method, void, my_open_do, (Am_Object self))
{
cout << endl << "my_open_do() called" << endl << flush;

//setup dialog box prompts
Am_Value_List prompts ;
prompts.Add("Please enter the name of an existing file.")
.Add("Enter the full path name, if the file is NOT in the current directory.")
.Add("(Be sure to enter the file extension)");

Am_String InFileName ; //define return value from input dialog

int xcoor = Am_AT_CENTER_SCREEN, ycoor = Am_AT_CENTER_SCREEN ; //input dialog location

//call Amulet input dialog box - see Amulet Manual pg. 289 - Dialog is Modal
InFileName = Am_Get_Input_From_Dialog(prompts, "filename.ext", xcoor, ycoor, true);

if (InFileName == Am_No_Value) //cancel button pressed
cout <<"No value entered"<<endl << flush;
else {
//convert entered Amulet string to string object
char* fstr = InFileName ;
string filestring(fstr);
cout << "Entered file name: " << filestring.c_str() << endl << flush;

//get the OpenFileField object and set its Am_Text value to the converted string object value
my_win.Get_Object(OpenFileField).Set(Am_TEXT, filestring.c_str());
}//else

}


void InitMenus (Am_Object& my_menu_bar);

int main (void)
{

Am_Initialize (); //Initialize Amulet


my_win = Am_Window.Create ("my_win") //Create an Amulet Window
.Set (Am_LEFT, 20)
.Set (Am_TOP, 50)
.Set (Am_WIDTH, 500)
.Set (Am_HEIGHT, 500)
.Set (Am_TITLE, "My Window");

//add the OpenFileLabel label & OpenFileField objects to the window
my_win.Add_Part(OpenFileLabel, Am_Text.Create("OpenFileLabel")
.Set(Am_LEFT, 175)
.Set(Am_TOP, 45)
.Set(Am_WIDTH, 42)
.Set(Am_HEIGHT, 14)
.Set(Am_TEXT, "File:")
.Set(Am_LINE_STYLE, Am_Black)
.Set(Am_FILL_STYLE, Am_No_Style)
)
.Add_Part(OpenFileField, Am_Text.Create("OpenFileField")
.Set(Am_LEFT, 225)
.Set(Am_TOP, 45)
.Set(Am_WIDTH, 119)
.Set(Am_HEIGHT, 14)
.Set(Am_TEXT, "* no open file *")
.Set(Am_LINE_STYLE, Am_Black)
.Set(Am_FILL_STYLE, Am_No_Style)
);


Am_Object my_menu_bar;

InitMenus (my_menu_bar);

my_win.Add_Part(my_menu_bar);

Am_Screen.Add_Part (my_win);

cout << endl << "Start Event Loop" << endl << flush ;

Am_Main_Event_Loop ();
Am_Cleanup ();

return 0;
}


void InitMenus (Am_Object& my_menu_bar)
{
my_menu_bar = Am_Menu_Bar.Create("my_menu_bar")
.Set(Am_FILL_STYLE, Am_Motif_Gray)
.Set(Am_ITEMS, Am_Value_List ()
.Add (Am_Command.Create("File_Command")
.Set(Am_LABEL, "File")
.Set(Am_IMPLEMENTATION_PARENT, true) //not undoable //File menu has no callback Fn
.Set(Am_ITEMS, Am_Value_List ()
.Add (Am_Command.Create("Open_Command")
.Set(Am_LABEL, "Open...")
.Set(Am_ACCELERATOR, "^o")
.Set(Am_ACTIVE, true)
.Set(Am_DO_METHOD, my_open_do)) //callback Fn for Open option
.Add (Am_Menu_Line_Command.Create("my menu line")) //menu spacer line
.Add (Am_Quit_No_Ask_Command.Create() ) //Amulet Quit FN callback
)
)
) ;

} // InitMenus


Amulet About Window Dialog Example

The following Amulet code creates an application with an about window containing an interactor object, and a file menu with About and Exit options. The about window is popped up when the application starts. The about window is displayed using the Amulet pop up window function which activates it as a modal dialog window and makes it visible. Modal dialogs prevent the user from doing anything else in the application until they have responded to the dialog, (although the user may still switch and work in other applications). The about window has an attached one-shot, (immediate event), interactor. The interactor has a command object that contains the associated callback function for the interactor. The interactor uses the Amulet default start event, (a left mouse click), to trigger execution of its command object callback function. The callback function calls the Amulet finish popup function which makes the about window invisible and halts execution of the suspended Amulet pop up window function whicg activated the about window.

In addition to the code demonstrating how to implement a modal dialog window, use the one shot interactor, and centering windows; the display of an image file is also implemented. An Amulet bitmap object is created and an Amulet image array is used to read in a MS Windows.bmp bitmap file and store it in the bitmap object. The full directory path to the bitmap file is created by using the Amulet merge pathname function to retrieve the path to the Amulet directory and concat the relative path to the bitmap file. The bitmap is added to the about window for display. (The Amulet image array objects and functions also include support for reading and displaying GIF files.)

Right click and choose "Save Target As..." to download the Amulet about window modal dialog example code file and right click again and choose "Save Target As..." to also download the Amulet AmAboutInt.bmp bitmap file, (the bitmap file must be stored in a BAM directory under the installed Amulet directory).


#include "camulet.h" //use MSVC wrapper directives for use with standard namespace

//#include <iostream> //included by "console.h" and "am_io.h"
#include <fstream>
#include <iomanip>
#include <string>



//compile with amulet files: "console.cpp" & "console.h" for console output

using namespace std;

Am_Object my_win, about_win; //define windows to be global so callback functions have access


//Define callback function for File menu About option
Am_Define_Method(Am_Object_Method, void, my_about_do, (Am_Object self))
{
cout << endl << "my_about_do() called" << endl << flush;

//pop up about window as modal & wait for user to left click on it
Am_Pop_Up_Window_And_Wait(about_win, Am_No_Value, true);
}

//Define callback function for about window interactor
Am_Define_Method(Am_Object_Method, void, about_win_do, (Am_Object self))
{
cout << endl << "about_win_do() called" << endl << flush;

//hide about window, complete execution of Am_Pop_Up_Window_And_Wait() & continue execution
Am_Finish_Pop_Up_Waiting(about_win, Am_No_Value);
}


void InitMenus (Am_Object& my_menu_bar);

int main (void)
{

Am_Initialize (); //Initialize Amulet


my_win = Am_Window.Create ("my_win") //Create an Amulet Window
.Set (Am_LEFT, Am_Center_X_Is_Center_Of) //Sets Upper left corner to the center of the Center X object
.Set (Am_TOP, Am_Center_Y_Is_Center_Of) //Sets Top location of window to the center of the Center Y object
.Add (Am_CENTER_X_OBJ, Am_Screen) //Adds a reference to the screen for left centering
.Add (Am_CENTER_Y_OBJ, Am_Screen) //Adds a reference to the screen for top centering
.Set (Am_WIDTH, 500)
.Set (Am_HEIGHT, 500)
.Set (Am_TITLE, "My Window");

about_win = Am_Window.Create ("about_win") //Create an Amulet Window
.Set(Am_DESTROY_WINDOW_METHOD, Am_Default_Pop_Up_Window_Destroy_Method)
.Set (Am_LEFT, Am_Center_X_Is_Center_Of) //Sets Upper left corner to the center of the Center X object
.Set (Am_TOP, Am_Center_Y_Is_Center_Of) //Sets Top location of window to the center of the Center Y object
.Add (Am_CENTER_X_OBJ, my_win) //Adds a reference to my_win for left centering
.Add (Am_CENTER_Y_OBJ, my_win) //Adds a reference to my_win for top centering
.Set (Am_FILL_STYLE, Am_Green)
.Set (Am_WIDTH, 300)
.Set (Am_HEIGHT, 300)
.Set (Am_TITLE, "About Window")
.Set (Am_VISIBLE, false);


//Define and setup bitmap to display
Am_Object bitmap;
bitmap = Am_Bitmap.Create("bitmap")
.Set (Am_LEFT, Am_Center_X_Is_Center_Of_Owner) //Center bitmap in window
.Set (Am_TOP , Am_Center_Y_Is_Center_Of_Owner);


about_win.Add_Part(bitmap);

//store file path to bitmap file: concat Amulet dir path with relative bitmap file path
//"AmAboutInt.bmp" should be stored in "D:\Amulet\BAM\AmAboutInt.bmp"
//Amulet converts Unix slashes to MS Win backslashes automatically
char* pathname = Am_Merge_Pathname("Bam/AmAboutInt.bmp");

Am_Image_Array image = Am_Image_Array(pathname); //input bitmap.bmp or file.gif image file
delete [] pathname; //get rid of path storage
bitmap.Set (Am_IMAGE, image); //store the image array in the amulet bitmap object

//create command for about window one shot interactor
Am_Object about_win_com = Am_Command.Create()
.Set (Am_DO_METHOD, about_win_do) ; //set callback function for command

//create mouse down interactor for about window
Am_Object about_win_inter = Am_One_Shot_Interactor.Create("about_win_inter")
// .Set(Am_START_WHEN, Am_Default_Start_Char) //default start char is left (mouse) down
.Set_Part(Am_COMMAND, about_win_com); //set interactor command object

about_win.Add_Part(about_win_inter); //add interactor to about window

Am_Object my_menu_bar;

InitMenus (my_menu_bar);

my_win.Add_Part(my_menu_bar);

//add windows to screen
Am_Screen.Add_Part (my_win);
Am_Screen.Add_Part (about_win);

cout << endl << "Start Event Loop" << endl << flush ;

//pop up about window as modal & wait for user to left click on it
Am_Pop_Up_Window_And_Wait(about_win, Am_No_Value, true);

Am_Main_Event_Loop ();
Am_Cleanup ();

return 0;
}


void InitMenus (Am_Object& my_menu_bar)
{
my_menu_bar = Am_Menu_Bar.Create("my_menu_bar")
.Set(Am_FILL_STYLE, Am_Motif_Gray)
.Set(Am_ITEMS, Am_Value_List ()
.Add (Am_Command.Create("File_Command")
.Set(Am_LABEL, "File")
.Set(Am_IMPLEMENTATION_PARENT, true) //not undoable //File menu has no callback Fn
.Set(Am_ITEMS, Am_Value_List ()
.Add (Am_Command.Create("About_Command")
.Set(Am_LABEL, "About")
.Set(Am_ACTIVE, true)
.Set(Am_DO_METHOD, my_about_do)) //callback Fn for About option
.Add (Am_Menu_Line_Command.Create("my menu line")) //menu spacer line
.Add (Am_Quit_No_Ask_Command.Create() ) //Amulet Quit FN callback
)
)
) ;

} // InitMenus

 

Amulet Menu Option Activation/Deactivation Example

The following Amulet code creates an application with one File menu with the usual options. Attached to a couple of the options are callback functions defined as Amulet methods using the Amulet Define Method macro. The callback functions do little except print out that they have been called. In addition, file menu option initialization formulas are defined, (using the Amulet Define Formula macro), to set the active status of the options and to store a reference to the object holding the option. These stored object references are later used in the callback functions to activate and deactivate the options appropriately. In this example, only the Open and Close options are activated and deactivated when the other callback function has executed.

Right click and choose "Save Target As..." to download the Amulet menu option activation/deactivation example code file.


#include "camulet.h" //use MSVC wrapper directives for use with standard namespace

//#include <iostream> //included by "console.h" and "am_io.h"
#include <fstream>
#include <iomanip>

#include <string>

//compile with amulet files: "console.cpp" & "console.h" for console output

using namespace std;

bool FileOpen = false ;

Am_Object my_win; //define window to be global so callback functions have access

Am_Object OpenOptionObject; //define amulet object to hold reference to File menu Open option object
Am_Object CloseOptionObject;//define amulet object to hold reference to File menu Close option object

//Define slot/part objects and register with amulet
Am_Slot_Key MenuBarSlot = Am_Register_Slot_Name ("MenuBarSlot");

//Define File menu Open option formula for initialization
Am_Define_Formula (bool, OpenOptionStatus) {
OpenOptionObject = self ; //store reference to File menu Open option object
return !FileOpen;
}

//Define File menu Close option formula for initialization
Am_Define_Formula (bool, CloseOptionStatus) {
CloseOptionObject = self; //store reference to File menu Close option object
return FileOpen;
}

//Define callback function for File menu Open... option
Am_Define_Method(Am_Object_Method, void, my_open_do, (Am_Object self))
{
cout << endl << "my_open_do() called" << endl << flush;
//call to driver() to open file

FileOpen = true ; //store Open option status
self.Set(Am_ACTIVE, false); //set self (i.e., File menu Open option) to inactive
CloseOptionObject.Set(Am_ACTIVE, true); //use stored reference to Close option to set it to active
}

//Define callback function for File menu Save As... option
Am_Define_Method(Am_Object_Method, void, my_saveas_do, (Am_Object self))
{
cout << endl << "my_saveas_do() called" << endl << flush;
}

//Define callback function for File menu Close option
Am_Define_Method(Am_Object_Method, void, my_close_do, (Am_Object self))
{
cout << endl << "my_close_do() called" << endl << flush;
//call to driver() to close file
FileOpen = false; //store Open option status
self.Set(Am_ACTIVE, false); //set self (i.e., File menu Close option) to inactive
OpenOptionObject.Set(Am_ACTIVE, true); //use stored reference to Open option to set it to active
}

void InitMenus (Am_Object& my_menu_bar);


int main (void)
{

Am_Initialize (); //Initialize Amulet

//Create an Amulet Window
my_win = Am_Window.Create ("my_win")
.Set (Am_LEFT, 20)
.Set (Am_TOP, 50)
.Set (Am_WIDTH, 500)
.Set (Am_HEIGHT, 500)
.Set (Am_TITLE, "My Window");

Am_Object my_menu_bar;

InitMenus (my_menu_bar);

my_win.Add_Part(MenuBarSlot, my_menu_bar);

Am_Screen.Add_Part (my_win);


Am_Main_Event_Loop ();
Am_Cleanup ();

return 0;
}


void InitMenus (Am_Object& my_menu_bar)
{
my_menu_bar = Am_Menu_Bar.Create("my_menu_bar")
.Set(Am_FILL_STYLE, Am_Motif_Gray)
.Set(Am_ITEMS, Am_Value_List ()
.Add (Am_Command.Create("File_Command")
.Set(Am_LABEL, "File")
.Set(Am_IMPLEMENTATION_PARENT, true) //not undoable //File menu has no callback Fn
.Set(Am_ITEMS, Am_Value_List ()
.Add (Am_Command.Create("New_Command")
.Set(Am_LABEL, "New...")
.Set(Am_ACCELERATOR, "^n")
.Set(Am_ACTIVE, false)
.Set(Am_IMPLEMENTATION_PARENT, true) ) //not undoable //New option has no callback Fn
.Add (Am_Command.Create("Open_Command")
.Set(Am_LABEL, "Open...")
.Set(Am_ACCELERATOR, "^o")
.Set(Am_ACTIVE, OpenOptionStatus) //call Open option fomula to initialize
.Set(Am_DO_METHOD, my_open_do)) //callback Fn for Open option
.Add (Am_Menu_Line_Command.Create("my menu line")) //menu spacer line
.Add (Am_Command.Create("Save_Command")
.Set(Am_LABEL, "Save")
.Set(Am_ACCELERATOR, "^s")
.Set(Am_ACTIVE, false)
.Set(Am_IMPLEMENTATION_PARENT, true) ) //not undoable //Save option has no callback Fn
.Add (Am_Command.Create("Save_As_Command")
.Set(Am_LABEL, "Save As...")
.Set(Am_ACCELERATOR, "^a")
.Set(Am_ACTIVE, false)
.Set(Am_DO_METHOD, my_saveas_do)) //callback Fn for Save As... option
.Add (Am_Command.Create("Close_Command")
.Set(Am_LABEL, "Close")
.Set(Am_ACCELERATOR, "^w")
.Set(Am_ACTIVE, CloseOptionStatus) //call Close option fomula to initialize
.Set(Am_DO_METHOD, my_close_do)) //callback Fn for Close option
.Add (Am_Menu_Line_Command.Create("my menu line")) //menu spacer line
.Add (Am_Quit_No_Ask_Command.Create() ) //Amulet Quit FN callback
)
)
) ;

} // InitMenus

Amulet Dynamic Menu Content Code Example

The following Amulet code creates a standard window with three menus -- File, Navigate, and Document. The File menu contains the standard options, the Navigate menu is empty, and the Document menu's contents change as the program executed. When the Open option in the File menu is first selected, an option named "Document 1" is created in the Document menu. The second time the Open option is selected, "Document 2" is added to the Document menu, and so on. When the Close option is selected from the File menu, the document with the lowest number is removed from the Document menu.

This code was created by simply adding a few things to the myappmenu.cpp code listed above. The added code is surrounded by comments that contain BEGIN/END ADDED STUFF.

This code relies on functions to send an Am_Value_List to the Document menu. This list contains all of the command objects that the menu contains, and is updated dynamically when the callbacks for the Open and Close options are called. Each option sets the value of the Document menu's Am_OBJECT_MODIFIED slot to true; this forces the formula (which is set up to depend on that value) to push the modified list of commands to the Document menu.

Right click and choose "Save Target As..." to download the Amulet dynamic menu options example code file.


/**********
This file started out as the myappmenu.cpp file that was given as an
example earlier. A few modifications have been made so that the open
and close options will dynamically add and remove (respectively) things
to/from the Document menu. Any additions that were made to the initial
code are surrounded by comments: BEGIN/END ADDED STUFF. Other than the
code between such comments, the source should be identical to the
original code found in myappmenu.cpp. - JPV 7/22/99
**********/
#include

#include

//compile with amulet files: "console.cpp" & "console.h" for console output
/*** BEGIN ADDED STUFF ***/

// open_counter and close_counter just let us use a sequence of numbers
// in the names of the files we "open" and "close".

int open_counter = 1; // Counts how many times we've chosen the Open menu option
int close_counter = 1; // Counts how many times we've chosen the Close menu option

Am_Object DocumentMenuCommand;

// DocumentList stores all of the menu options that will go in the Document menu

Am_Value_List DocumentList = Am_Value_List();

Am_Define_Value_List_Formula (DocumentFormula)
{
// We need this formula to access the value of DocumentMenuCommand's slot
// named Am_OBJECT_MODIFIED so that the formula will become dependent
// on that slot value and will recompute itself when the value changes.
// We never really _use_ the value -- we just depend on it.

bool foo = DocumentMenuCommand.Get(Am_OBJECT_MODIFIED);

// If the DocumentList has been updated, DocumentMenuCommand's slot
// named Am_OBJECT_MODIFIED will have been set by us to true to let
// us know of the modification. We can now reset it and return the
// new value of the modified DocumentList.

if (foo == true)
DocumentMenuCommand.Set(Am_OBJECT_MODIFIED, false);

return DocumentList;
}

// The my_document_do callback is called when we choose something from the
// Document menu; that's the way we set it up for each item we add to
// the menu when we open a file

Am_Define_Method(Am_Object_Method, void, my_document_do, (Am_Object self))
{
Am_String document_chosen;

// Print out the label from the command that was chosen

document_chosen = self.Get(Am_LABEL);
cout << document_chosen << " chosen from Document menu" << endl;
}


/*** END ADDED STUFF ***/


//Define callback function for File menu Open... option
Am_Define_Method(Am_Object_Method, void, my_open_do, (Am_Object self))
{
cout << endl << "my_open_do() called" << endl << flush;
/*** BEGIN ADDED STUFF ***/

// Make up a name for the file we "open" (we're faking the opening of
// a file here -- this would be replaced by a real name).

char *buffer = new char[16];

sprintf(buffer, "Document %d", open_counter++);

// Go to the end of the DocumentList and add a new command to it

DocumentList.End();

DocumentList.Add(Am_Command.Create(buffer)

.Set(Am_LABEL, buffer)

.Set(Am_ACTIVE, true)

.Set(Am_DO_METHOD, my_document_do));

// Let the DocumentMenuCommand know that DocumentList was modified

DocumentMenuCommand.Set(Am_OBJECT_MODIFIED, true);

/*** END ADDED STUFF ***/

}

//Define callback function for File menu Save As... option
Am_Define_Method(Am_Object_Method, void, my_saveas_do, (Am_Object self))
{
cout << endl << "my_saveas_do() called" << endl << flush;
}

//Define callback function for File menu Close option
Am_Define_Method(Am_Object_Method, void, my_close_do, (Am_Object self))
{
cout << endl << "my_close_do() called" << endl << flush;
/*** BEGIN ADDED STUFF ***/

// Create a character array that contains the name of the document to delete
// Again, this is a pseudo-name, just like open.

char *buffer = new char[16];

// We want to make sure that we've actually opened more files than we've closed

if (close_counter >= open_counter)
{
cout << "No documents to be closed" << endl;
}
else
{
sprintf(buffer, "Document %d", close_counter++);
cout << buffer << " to be deleted" << endl;

// Look through the commands in the DocumentList to see which one has the
// label stored in buffer; when found, delete it

for (DocumentList.Start(); !DocumentList.Last(); DocumentList.Next())
{
Am_Object list_item = DocumentList.Get();

if (list_item.Get(Am_LABEL) == buffer)
{
DocumentList.Delete();

// Signal that the DocumentList was updated. This will trigger
// the recomputation of the DocumentList's formula so that it
// will recompute its contents and provide the newly modified
// list to the Document menu.

DocumentMenuCommand.Set(Am_OBJECT_MODIFIED, true);
}
}
}
/*** END ADDED STUFF ***/

}

void InitMenus (Am_Object& my_menu_bar);


int main (void)
{

Am_Initialize (); //Initialize Amulet

//Create an Amulet Window
Am_Object my_win = Am_Window.Create ("my_win")
.Set (Am_LEFT, 20)
.Set (Am_TOP, 50)
.Set (Am_WIDTH, 500)
.Set (Am_HEIGHT, 500)
.Set (Am_TITLE, "My Window");

Am_Object my_menu_bar;

InitMenus (my_menu_bar);

my_win.Add_Part(my_menu_bar);

Am_Screen.Add_Part (my_win);


Am_Main_Event_Loop ();
Am_Cleanup ();

return 0;
}


void InitMenus (Am_Object& my_menu_bar)
{
my_menu_bar = Am_Menu_Bar.Create("my_menu_bar")
.Set(Am_FILL_STYLE, Am_Motif_Gray)
.Set(Am_ITEMS, Am_Value_List ()
.Add (Am_Command.Create("File_Command")
.Set(Am_LABEL, "File")
.Set(Am_IMPLEMENTATION_PARENT, true) //not undoable //File menu has no callback Fn
.Set(Am_ITEMS, Am_Value_List ()
.Add (Am_Command.Create("New_Command")
.Set(Am_LABEL, "New...")
.Set(Am_ACCELERATOR, "^n")
.Set(Am_ACTIVE, false)
.Set(Am_IMPLEMENTATION_PARENT, true) ) //not undoable //New option has no callback Fn
.Add (Am_Command.Create("Open_Command")
.Set(Am_LABEL, "Open...")
.Set(Am_ACCELERATOR, "^o")
.Set(Am_ACTIVE, true)
.Set(Am_DO_METHOD, my_open_do)) //callback Fn for Open option
.Add (Am_Menu_Line_Command.Create("my menu line")) //menu spacer line
.Add (Am_Command.Create("Save_Command")
.Set(Am_LABEL, "Save")
.Set(Am_ACCELERATOR, "^s")
.Set(Am_ACTIVE, false)
.Set(Am_IMPLEMENTATION_PARENT, true) ) //not undoable //Save option has no callback Fn
.Add (Am_Command.Create("Save_As_Command")
.Set(Am_LABEL, "Save As...")
.Set(Am_ACCELERATOR, "^a")
.Set(Am_DO_METHOD, my_saveas_do)) //callback Fn for Save As... option
.Add (Am_Command.Create("Close_Command")
.Set(Am_LABEL, "Close")
.Set(Am_ACCELERATOR, "^w")
.Set(Am_DO_METHOD, my_close_do)) //callback Fn for Close option
.Add (Am_Menu_Line_Command.Create("my menu line")) //menu spacer line
.Add (Am_Quit_No_Ask_Command.Create() ) //Amulet Quit FN callback
)
)
/*** BEGIN ADDED STUFF ***/

.Add (Am_Command.Create("Navigate_Command")

.Set(Am_LABEL, "Navigate")

.Set(Am_IMPLEMENTATION_PARENT, true) //not undoable //File menu has no callback Fn

)

.Add (DocumentMenuCommand = Am_Command.Create("Document_Command")

.Set(Am_LABEL, "Document")

.Set(Am_IMPLEMENTATION_PARENT, true) //not undoable //File menu has no callback Fn

// The Document menu's contents come from a formula that we defined
// that returns the contents of the Am_Value_List DocumentList.
// The DocumentMenuCommand (that was assigned just above) will have its
// Am_OBJECT_MODIFIED slot adjusted when a new item is added. This will
// trigger the formula to feed us the modified DocumentList.

.Set(Am_ITEMS, DocumentFormula)

)

/*** END ADDED STUFF ***/

) ;

} // InitMenus

D. Barnette 4/25/99, P. Van Metre 7/22/99 Virginia Tech © 1995-1999