/********** 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