\ io \ \ io_menus \ menu bar for the turnkeyed io. \ \ \ note: the menu items are for the turnkeyed io, and requires the necessary \ resource file to be included. This component is only loaded if the constant \ io_turnkey? (from the file io_config) is set to true. \ \ \ see the file io_top for more information. \ \ \ constructor: Han-earl Park \ copyright 2008 buster & friends' C-ALTO Labs \ \ www.busterandfriends.com/io \ \ (Edinburgh, November 1996 - \ (London, August 1997 - \ (Den Haag, October 1997 - \ (Valencia, March 1999 - \ (Southampton, May 2000 - \ (Cork, April 2006 - \ \ (Cork, October 2008 - \ \ REV: 0.0.1 alpha (Southampton, October 2000) \ REV: 0.0.1 beta (Southampton, November 2000) \ REV: 0.0.1 alpha++ (Southampton, July 2004) \ REV: 0.0.1 beta++ (Cork, May 2010) \ \ \ MOD: HeP 09/19/00 Spin off modules:io_menus from io_screen. This results in \ redesign of how the screen menu is updated. The menu \ control code is now called from io_top. \ MOD: HeP 09/20/00 Trash the "Default..." menu item. \ REV: 0.0.1 alpha __________________________________________________________ \ MOD: HeP 11/01/00 Only enable file items if io_file? is true. \ MOD: HeP 11/22/00 Change commands key for screen menu to ascii 1 and 2 in \ order to avoid conflicts with the midi menu (see file \ myt:midi_menu). \ REV: 0.0.1 beta __________________________________________________________ \ MOD: HeP 06/24/01 Minor revision of the (unused) file menu. \ MOD: HeP 04-13-04 File menu has three states depending on the file \ save/unsaved and the play/idle state. \ MOD: HeP 04-13-04 Defer SCREEN.CHANGED if io_file? is true. \ MOD: HeP 04-14-04 Get rid of "New" file menu item. \ Add SAVED.CHANGE. \ MOD: HeP 04-15-04 Redesign menu bar (again). \ Use GetMenu() with the resource based scenes menu. \ MOD: HeP 05-01-04 Move all includes (and conditional includes) from the \ individual files to load_io. \ MOD: HeP 05-03-04 Add SELECT.SCENE, NEXT.SCENE and PREV.SCENE. (I hope this \ is not the start of io getting hopelessly complicated.) \ MOD: HeP 05-12-04 Add DelMenuItem() which is not defined in h4th. \ MOD: HeP 05-13-04 Implement file and scenes menu item enabling/disabling. \ MOD: HeP 05-14-04 Add InsMenuItem(). \ Add ADD.SCENE and DELETE.SCENE. \ New scenes get inserted at the current rather than being \ adding to the end of the list. \ MOD: HeP 05-16-04 Fix file menu bug that occured when close was called in \ succession. Source of bug was IO.PRINT.FILE.INFO (in \ modules:io_file) which PRINT:ed objects. This action calls \ ?terminal (?pause) which could initiate a menu action. Bug \ only operates when io_test? is true. \ Modify words that track file save state (SAVED.CHANGE, \ etc) to use OB.IO.SCENE's save state. \ MOD: HeP 05-17-04 Fix bug that set UNSAVED.CHANGES? to true when switching \ scenes. See io_screen and modules:io_file_glue. \ MOD: HeP 05-24-04 Remove multiple (hidden) calls to DrawMenuBar(). We call \ DrawMenuBar() at during init and term. \ "Revert" is only available if the scene is on disk. \ MOD: HeP 05-25-04 Update item name in scenes submenu after renaming a file \ via "Save" or "Save As". \ Update file and scene menus depending on current scene's \ save state and number of scenes loaded into memory. \ MOD: HeP 07-01-04 Simplify this code by have the file menu updated after \ _every_ file action by having the menu component query the file/scene \ file component's state. Done by calling IO.FILE.MENU.DRAW \ at the end of IO.FILE.MENU.FUNC regardless of menu action. \ REV: 0.0.1 a ++ __________________________________________________________ \ REV: 0.0.1 b ++ __________________________________________________________ \ Version for performance at Blackrock Castle Observatory, \ Cork, Ireland, May 25, 2010. anew task-io_menus \ additional mac system calls .NEED InsMenuItem() : InsMenuItem() ( MenuHandle $item item# -- , insert a menu item ) pass: 442 trap: a826 ; .THEN .NEED DelMenuItem() : DelMenuItem() ( MenuHandle item# -- , delete a menu item ) pass: 42 trap: a952 ; .THEN .NEED SetMenuItemText() : SetMenuItemText() ( MenuHandle item# -- , delete a menu item ) ; .THEN \ menu resource id# 129 constant file_menu_id 130 constant edit_menu_id 131 constant window_menu_id 132 constant scenes_menu_id \ menu handles variable file-menu-handle variable edit-menu-handle variable window-menu-handle variable scenes-menu-handle \ file menu items 1 constant new_menu_item 2 constant open_menu_item \ ---------------------- 4 constant close_menu_item 5 constant save_menu_item 6 constant save_as_menu_item 7 constant revert_menu_item \ ---------------------- 9 constant scenes_menu_item \ scenes submenu 10 constant previous_menu_item 11 constant next_menu_item \ ---------------------- 13 constant make_default_menu_item \ ---------------------- 15 constant quit_menu_item \ file menu - disable & enable items io_file? .IF : IO.SCENES.MENU.ENABLE ( -- ) file-menu-handle @ dup scenes_menu_item EnableItem() dup previous_menu_item EnableItem() next_menu_item EnableItem() ; : IO.SCENES.MENU.DISABLE ( -- ) file-menu-handle @ dup scenes_menu_item DisableItem() dup previous_menu_item DisableItem() next_menu_item DisableItem() ; : IO.SCENES.MENU.DRAW ( -- ) #scenes@ 1 > IF io.scenes.menu.enable ELSE io.scenes.menu.disable THEN ; : IO.FILE.MENU.CLOSE.DRAW ( -- , enable if there are scenes to close ) file-menu-handle @ close_menu_item \ #scenes@ IF EnableItem() ELSE DisableItem() THEN ; : IO.FILE.MENU.SAVE.DRAW ( -- , enable if file is not saved ) file-menu-handle @ save_menu_item \ unsaved? IF EnableItem() ELSE DisableItem() THEN ; : IO.FILE.MENU.REVERT.DRAW ( -- , enable if file is on disk ) file-menu-handle @ revert_menu_item \ unsaved? \ not saved to disk? IF DisableItem() ELSE EnableItem() THEN ; : IO.FILE.MENU.SAVED ( -- , default state of the file menu ) file-menu-handle @ dup new_menu_item EnableItem() dup open_menu_item EnableItem() \ io.file.menu.save.draw \ io.file.menu.close.draw \ dup save_as_menu_item EnableItem() dup revert_menu_item DisableItem() \ dup make_default_menu_item EnableItem() quit_menu_item EnableItem() \ io.scenes.menu.draw ; : IO.FILE.MENU.UNSAVED ( -- , menu after unsaved changes are made ) file-menu-handle @ dup new_menu_item EnableItem() dup open_menu_item EnableItem() dup save_menu_item EnableItem() \ save enabled \ io.file.menu.close.draw \ dup save_as_menu_item EnableItem() \ io.file.menu.revert.draw \ dup make_default_menu_item EnableItem() quit_menu_item EnableItem() \ io.scenes.menu.draw ; : IO.FILE.MENU.DRAW ( -- ) unsaved.change? IF io.file.menu.unsaved ELSE io.file.menu.saved THEN ; : IO.FILE.MENU.PLAY ( -- , during play ) file-menu-handle @ dup new_menu_item DisableItem() dup open_menu_item DisableItem() dup save_menu_item DisableItem() dup close_menu_item DisableItem() dup save_as_menu_item DisableItem() dup revert_menu_item DisableItem() \ dup make_default_menu_item DisableItem() quit_menu_item EnableItem() \ io.scenes.menu.disable ; : IO.FILE.MENU.IDLE ( -- ) io.file.menu.draw ; .ELSE : IO.FILE.MENU.PLAY ( -- ) ; : IO.FILE.MENU.IDLE ( -- ) ; .THEN \ disable & enable items depending on io's state : IO.MENUS.PLAY ( -- ) io.file.menu.play \ window-menu-handle @ 1 DisableItem() ; : IO.MENUS.IDLE ( -- ) io.file.menu.idle \ window-menu-handle @ 1 EnableItem() ; \ keep track of changes \ \ the following correspond to the deferred words declared in io_glob and \ configured in io_top. io_file? .IF : (UNSAVED.CHANGE) ( -- ) (unsaved.change) io.file.menu.unsaved ; : (SAVED.CHANGE) ( -- ) (saved.change) io.file.menu.saved ; : (UNSAVED.CHANGE?) ( -- flag ) (unsaved.change?) ; .THEN \ settings for the midi dialog boxes : IO.MENUS.ON ( -- , enable all except Edit menu ) applemenuh @ 0 EnableItem() file-menu-handle @ 0 EnableItem() window-menu-handle @ 0 EnableItem() midi-menu-handle @ 0 EnableItem() ; : IO.MENUS.OFF ( -- , disable all except Edit menu ) applemenuh @ 0 DisableItem() file-menu-handle @ 0 DisableItem() window-menu-handle @ 0 DisableItem() midi-menu-handle @ 0 DisableItem() ; \ scenes io_file? .IF \ the following correspond to the deferred words declared in io_glob and \ configured in io_top. Here we redefined the words from io_file. variable scene-menu-checked# : (SELECT.SCENE) ( indx -- ) scenes-menu-handle @ scene-menu-checked# @ FALSE checkItem() \ dup (select.scene) 1+ scenes-menu-handle @ over TRUE checkItem() scene-menu-checked# ! \ io.file.menu.draw ; : (PREV.SCENE) ( -- ) scenes-menu-handle @ scene-menu-checked# @ FALSE checkItem() \ (prev.scene) \ current-scene-indx @ 1+ scenes-menu-handle @ over TRUE checkItem() scene-menu-checked# ! \ io.file.menu.draw ; : (NEXT.SCENE) ( -- ) scenes-menu-handle @ scene-menu-checked# @ FALSE checkItem() \ (next.scene) \ current-scene-indx @ 1+ scenes-menu-handle @ over TRUE checkItem() scene-menu-checked# ! \ io.file.menu.draw ; : (ADD.SCENE) ( -- , add item to submenu ) scenes-menu-handle @ scene-menu-checked# @ FALSE checkItem() \ scenes-menu-handle @ current-scene-indx @ scene.name current-scene-indx @ InsMenuItem() \ current-scene-indx @ 1+ scenes-menu-handle @ over TRUE checkItem() scene-menu-checked# ! \ io.scenes.menu.draw ; : (DELETE.SCENE) ( -- , delete item from submenu ) scenes-menu-handle @ scene-menu-checked# @ FALSE checkItem() \ scenes-menu-handle @ current-scene-indx @ 1+ DelMenuItem() \ current-scene-indx @ 1+ scenes-menu-handle @ over TRUE checkItem() scene-menu-checked# ! \ io.scenes.menu.draw ; : UPDATE.SCENE.NAME ( -- , update name after a save as command ) scenes-menu-handle @ current-scene-indx @ 1+ DelMenuItem() \ scenes-menu-handle @ current-scene-indx @ scene.name current-scene-indx @ InsMenuItem() \ current-scene-indx @ 1+ scenes-menu-handle @ over TRUE checkItem() scene-menu-checked# ! ; .THEN \ file menu function io_file? .IF : IO.FILE.MENU.FUNC ( -- ) which-part @ 15 AND CASE new_menu_item OF io.file.new ENDOF open_menu_item OF io.file.open ENDOF \ close_menu_item OF io.file.close ENDOF save_menu_item OF io.file.save update.scene.name ENDOF save_as_menu_item OF io.file.save.as update.scene.name ENDOF revert_menu_item OF io.file.revert ENDOF \ previous_menu_item OF prev.scene ENDOF next_menu_item OF next.scene ENDOF \ make_default_menu_item OF io.file.make.default ENDOF \ quit_menu_item OF io.file.quit ENDOF ENDCASE \ io.file.menu.draw \ MOD: 07-01-04 ; .ELSE : IO.FILE.MENU.FUNC ( -- ) which-part @ 15 AND quit_menu_item = IF true quit-hmsl ! THEN ; .THEN io_file? io_test? AND .IF \ recursive bug: if io_test? is true, objects sometimes get printed during \ a menu action. This in turn calls ?terminal (?pause) which may initiate \ another menu action causing the two processes to interfere with one \ another. So, let's set a flag to stop this recursion from happening. variable file-menu-busy? : IO.FILE.MENU.FUNC ( -- ) file-menu-busy? @ NOT IF true file-menu-busy? ! \ io.file.menu.func \ false file-menu-busy? ! THEN ; .THEN \ edit menu function : IO.EDIT.MENU.FUNC ( -- , stub ) ; \ window menu function : (DRAW.CONFIG.SCREEN) ( -- ) draw: config-screen config.qwerty.help ; : (DRAW.PERF.SCREEN) ( -- ) draw: perf-screen ui.qwerty.help ; : DRAW.CONFIG.SCREEN ( -- ) cg-current-screen @ ?dup IF config-screen = NOT IF cg-current-screen @ undraw: [] (draw.config.screen) THEN ELSE (draw.config.screen) THEN hmsl-window @ SelectWindow() ; : DRAW.PERF.SCREEN ( -- ) cg-current-screen @ ?dup IF perf-screen = NOT IF cg-current-screen @ undraw: [] (draw.perf.screen) THEN ELSE (draw.perf.screen) THEN hmsl-window @ SelectWindow() ; : IO.WINDOW.MENU.FUNC ( -- ) which-part @ 15 AND CASE 1 OF draw.config.screen ENDOF 2 OF draw.perf.screen ENDOF \ --------------------------- 4 OF main_window SelectWindow() ENDOF ENDCASE ; \ scenes submenu function io_file? .IF \ all h4th code and documentation use "which-part @ 15 AND" to get the \ first 15 menu items. I don't see why you should have this limitation \ if, as I suspect is the case, which-part corresponds to the 4 byte \ value returned by the Mac menu manager in which the lower 16 bits \ correspond to the menu item number. : IO.SCENES.MENU.FUNC ( -- ) which-part @ $ ffff AND 1- select.scene \ io.file.menu.draw ; .ELSE : IO.SCENES.MENU.FUNC ( -- , stub ) ; .THEN \ system control : IO.MENUS.DEFAULT ( -- ) io.file.menu.idle ; : IO.MENUS.RESET ( -- ) [ io_test? .IF ] tab ." IO.MENUS.RESET" cr [ .THEN ] ; : IO.MENUS.UPDATE ( -- ) ; : IO.MENUS.PANIC ( -- ) ; : IO.MENUS.STANDBY ( -- ) (midi.menu.play) io.menus.play ; : IO.MENUS.START ( -- ) ; : MENUS.IMBNF ( -- , it must be nearly finished ) ; : IO.MENUS.STOP ( -- ) (midi.menu.idle) io.menus.idle ; : IO.MENUS.PAUSE ( -- ) (midi.menu.idle) io.menus.idle ; : IO.MENUS.RESUME ( -- ) (midi.menu.play) io.menus.play ; \ setup & clearup : IO.MENUS.INIT ( -- ) [ io_test? .IF ] tab ." IO.MENUS.INIT" cr [ .THEN ] \ [ io_file? io_test? AND .IF ] false file-menu-busy? ! [ .THEN ] \ midi.menu.init (midi.menu.on) (draw.midi.menu) 'c IO.MENUS.OFF is MTDLOG.START 'c IO.MENUS.ON is MTDLOG.STOP \ \ automatically loaded by H4th... \ file_menu_id GetMHandle() file-menu-handle ! edit_menu_id GetMHandle() edit-menu-handle ! window_menu_id GetMHandle() window-menu-handle ! \ \ not loaded by H4th... \ scenes_menu_id GetMenu() scenes-menu-handle ! \ 'c io.file.menu.func file_menu_id ev.menu.func! 'c io.edit.menu.func edit_menu_id ev.menu.func! 'c io.window.menu.func window_menu_id ev.menu.func! 'c io.scenes.menu.func scenes_menu_id ev.menu.func! \ scenes-menu-handle @ -1 InsertMenu() \ 'c noop is DRAW.HMSL.MENUS \ unused 'c noop is UNDRAW.HMSL.MENUS \ unused \ \ io.menus.default \ removed MOD: 07-03-04 \ DrawMenuBar() ; : IO.MENUS.TERM ( -- ) [ io_test? .IF ] tab ." IO.MENUS.TERM" cr [ .THEN ] \ scenes-menu-handle @ IF scenes_menu_id DeleteMenu() scenes-menu-handle @ DisposeMenu() 0 scenes-menu-handle ! THEN \ midi.menu.term ; if.forgotten io.menus.term