trunk/src/emu/inpttype.h
| r29577 | r29578 | |
| 709 | 709 | INPUT_PORT_DIGITAL_TYPE( 0, OTHER, KEYBOARD, "Keyboard", input_seq() ) |
| 710 | 710 | } |
| 711 | 711 | |
| 712 | | void construct_core_types_UI(simple_list<input_type_entry> &typelist) |
| 712 | void construct_core_types_ui_general(simple_list<input_type_entry> &typelist) |
| 713 | 713 | { |
| 714 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ON_SCREEN_DISPLAY,"On Screen Display", input_seq(KEYCODE_TILDE) ) |
| 715 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_DEBUG_BREAK, "Break in Debugger", input_seq(KEYCODE_TILDE) ) |
| 716 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_CONFIGURE, "Config Menu", input_seq(KEYCODE_TAB) ) |
| 717 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAUSE, "Pause", input_seq(KEYCODE_P) ) |
| 718 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_RESET_MACHINE, "Reset Game", input_seq(KEYCODE_F3, KEYCODE_LSHIFT) ) |
| 719 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SOFT_RESET, "Soft Reset", input_seq(KEYCODE_F3, input_seq::not_code, KEYCODE_LSHIFT) ) |
| 720 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SHOW_GFX, "Show Gfx", input_seq(KEYCODE_F4) ) |
| 721 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FRAMESKIP_DEC, "Frameskip Dec", input_seq(KEYCODE_F8) ) |
| 722 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FRAMESKIP_INC, "Frameskip Inc", input_seq(KEYCODE_F9) ) |
| 723 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_THROTTLE, "Throttle", input_seq(KEYCODE_F10) ) |
| 724 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_FAST_FORWARD, "Fast Forward", input_seq(KEYCODE_INSERT) ) |
| 725 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SHOW_FPS, "Show FPS", input_seq(KEYCODE_F11, input_seq::not_code, KEYCODE_LSHIFT) ) |
| 726 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SNAPSHOT, "Save Snapshot", input_seq(KEYCODE_F12, input_seq::not_code, KEYCODE_LSHIFT) ) |
| 727 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_RECORD_MOVIE, "Record Movie", input_seq(KEYCODE_F12, KEYCODE_LSHIFT) ) |
| 728 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_TOGGLE_CHEAT, "Toggle Cheat", input_seq(KEYCODE_F6) ) |
| 729 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_UP, "UI Up", input_seq(KEYCODE_UP, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(0)) ) |
| 730 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_DOWN, "UI Down", input_seq(KEYCODE_DOWN, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(0)) ) |
| 731 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_LEFT, "UI Left", input_seq(KEYCODE_LEFT, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(0)) ) |
| 732 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_RIGHT, "UI Right", input_seq(KEYCODE_RIGHT, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(0)) ) |
| 733 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_HOME, "UI Home", input_seq(KEYCODE_HOME) ) |
| 734 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_END, "UI End", input_seq(KEYCODE_END) ) |
| 735 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAGE_UP, "UI Page Up", input_seq(KEYCODE_PGUP) ) |
| 736 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PAGE_DOWN, "UI Page Down", input_seq(KEYCODE_PGDN) ) |
| 737 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SELECT, "UI Select", input_seq(KEYCODE_ENTER, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(0)) ) |
| 738 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_CANCEL, "UI Cancel", input_seq(KEYCODE_ESC) ) |
| 739 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_DISPLAY_COMMENT, "UI Display Comment", input_seq(KEYCODE_SPACE) ) |
| 740 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_CLEAR, "UI Clear", input_seq(KEYCODE_DEL) ) |
| 741 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ZOOM_IN, "UI Zoom In", input_seq(KEYCODE_EQUALS) ) |
| 742 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ZOOM_OUT, "UI Zoom Out", input_seq(KEYCODE_MINUS) ) |
| 743 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PREV_GROUP, "UI Previous Group", input_seq(KEYCODE_OPENBRACE) ) |
| 744 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_NEXT_GROUP, "UI Next Group", input_seq(KEYCODE_CLOSEBRACE) ) |
| 745 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ROTATE, "UI Rotate", input_seq(KEYCODE_R) ) |
| 746 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SHOW_PROFILER, "Show Profiler", input_seq(KEYCODE_F11, KEYCODE_LSHIFT) ) |
| 747 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_TOGGLE_UI, "UI Toggle", input_seq(KEYCODE_SCRLOCK, input_seq::not_code, KEYCODE_LSHIFT) ) |
| 748 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PASTE, "UI Paste Text", input_seq(KEYCODE_SCRLOCK, KEYCODE_LSHIFT) ) |
| 749 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_TOGGLE_DEBUG, "Toggle Debugger", input_seq(KEYCODE_F5) ) |
| 750 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_SAVE_STATE, "Save State", input_seq(KEYCODE_F7, KEYCODE_LSHIFT) ) |
| 751 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_LOAD_STATE, "Load State", input_seq(KEYCODE_F7, input_seq::not_code, KEYCODE_LSHIFT) ) |
| 714 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, UI_CONFIGURE, "Config Menu", input_seq(KEYCODE_TAB, input_seq::or_code, KEYCODE_SCRLOCK) ) |
| 715 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, UI_UP, "UI Up", input_seq(KEYCODE_UP, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(0)) ) |
| 716 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, UI_DOWN, "UI Down", input_seq(KEYCODE_DOWN, input_seq::or_code, JOYCODE_Y_DOWN_SWITCH_INDEXED(0)) ) |
| 717 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, UI_LEFT, "UI Left", input_seq(KEYCODE_LEFT, input_seq::or_code, JOYCODE_X_LEFT_SWITCH_INDEXED(0)) ) |
| 718 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, UI_RIGHT, "UI Right", input_seq(KEYCODE_RIGHT, input_seq::or_code, JOYCODE_X_RIGHT_SWITCH_INDEXED(0)) ) |
| 719 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, UI_HOME, "UI Home", input_seq(KEYCODE_HOME) ) |
| 720 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, UI_END, "UI End", input_seq(KEYCODE_END) ) |
| 721 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, UI_PAGE_UP, "UI Page Up", input_seq(KEYCODE_PGUP) ) |
| 722 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, UI_PAGE_DOWN, "UI Page Down", input_seq(KEYCODE_PGDN) ) |
| 723 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, UI_SELECT, "UI Select", input_seq(KEYCODE_ENTER, input_seq::or_code, JOYCODE_BUTTON1_INDEXED(0)) ) |
| 724 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, UI_CANCEL, "UI Cancel", input_seq(KEYCODE_ESC) ) |
| 725 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, UI_DISPLAY_COMMENT, "UI Display Comment", input_seq(KEYCODE_SPACE) ) |
| 726 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, UI_CLEAR, "UI Clear", input_seq(KEYCODE_DEL) ) |
| 727 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, UI_ZOOM_IN, "UI Zoom In", input_seq(KEYCODE_EQUALS) ) |
| 728 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, UI_ZOOM_OUT, "UI Zoom Out", input_seq(KEYCODE_MINUS) ) |
| 729 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, UI_PREV_GROUP, "UI Previous Group", input_seq(KEYCODE_OPENBRACE) ) |
| 730 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, UI_NEXT_GROUP, "UI Next Group", input_seq(KEYCODE_CLOSEBRACE) ) |
| 752 | 731 | } |
| 753 | 732 | |
| 733 | void construct_core_types_ui_shortcuts(simple_list<input_type_entry> &typelist) |
| 734 | { |
| 735 | INPUT_PORT_DIGITAL_TYPE( 0, UI_SHORTCUT, UI_ON_SCREEN_DISPLAY,"On Screen Display", input_seq(KEYCODE_TILDE) ) |
| 736 | INPUT_PORT_DIGITAL_TYPE( 0, UI_SHORTCUT, UI_DEBUG_BREAK, "Break in Debugger", input_seq(KEYCODE_TILDE) ) |
| 737 | INPUT_PORT_DIGITAL_TYPE( 0, UI_SHORTCUT, UI_PAUSE, "Pause", input_seq(KEYCODE_P) ) |
| 738 | INPUT_PORT_DIGITAL_TYPE( 0, UI_SHORTCUT, UI_RESET_MACHINE, "Reset Game", input_seq(KEYCODE_F3, KEYCODE_LSHIFT) ) |
| 739 | INPUT_PORT_DIGITAL_TYPE( 0, UI_SHORTCUT, UI_SOFT_RESET, "Soft Reset", input_seq(KEYCODE_F3, input_seq::not_code, KEYCODE_LSHIFT) ) |
| 740 | INPUT_PORT_DIGITAL_TYPE( 0, UI_SHORTCUT, UI_EXIT, "Exit", input_seq(KEYCODE_ESC) ) |
| 741 | INPUT_PORT_DIGITAL_TYPE( 0, UI_SHORTCUT, UI_SHOW_GFX, "Show Gfx", input_seq(KEYCODE_F4) ) |
| 742 | INPUT_PORT_DIGITAL_TYPE( 0, UI_SHORTCUT, UI_FRAMESKIP_DEC, "Frameskip Dec", input_seq(KEYCODE_F8) ) |
| 743 | INPUT_PORT_DIGITAL_TYPE( 0, UI_SHORTCUT, UI_FRAMESKIP_INC, "Frameskip Inc", input_seq(KEYCODE_F9) ) |
| 744 | INPUT_PORT_DIGITAL_TYPE( 0, UI_SHORTCUT, UI_THROTTLE, "Throttle", input_seq(KEYCODE_F10) ) |
| 745 | INPUT_PORT_DIGITAL_TYPE( 0, UI_SHORTCUT, UI_FAST_FORWARD, "Fast Forward", input_seq(KEYCODE_INSERT) ) |
| 746 | INPUT_PORT_DIGITAL_TYPE( 0, UI_SHORTCUT, UI_SHOW_FPS, "Show FPS", input_seq(KEYCODE_F11, input_seq::not_code, KEYCODE_LSHIFT) ) |
| 747 | INPUT_PORT_DIGITAL_TYPE( 0, UI_SHORTCUT, UI_SNAPSHOT, "Save Snapshot", input_seq(KEYCODE_F12, input_seq::not_code, KEYCODE_LSHIFT) ) |
| 748 | INPUT_PORT_DIGITAL_TYPE( 0, UI_SHORTCUT, UI_RECORD_MOVIE, "Record Movie", input_seq(KEYCODE_F12, KEYCODE_LSHIFT) ) |
| 749 | INPUT_PORT_DIGITAL_TYPE( 0, UI_SHORTCUT, UI_TOGGLE_CHEAT, "Toggle Cheat", input_seq(KEYCODE_F6) ) |
| 750 | INPUT_PORT_DIGITAL_TYPE( 0, UI_SHORTCUT, UI_ROTATE, "UI Rotate", input_seq(KEYCODE_R) ) |
| 751 | INPUT_PORT_DIGITAL_TYPE( 0, UI_SHORTCUT, UI_SHOW_PROFILER, "Show Profiler", input_seq(KEYCODE_F11, KEYCODE_LSHIFT) ) |
| 752 | INPUT_PORT_DIGITAL_TYPE( 0, UI_SHORTCUT, UI_PASTE, "UI Paste Text", input_seq(KEYCODE_SCRLOCK, KEYCODE_LSHIFT) ) |
| 753 | INPUT_PORT_DIGITAL_TYPE( 0, UI_SHORTCUT, UI_TOGGLE_DEBUG, "Toggle Debugger", input_seq(KEYCODE_F5) ) |
| 754 | INPUT_PORT_DIGITAL_TYPE( 0, UI_SHORTCUT, UI_SAVE_STATE, "Save State", input_seq(KEYCODE_F7, KEYCODE_LSHIFT) ) |
| 755 | INPUT_PORT_DIGITAL_TYPE( 0, UI_SHORTCUT, UI_LOAD_STATE, "Load State", input_seq(KEYCODE_F7, input_seq::not_code, KEYCODE_LSHIFT) ) |
| 756 | } |
| 757 | |
| 754 | 758 | void construct_core_types_OSD(simple_list<input_type_entry> &typelist) |
| 755 | 759 | { |
| 756 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_1, NULL, input_seq() ) |
| 757 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_2, NULL, input_seq() ) |
| 758 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_3, NULL, input_seq() ) |
| 759 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_4, NULL, input_seq() ) |
| 760 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_5, NULL, input_seq() ) |
| 761 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_6, NULL, input_seq() ) |
| 762 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_7, NULL, input_seq() ) |
| 763 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_8, NULL, input_seq() ) |
| 764 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_9, NULL, input_seq() ) |
| 765 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_10, NULL, input_seq() ) |
| 766 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_11, NULL, input_seq() ) |
| 767 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_12, NULL, input_seq() ) |
| 768 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_13, NULL, input_seq() ) |
| 769 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_14, NULL, input_seq() ) |
| 770 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_15, NULL, input_seq() ) |
| 771 | | INPUT_PORT_DIGITAL_TYPE( 0, UI, OSD_16, NULL, input_seq() ) |
| 760 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, OSD_1, NULL, input_seq() ) |
| 761 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, OSD_2, NULL, input_seq() ) |
| 762 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, OSD_3, NULL, input_seq() ) |
| 763 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, OSD_4, NULL, input_seq() ) |
| 764 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, OSD_5, NULL, input_seq() ) |
| 765 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, OSD_6, NULL, input_seq() ) |
| 766 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, OSD_7, NULL, input_seq() ) |
| 767 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, OSD_8, NULL, input_seq() ) |
| 768 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, OSD_9, NULL, input_seq() ) |
| 769 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, OSD_10, NULL, input_seq() ) |
| 770 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, OSD_11, NULL, input_seq() ) |
| 771 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, OSD_12, NULL, input_seq() ) |
| 772 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, OSD_13, NULL, input_seq() ) |
| 773 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, OSD_14, NULL, input_seq() ) |
| 774 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, OSD_15, NULL, input_seq() ) |
| 775 | INPUT_PORT_DIGITAL_TYPE( 0, UI_GENERAL, OSD_16, NULL, input_seq() ) |
| 772 | 776 | } |
| 773 | 777 | |
| 774 | 778 | void construct_core_types_invalid(simple_list<input_type_entry> &typelist) |
| r29577 | r29578 | |
| 823 | 827 | construct_core_types_mouse_X(typelist); |
| 824 | 828 | construct_core_types_mouse_Y(typelist); |
| 825 | 829 | construct_core_types_keypad(typelist); |
| 826 | | construct_core_types_UI(typelist); |
| 830 | construct_core_types_ui_general(typelist); |
| 831 | construct_core_types_ui_shortcuts(typelist); |
| 827 | 832 | construct_core_types_OSD(typelist); |
| 828 | 833 | construct_core_types_invalid(typelist); |
| 829 | 834 | } |
trunk/src/emu/ui/mainmenu.c
| r29577 | r29578 | |
| 1 | | /********************************************************************* |
| 2 | | |
| 3 | | ui/mainmenu.c |
| 4 | | |
| 5 | | Internal MAME menus for the user interface. |
| 6 | | |
| 7 | | Copyright Nicola Salmoria and the MAME Team. |
| 8 | | Visit http://mamedev.org for licensing and usage restrictions. |
| 9 | | |
| 10 | | *********************************************************************/ |
| 11 | | |
| 12 | | #include "emu.h" |
| 13 | | #include "osdnet.h" |
| 14 | | #include "emuopts.h" |
| 15 | | #include "ui/ui.h" |
| 16 | | #include "rendutil.h" |
| 17 | | #include "cheat.h" |
| 18 | | #include "uiinput.h" |
| 19 | | #include "ui/filemngr.h" |
| 20 | | #include "ui/filesel.h" |
| 21 | | #include "ui/barcode.h" |
| 22 | | #include "ui/bbcontrl.h" |
| 23 | | #include "ui/tapectrl.h" |
| 24 | | #include "ui/mainmenu.h" |
| 25 | | #include "ui/miscmenu.h" |
| 26 | | #include "ui/imginfo.h" |
| 27 | | #include "ui/selgame.h" |
| 28 | | #include "audit.h" |
| 29 | | #include "crsshair.h" |
| 30 | | #include <ctype.h> |
| 31 | | #include "imagedev/cassette.h" |
| 32 | | #include "imagedev/bitbngr.h" |
| 33 | | #include "machine/bcreader.h" |
| 34 | | |
| 35 | | |
| 36 | | |
| 37 | | /*************************************************************************** |
| 38 | | MENU HANDLERS |
| 39 | | ***************************************************************************/ |
| 40 | | |
| 41 | | /*------------------------------------------------- |
| 42 | | ui_menu_main constructor - populate the main menu |
| 43 | | -------------------------------------------------*/ |
| 44 | | |
| 45 | | ui_menu_main::ui_menu_main(running_machine &machine, render_container *container) : ui_menu(machine, container) |
| 46 | | { |
| 47 | | } |
| 48 | | |
| 49 | | void ui_menu_main::populate() |
| 50 | | { |
| 51 | | astring menu_text; |
| 52 | | |
| 53 | | /* add input menu items */ |
| 54 | | item_append("Input (general)", NULL, 0, (void *)INPUT_GROUPS); |
| 55 | | |
| 56 | | menu_text.printf("Input (this %s)",emulator_info::get_capstartgamenoun()); |
| 57 | | item_append(menu_text.cstr(), NULL, 0, (void *)INPUT_SPECIFIC); |
| 58 | | |
| 59 | | /* add optional input-related menus */ |
| 60 | | if (machine().ioport().has_analog()) |
| 61 | | item_append("Analog Controls", NULL, 0, (void *)ANALOG); |
| 62 | | if (machine().ioport().has_dips()) |
| 63 | | item_append("Dip Switches", NULL, 0, (void *)SETTINGS_DIP_SWITCHES); |
| 64 | | if (machine().ioport().has_configs()) |
| 65 | | { |
| 66 | | menu_text.printf("%s Configuration",emulator_info::get_capstartgamenoun()); |
| 67 | | item_append(menu_text.cstr(), NULL, 0, (void *)SETTINGS_DRIVER_CONFIG); |
| 68 | | } |
| 69 | | |
| 70 | | /* add bookkeeping menu */ |
| 71 | | item_append("Bookkeeping Info", NULL, 0, (void *)BOOKKEEPING); |
| 72 | | |
| 73 | | /* add game info menu */ |
| 74 | | menu_text.printf("%s Information",emulator_info::get_capstartgamenoun()); |
| 75 | | item_append(menu_text.cstr(), NULL, 0, (void *)GAME_INFO); |
| 76 | | |
| 77 | | image_interface_iterator imgiter(machine().root_device()); |
| 78 | | if (imgiter.first() != NULL) |
| 79 | | { |
| 80 | | /* add image info menu */ |
| 81 | | item_append("Image Information", NULL, 0, (void *)IMAGE_MENU_IMAGE_INFO); |
| 82 | | |
| 83 | | /* add file manager menu */ |
| 84 | | item_append("File Manager", NULL, 0, (void *)IMAGE_MENU_FILE_MANAGER); |
| 85 | | |
| 86 | | /* add tape control menu */ |
| 87 | | cassette_device_iterator cassiter(machine().root_device()); |
| 88 | | if (cassiter.first() != NULL) |
| 89 | | item_append("Tape Control", NULL, 0, (void *)MESS_MENU_TAPE_CONTROL); |
| 90 | | |
| 91 | | /* add bitbanger control menu */ |
| 92 | | bitbanger_device_iterator bititer(machine().root_device()); |
| 93 | | if (bititer.first() != NULL) |
| 94 | | item_append("Bitbanger Control", NULL, 0, (void *)MESS_MENU_BITBANGER_CONTROL); |
| 95 | | } |
| 96 | | |
| 97 | | if (machine().ioport().has_bioses()) |
| 98 | | item_append("Bios Selection", NULL, 0, (void *)BIOS_SELECTION); |
| 99 | | |
| 100 | | slot_interface_iterator slotiter(machine().root_device()); |
| 101 | | if (slotiter.first() != NULL) |
| 102 | | { |
| 103 | | /* add slot info menu */ |
| 104 | | item_append("Slot Devices", NULL, 0, (void *)SLOT_DEVICES); |
| 105 | | } |
| 106 | | |
| 107 | | barcode_reader_device_iterator bcriter(machine().root_device()); |
| 108 | | if (bcriter.first() != NULL) |
| 109 | | { |
| 110 | | /* add slot info menu */ |
| 111 | | item_append("Barcode Reader", NULL, 0, (void *)BARCODE_READ); |
| 112 | | } |
| 113 | | |
| 114 | | network_interface_iterator netiter(machine().root_device()); |
| 115 | | if (netiter.first() != NULL) |
| 116 | | { |
| 117 | | /* add image info menu */ |
| 118 | | item_append("Network Devices", NULL, 0, (void*)NETWORK_DEVICES); |
| 119 | | } |
| 120 | | |
| 121 | | /* add keyboard mode menu */ |
| 122 | | if (machine().ioport().has_keyboard() && machine().ioport().natkeyboard().can_post()) |
| 123 | | item_append("Keyboard Mode", NULL, 0, (void *)KEYBOARD_MODE); |
| 124 | | |
| 125 | | /* add sliders menu */ |
| 126 | | item_append("Slider Controls", NULL, 0, (void *)SLIDERS); |
| 127 | | |
| 128 | | /* add video options menu */ |
| 129 | | item_append("Video Options", NULL, 0, (machine().render().target_by_index(1) != NULL) ? (void *)VIDEO_TARGETS : (void *)VIDEO_OPTIONS); |
| 130 | | |
| 131 | | /* add crosshair options menu */ |
| 132 | | if (crosshair_get_usage(machine())) |
| 133 | | item_append("Crosshair Options", NULL, 0, (void *)CROSSHAIR); |
| 134 | | |
| 135 | | /* add cheat menu */ |
| 136 | | if (machine().options().cheat() && machine().cheat().first() != NULL) |
| 137 | | item_append("Cheat", NULL, 0, (void *)CHEAT); |
| 138 | | |
| 139 | | /* add memory card menu */ |
| 140 | | if (machine().config().m_memcard_handler != NULL) |
| 141 | | item_append("Memory Card", NULL, 0, (void *)MEMORY_CARD); |
| 142 | | |
| 143 | | /* add reset and exit menus */ |
| 144 | | menu_text.printf("Select New %s",emulator_info::get_capstartgamenoun()); |
| 145 | | item_append(menu_text.cstr(), NULL, 0, (void *)SELECT_GAME); |
| 146 | | } |
| 147 | | |
| 148 | | ui_menu_main::~ui_menu_main() |
| 149 | | { |
| 150 | | } |
| 151 | | |
| 152 | | /*------------------------------------------------- |
| 153 | | menu_main - handle the main menu |
| 154 | | -------------------------------------------------*/ |
| 155 | | |
| 156 | | void ui_menu_main::handle() |
| 157 | | { |
| 158 | | /* process the menu */ |
| 159 | | const ui_menu_event *menu_event = process(0); |
| 160 | | if (menu_event != NULL && menu_event->iptkey == IPT_UI_SELECT) { |
| 161 | | switch((long long)(menu_event->itemref)) { |
| 162 | | case INPUT_GROUPS: |
| 163 | | ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_input_groups(machine(), container))); |
| 164 | | break; |
| 165 | | |
| 166 | | case INPUT_SPECIFIC: |
| 167 | | ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_input_specific(machine(), container))); |
| 168 | | break; |
| 169 | | |
| 170 | | case SETTINGS_DIP_SWITCHES: |
| 171 | | ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_settings_dip_switches(machine(), container))); |
| 172 | | break; |
| 173 | | |
| 174 | | case SETTINGS_DRIVER_CONFIG: |
| 175 | | ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_settings_driver_config(machine(), container))); |
| 176 | | break; |
| 177 | | |
| 178 | | case ANALOG: |
| 179 | | ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_analog(machine(), container))); |
| 180 | | break; |
| 181 | | |
| 182 | | case BOOKKEEPING: |
| 183 | | ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_bookkeeping(machine(), container))); |
| 184 | | break; |
| 185 | | |
| 186 | | case GAME_INFO: |
| 187 | | ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_game_info(machine(), container))); |
| 188 | | break; |
| 189 | | |
| 190 | | case IMAGE_MENU_IMAGE_INFO: |
| 191 | | ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_image_info(machine(), container))); |
| 192 | | break; |
| 193 | | |
| 194 | | case IMAGE_MENU_FILE_MANAGER: |
| 195 | | ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_file_manager(machine(), container))); |
| 196 | | break; |
| 197 | | |
| 198 | | case MESS_MENU_TAPE_CONTROL: |
| 199 | | ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_mess_tape_control(machine(), container, NULL))); |
| 200 | | break; |
| 201 | | |
| 202 | | case MESS_MENU_BITBANGER_CONTROL: |
| 203 | | ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_mess_bitbanger_control(machine(), container, NULL))); |
| 204 | | break; |
| 205 | | |
| 206 | | case SLOT_DEVICES: |
| 207 | | ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_slot_devices(machine(), container))); |
| 208 | | break; |
| 209 | | |
| 210 | | case NETWORK_DEVICES: |
| 211 | | ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_network_devices(machine(), container))); |
| 212 | | break; |
| 213 | | |
| 214 | | case KEYBOARD_MODE: |
| 215 | | ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_keyboard_mode(machine(), container))); |
| 216 | | break; |
| 217 | | |
| 218 | | case SLIDERS: |
| 219 | | ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_sliders(machine(), container, false))); |
| 220 | | break; |
| 221 | | |
| 222 | | case VIDEO_TARGETS: |
| 223 | | ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_video_targets(machine(), container))); |
| 224 | | break; |
| 225 | | |
| 226 | | case VIDEO_OPTIONS: |
| 227 | | ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_video_options(machine(), container, machine().render().first_target()))); |
| 228 | | break; |
| 229 | | |
| 230 | | case CROSSHAIR: |
| 231 | | ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_crosshair(machine(), container))); |
| 232 | | break; |
| 233 | | |
| 234 | | case CHEAT: |
| 235 | | ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_cheat(machine(), container))); |
| 236 | | break; |
| 237 | | |
| 238 | | case MEMORY_CARD: |
| 239 | | ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_memory_card(machine(), container))); |
| 240 | | break; |
| 241 | | |
| 242 | | case SELECT_GAME: |
| 243 | | ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_select_game(machine(), container, 0))); |
| 244 | | break; |
| 245 | | |
| 246 | | case BIOS_SELECTION: |
| 247 | | ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_bios_selection(machine(), container))); |
| 248 | | break; |
| 249 | | |
| 250 | | case BARCODE_READ: |
| 251 | | ui_menu::stack_push(auto_alloc_clear(machine(), ui_menu_barcode_reader(machine(), container))); |
| 252 | | break; |
| 253 | | |
| 254 | | default: |
| 255 | | fatalerror("ui_menu_main::handle - unknown reference\n"); |
| 256 | | } |
| 257 | | } |
| 258 | | } |
trunk/src/emu/ui/ui.c
| r29577 | r29578 | |
| 18 | 18 | #include "rendfont.h" |
| 19 | 19 | #include "ui/ui.h" |
| 20 | 20 | #include "uiinput.h" |
| 21 | | #include "ui/mainmenu.h" |
| 22 | 21 | #include "ui/miscmenu.h" |
| 23 | 22 | #include "ui/viewgfx.h" |
| 24 | 23 | #include <ctype.h> |
| 25 | 24 | |
| 26 | 25 | |
| 27 | 26 | /*************************************************************************** |
| 28 | | CONSTANTS |
| 29 | | ***************************************************************************/ |
| 30 | | |
| 31 | | enum |
| 32 | | { |
| 33 | | LOADSAVE_NONE, |
| 34 | | LOADSAVE_LOAD, |
| 35 | | LOADSAVE_SAVE |
| 36 | | }; |
| 37 | | |
| 38 | | |
| 39 | | /*************************************************************************** |
| 40 | 27 | LOCAL VARIABLES |
| 41 | 28 | ***************************************************************************/ |
| 42 | 29 | |
| r29577 | r29578 | |
| 226 | 213 | ui_gfx_init(machine); |
| 227 | 214 | |
| 228 | 215 | // reset instance variables |
| 216 | m_menubar = NULL; |
| 229 | 217 | m_font = NULL; |
| 230 | 218 | m_handler_callback = NULL; |
| 231 | 219 | m_handler_param = 0; |
| r29577 | r29578 | |
| 360 | 348 | // loop while we have a handler |
| 361 | 349 | while (m_handler_callback != handler_ingame && !machine().scheduled_event_pending() && !ui_menu::stack_has_special_main_menu()) |
| 362 | 350 | machine().video().frame_update(); |
| 363 | | |
| 364 | | // clear the handler and force an update |
| 365 | | set_handler(handler_ingame, 0); |
| 366 | | machine().video().frame_update(); |
| 367 | 351 | } |
| 368 | 352 | |
| 369 | 353 | // if we're the empty driver, force the menus on |
| r29577 | r29578 | |
| 474 | 458 | { |
| 475 | 459 | INT32 raw_font_pixel_height = get_font()->pixel_height(); |
| 476 | 460 | render_target &ui_target = machine().render().ui_target(); |
| 461 | INT32 target_pixel_width = ui_target.width(); |
| 477 | 462 | INT32 target_pixel_height = ui_target.height(); |
| 478 | | float one_to_one_line_height; |
| 479 | | float scale_factor; |
| 480 | 463 | |
| 481 | | // compute the font pixel height at the nominal size |
| 482 | | one_to_one_line_height = (float)raw_font_pixel_height / (float)target_pixel_height; |
| 464 | // compute the font pixel width/height at the nominal size |
| 465 | float one_to_one_line_width = (float)raw_font_pixel_height / (float)target_pixel_width; |
| 466 | float one_to_one_line_height = (float)raw_font_pixel_height / (float)target_pixel_height; |
| 483 | 467 | |
| 484 | 468 | // determine the scale factor |
| 485 | | scale_factor = UI_TARGET_FONT_HEIGHT / one_to_one_line_height; |
| 469 | float scale_factor = MIN( |
| 470 | UI_TARGET_FONT_WIDTH / one_to_one_line_width, |
| 471 | UI_TARGET_FONT_HEIGHT / one_to_one_line_height); |
| 486 | 472 | |
| 487 | 473 | // if our font is small-ish, do integral scaling |
| 488 | 474 | if (raw_font_pixel_height < 24) |
| r29577 | r29578 | |
| 960 | 946 | |
| 961 | 947 | bool ui_manager::is_menu_active(void) |
| 962 | 948 | { |
| 963 | | return (m_handler_callback == ui_menu::ui_handler); |
| 949 | return (m_handler_callback == ui_menu::ui_handler) |
| 950 | || (m_handler_callback == handler_ingame && m_menubar != NULL && m_menubar->has_selection()); |
| 964 | 951 | } |
| 965 | 952 | |
| 966 | 953 | |
| r29577 | r29578 | |
| 1448 | 1435 | |
| 1449 | 1436 | UINT32 ui_manager::handler_ingame(running_machine &machine, render_container *container, UINT32 state) |
| 1450 | 1437 | { |
| 1451 | | bool is_paused = machine.paused(); |
| 1438 | return machine.ui().handler_ingame_method(container, state); |
| 1439 | } |
| 1452 | 1440 | |
| 1453 | | // first draw the FPS counter |
| 1454 | | if (machine.ui().show_fps_counter()) |
| 1455 | | { |
| 1456 | | astring tempstring; |
| 1457 | | machine.ui().draw_text_full(container, machine.video().speed_text(tempstring), 0.0f, 0.0f, 1.0f, |
| 1458 | | JUSTIFY_RIGHT, WRAP_WORD, DRAW_OPAQUE, ARGB_WHITE, ARGB_BLACK, NULL, NULL); |
| 1459 | | } |
| 1460 | 1441 | |
| 1461 | | // draw the profiler if visible |
| 1462 | | if (machine.ui().show_profiler()) |
| 1463 | | { |
| 1464 | | const char *text = g_profiler.text(machine); |
| 1465 | | machine.ui().draw_text_full(container, text, 0.0f, 0.0f, 1.0f, JUSTIFY_LEFT, WRAP_WORD, DRAW_OPAQUE, ARGB_WHITE, ARGB_BLACK, NULL, NULL); |
| 1466 | | } |
| 1442 | //------------------------------------------------- |
| 1443 | // handler_ingame_method - in-game handler takes |
| 1444 | // care of the standard keypresses |
| 1445 | //------------------------------------------------- |
| 1467 | 1446 | |
| 1468 | | // if we're single-stepping, pause now |
| 1469 | | if (machine.ui().single_step()) |
| 1470 | | { |
| 1471 | | machine.pause(); |
| 1472 | | machine.ui().set_single_step(false); |
| 1473 | | } |
| 1474 | | |
| 1475 | | // determine if we should disable the rest of the UI |
| 1476 | | bool ui_disabled = (machine.ioport().has_keyboard() && !machine.ui_active()); |
| 1477 | | |
| 1478 | | // is ScrLk UI toggling applicable here? |
| 1479 | | if (machine.ioport().has_keyboard()) |
| 1480 | | { |
| 1481 | | // are we toggling the UI with ScrLk? |
| 1482 | | if (ui_input_pressed(machine, IPT_UI_TOGGLE_UI)) |
| 1483 | | { |
| 1484 | | // toggle the UI |
| 1485 | | machine.set_ui_active(!machine.ui_active()); |
| 1486 | | |
| 1487 | | // display a popup indicating the new status |
| 1488 | | if (machine.ui_active()) |
| 1489 | | { |
| 1490 | | machine.ui().popup_time(2, "%s\n%s\n%s\n%s\n%s\n%s\n", |
| 1491 | | "Keyboard Emulation Status", |
| 1492 | | "-------------------------", |
| 1493 | | "Mode: PARTIAL Emulation", |
| 1494 | | "UI: Enabled", |
| 1495 | | "-------------------------", |
| 1496 | | "**Use ScrLock to toggle**"); |
| 1497 | | } |
| 1498 | | else |
| 1499 | | { |
| 1500 | | machine.ui().popup_time(2, "%s\n%s\n%s\n%s\n%s\n%s\n", |
| 1501 | | "Keyboard Emulation Status", |
| 1502 | | "-------------------------", |
| 1503 | | "Mode: FULL Emulation", |
| 1504 | | "UI: Disabled", |
| 1505 | | "-------------------------", |
| 1506 | | "**Use ScrLock to toggle**"); |
| 1507 | | } |
| 1508 | | } |
| 1509 | | } |
| 1510 | | |
| 1511 | | // is the natural keyboard enabled? |
| 1512 | | if (machine.ui().use_natural_keyboard() && (machine.phase() == MACHINE_PHASE_RUNNING)) |
| 1513 | | machine.ui().process_natural_keyboard(); |
| 1514 | | |
| 1515 | | if (!ui_disabled) |
| 1516 | | { |
| 1517 | | // paste command |
| 1518 | | if (ui_input_pressed(machine, IPT_UI_PASTE)) |
| 1519 | | machine.ui().paste(); |
| 1520 | | } |
| 1521 | | |
| 1522 | | machine.ui().image_handler_ingame(); |
| 1523 | | |
| 1524 | | if (ui_disabled) return ui_disabled; |
| 1525 | | |
| 1526 | | if (ui_input_pressed(machine, IPT_UI_CANCEL)) |
| 1527 | | { |
| 1528 | | machine.ui().request_quit(); |
| 1529 | | return 0; |
| 1530 | | } |
| 1531 | | |
| 1532 | | // turn on menus if requested |
| 1533 | | if (ui_input_pressed(machine, IPT_UI_CONFIGURE)) |
| 1534 | | return machine.ui().set_handler(ui_menu::ui_handler, 0); |
| 1535 | | |
| 1536 | | // if the on-screen display isn't up and the user has toggled it, turn it on |
| 1537 | | if ((machine.debug_flags & DEBUG_FLAG_ENABLED) == 0 && ui_input_pressed(machine, IPT_UI_ON_SCREEN_DISPLAY)) |
| 1538 | | return machine.ui().set_handler(ui_menu_sliders::ui_handler, 1); |
| 1539 | | |
| 1540 | | // handle a reset request |
| 1541 | | if (ui_input_pressed(machine, IPT_UI_RESET_MACHINE)) |
| 1542 | | machine.schedule_hard_reset(); |
| 1543 | | if (ui_input_pressed(machine, IPT_UI_SOFT_RESET)) |
| 1544 | | machine.schedule_soft_reset(); |
| 1545 | | |
| 1546 | | // handle a request to display graphics/palette |
| 1547 | | if (ui_input_pressed(machine, IPT_UI_SHOW_GFX)) |
| 1548 | | { |
| 1549 | | if (!is_paused) |
| 1550 | | machine.pause(); |
| 1551 | | return machine.ui().set_handler(ui_gfx_ui_handler, is_paused); |
| 1552 | | } |
| 1553 | | |
| 1554 | | // handle a save state request |
| 1555 | | if (ui_input_pressed(machine, IPT_UI_SAVE_STATE)) |
| 1556 | | { |
| 1557 | | machine.pause(); |
| 1558 | | return machine.ui().set_handler(handler_load_save, LOADSAVE_SAVE); |
| 1559 | | } |
| 1560 | | |
| 1561 | | // handle a load state request |
| 1562 | | if (ui_input_pressed(machine, IPT_UI_LOAD_STATE)) |
| 1563 | | { |
| 1564 | | machine.pause(); |
| 1565 | | return machine.ui().set_handler(handler_load_save, LOADSAVE_LOAD); |
| 1566 | | } |
| 1567 | | |
| 1568 | | // handle a save snapshot request |
| 1569 | | if (ui_input_pressed(machine, IPT_UI_SNAPSHOT)) |
| 1570 | | machine.video().save_active_screen_snapshots(); |
| 1571 | | |
| 1572 | | // toggle pause |
| 1573 | | if (ui_input_pressed(machine, IPT_UI_PAUSE)) |
| 1574 | | { |
| 1575 | | // with a shift key, it is single step |
| 1576 | | if (is_paused && (machine.input().code_pressed(KEYCODE_LSHIFT) || machine.input().code_pressed(KEYCODE_RSHIFT))) |
| 1577 | | { |
| 1578 | | machine.ui().set_single_step(true); |
| 1579 | | machine.resume(); |
| 1580 | | } |
| 1581 | | else |
| 1582 | | machine.toggle_pause(); |
| 1583 | | } |
| 1584 | | |
| 1585 | | // handle a toggle cheats request |
| 1586 | | if (ui_input_pressed(machine, IPT_UI_TOGGLE_CHEAT)) |
| 1587 | | machine.cheat().set_enable(!machine.cheat().enabled()); |
| 1588 | | |
| 1589 | | // toggle movie recording |
| 1590 | | if (ui_input_pressed(machine, IPT_UI_RECORD_MOVIE)) |
| 1591 | | machine.video().toggle_record_movie(); |
| 1592 | | |
| 1593 | | // toggle profiler display |
| 1594 | | if (ui_input_pressed(machine, IPT_UI_SHOW_PROFILER)) |
| 1595 | | machine.ui().set_show_profiler(!machine.ui().show_profiler()); |
| 1596 | | |
| 1597 | | // toggle FPS display |
| 1598 | | if (ui_input_pressed(machine, IPT_UI_SHOW_FPS)) |
| 1599 | | machine.ui().set_show_fps(!machine.ui().show_fps()); |
| 1600 | | |
| 1601 | | // increment frameskip? |
| 1602 | | if (ui_input_pressed(machine, IPT_UI_FRAMESKIP_INC)) |
| 1603 | | machine.ui().increase_frameskip(); |
| 1604 | | |
| 1605 | | // decrement frameskip? |
| 1606 | | if (ui_input_pressed(machine, IPT_UI_FRAMESKIP_DEC)) |
| 1607 | | machine.ui().decrease_frameskip(); |
| 1608 | | |
| 1609 | | // toggle throttle? |
| 1610 | | if (ui_input_pressed(machine, IPT_UI_THROTTLE)) |
| 1611 | | machine.video().toggle_throttle(); |
| 1612 | | |
| 1613 | | // check for fast forward |
| 1614 | | if (machine.ioport().type_pressed(IPT_UI_FAST_FORWARD)) |
| 1615 | | { |
| 1616 | | machine.video().set_fastforward(true); |
| 1617 | | machine.ui().show_fps_temp(0.5); |
| 1618 | | } |
| 1619 | | else |
| 1620 | | machine.video().set_fastforward(false); |
| 1621 | | |
| 1622 | | return 0; |
| 1447 | UINT32 ui_manager::handler_ingame_method(render_container *container, UINT32 state) |
| 1448 | { |
| 1449 | // no menubar? create it |
| 1450 | if (m_menubar == NULL) |
| 1451 | m_menubar = auto_alloc(machine(), ui_emu_menubar(machine())); |
| 1452 | |
| 1453 | // handle! |
| 1454 | m_menubar->handle(container); |
| 1455 | |
| 1456 | // did we change out the handler? |
| 1457 | if (m_handler_callback != handler_ingame) |
| 1458 | { |
| 1459 | // if so, flush the menubar... |
| 1460 | auto_free(machine(), m_menubar); |
| 1461 | m_menubar = NULL; |
| 1462 | |
| 1463 | // ...and then check to see if this is just a "refresh" |
| 1464 | if (m_handler_callback == NULL) |
| 1465 | m_handler_callback = handler_ingame; |
| 1466 | } |
| 1467 | |
| 1468 | return m_handler_param; |
| 1623 | 1469 | } |
| 1624 | 1470 | |
| 1625 | 1471 | |
| 1626 | 1472 | //------------------------------------------------- |
| 1627 | | // handler_load_save - leads the user through |
| 1473 | // ui_handler_load_save - leads the user through |
| 1628 | 1474 | // specifying a game to save or load |
| 1629 | 1475 | //------------------------------------------------- |
| 1630 | 1476 | |
| 1631 | | UINT32 ui_manager::handler_load_save(running_machine &machine, render_container *container, UINT32 state) |
| 1477 | UINT32 ui_manager::ui_handler_load_save(running_machine &machine, render_container *container, UINT32 state) |
| 1632 | 1478 | { |
| 1633 | 1479 | char filename[20]; |
| 1634 | 1480 | input_code code; |
trunk/src/emu/ui/menubar.c
| r0 | r29578 | |
| 1 | /*************************************************************************** |
| 2 | |
| 3 | menubar.c |
| 4 | |
| 5 | Internal MAME menu bar for the user interface. |
| 6 | |
| 7 | Copyright Nicola Salmoria and the MAME Team. |
| 8 | Visit http://mamedev.org for licensing and usage restrictions. |
| 9 | |
| 10 | ***************************************************************************/ |
| 11 | |
| 12 | #include "emu.h" |
| 13 | #include "ui/menubar.h" |
| 14 | #include "ui/ui.h" |
| 15 | #include "uiinput.h" |
| 16 | |
| 17 | |
| 18 | //************************************************************************** |
| 19 | // CONSTANTS |
| 20 | //************************************************************************** |
| 21 | |
| 22 | #define CHECKMARK "x " |
| 23 | #define SEPARATOR_HEIGHT 0.25 |
| 24 | |
| 25 | |
| 26 | //************************************************************************** |
| 27 | // CLASSES |
| 28 | //************************************************************************** |
| 29 | |
| 30 | class tabbed_text_iterator |
| 31 | { |
| 32 | public: |
| 33 | tabbed_text_iterator(const char *text); |
| 34 | bool next(); |
| 35 | int index() const { return m_index; } |
| 36 | const char *current() { return m_current; } |
| 37 | |
| 38 | private: |
| 39 | astring m_buffer; |
| 40 | const char * m_text; |
| 41 | const char * m_current; |
| 42 | int m_position; |
| 43 | int m_index; |
| 44 | }; |
| 45 | |
| 46 | |
| 47 | //************************************************************************** |
| 48 | // MENUBAR IMPLEMENTATION |
| 49 | //************************************************************************** |
| 50 | |
| 51 | //------------------------------------------------- |
| 52 | // ctor |
| 53 | //------------------------------------------------- |
| 54 | |
| 55 | ui_menubar::ui_menubar(running_machine &machine) |
| 56 | : m_machine(machine), m_menus(*this) |
| 57 | { |
| 58 | m_container = NULL; |
| 59 | m_shortcuted_menu_items = NULL; |
| 60 | m_selected_item = NULL; |
| 61 | m_active_item = NULL; |
| 62 | m_dragged = false; |
| 63 | m_checkmark_width = -1; |
| 64 | m_mouse_x = -1; |
| 65 | m_mouse_y = -1; |
| 66 | m_mouse_button = false; |
| 67 | m_last_mouse_move = 0; |
| 68 | m_first_time = true; |
| 69 | } |
| 70 | |
| 71 | |
| 72 | //------------------------------------------------- |
| 73 | // dtor |
| 74 | //------------------------------------------------- |
| 75 | |
| 76 | ui_menubar::~ui_menubar() |
| 77 | { |
| 78 | } |
| 79 | |
| 80 | |
| 81 | //------------------------------------------------- |
| 82 | // reset |
| 83 | //------------------------------------------------- |
| 84 | |
| 85 | void ui_menubar::reset() |
| 86 | { |
| 87 | } |
| 88 | |
| 89 | |
| 90 | //------------------------------------------------- |
| 91 | // input_pressed_safe |
| 92 | //------------------------------------------------- |
| 93 | |
| 94 | bool ui_menubar::input_pressed_safe(int key) |
| 95 | { |
| 96 | return (key != IPT_INVALID) && ui_input_pressed(machine(), key); |
| 97 | } |
| 98 | |
| 99 | |
| 100 | //------------------------------------------------- |
| 101 | // handle |
| 102 | //------------------------------------------------- |
| 103 | |
| 104 | void ui_menubar::handle(render_container *current_container) |
| 105 | { |
| 106 | m_container = current_container; |
| 107 | |
| 108 | // do we need to initialize the menus? |
| 109 | if (m_menus.is_empty()) |
| 110 | menubar_build_menus(); |
| 111 | |
| 112 | // measure standard string widths (if necessary) |
| 113 | if (m_checkmark_width <= 0) |
| 114 | m_checkmark_width = machine().ui().get_string_width(CHECKMARK); |
| 115 | |
| 116 | // reset screen locations of all menu items |
| 117 | m_menus.clear_area_recursive(); |
| 118 | |
| 119 | // calculate visibility of the menubar |
| 120 | m_menubar_visibility = get_menubar_visibility(); |
| 121 | |
| 122 | // draw conventional UI elements (e.g. - frameskip) |
| 123 | menubar_draw_ui_elements(); |
| 124 | |
| 125 | float text_height = machine().ui().get_line_height(); |
| 126 | float spacing = text_height / 10; |
| 127 | float x = spacing; |
| 128 | float y = spacing; |
| 129 | |
| 130 | for(menu_item *mi = m_menus.child(); mi != NULL; mi = mi->next()) |
| 131 | { |
| 132 | float width = machine().ui().get_string_width(mi->text()); |
| 133 | |
| 134 | machine().ui().draw_outlined_box( |
| 135 | container(), |
| 136 | x, |
| 137 | y, |
| 138 | x + width + (spacing * 2), |
| 139 | y + text_height + (spacing * 2), |
| 140 | adjust_color(UI_BORDER_COLOR), |
| 141 | adjust_color(UI_BACKGROUND_COLOR)); |
| 142 | |
| 143 | draw_menu_item_text( |
| 144 | mi, |
| 145 | x + spacing, |
| 146 | y + spacing, |
| 147 | x + spacing + width, |
| 148 | y + spacing + text_height, |
| 149 | false); |
| 150 | |
| 151 | // child menu open? |
| 152 | if (is_child_menu_visible(mi)) |
| 153 | draw_child_menu(mi, x, y + text_height + (spacing * 3)); |
| 154 | |
| 155 | x += width + spacing * 4; |
| 156 | } |
| 157 | |
| 158 | // loop while we have interesting events |
| 159 | while(!event_loop()) |
| 160 | { |
| 161 | } |
| 162 | } |
| 163 | |
| 164 | |
| 165 | //------------------------------------------------- |
| 166 | // event_loop |
| 167 | //------------------------------------------------- |
| 168 | |
| 169 | bool ui_menubar::event_loop() |
| 170 | { |
| 171 | bool done = false; |
| 172 | |
| 173 | ui_event local_menu_event; |
| 174 | if (ui_input_pop_event(machine(), &local_menu_event)) |
| 175 | { |
| 176 | // find the menu item we're pointing at |
| 177 | find_mouse(m_mouse_x, m_mouse_y, m_mouse_button); |
| 178 | menu_item *mi = m_menus.find_point(m_mouse_x, m_mouse_y); |
| 179 | |
| 180 | switch (local_menu_event.event_type) |
| 181 | { |
| 182 | case UI_EVENT_MOUSE_DOWN: |
| 183 | if (mi != NULL) |
| 184 | { |
| 185 | m_selected_item = mi; |
| 186 | m_active_item = mi; |
| 187 | m_dragged = false; |
| 188 | } |
| 189 | break; |
| 190 | |
| 191 | case UI_EVENT_MOUSE_MOVE: |
| 192 | // record the move |
| 193 | m_last_mouse_move = osd_ticks(); |
| 194 | |
| 195 | // moving is only interesting if we have an active menu selection |
| 196 | if (m_mouse_button && m_active_item != NULL) |
| 197 | { |
| 198 | // are we changing the active menu item? |
| 199 | if (m_active_item != mi) |
| 200 | { |
| 201 | if (mi != NULL) |
| 202 | m_active_item = mi->has_children() ? mi->child() : mi; |
| 203 | m_dragged = true; |
| 204 | done = true; |
| 205 | } |
| 206 | |
| 207 | // are we changing the selection? |
| 208 | if (m_selected_item != mi) |
| 209 | { |
| 210 | m_selected_item = mi; |
| 211 | done = true; |
| 212 | } |
| 213 | } |
| 214 | break; |
| 215 | |
| 216 | case UI_EVENT_MOUSE_UP: |
| 217 | m_active_item = NULL; |
| 218 | if (m_selected_item && m_selected_item == mi) |
| 219 | { |
| 220 | // looks like we did a mouse up on the current selection; we |
| 221 | // should invoke or expand the current selection (whichever |
| 222 | // may be appropriate) |
| 223 | if (m_selected_item->is_invokable()) |
| 224 | invoke(m_selected_item); |
| 225 | else if (m_selected_item->has_children()) |
| 226 | m_active_item = m_selected_item->child(); |
| 227 | } |
| 228 | else if (m_dragged) |
| 229 | { |
| 230 | m_selected_item = NULL; |
| 231 | } |
| 232 | done = true; |
| 233 | break; |
| 234 | |
| 235 | default: |
| 236 | break; |
| 237 | } |
| 238 | } |
| 239 | |
| 240 | if (!done) |
| 241 | { |
| 242 | bool navigation_input_pressed = poll_navigation_keys(); |
| 243 | poll_shortcut_keys(navigation_input_pressed || m_first_time); |
| 244 | m_first_time = false; |
| 245 | done = true; |
| 246 | } |
| 247 | return done; |
| 248 | } |
| 249 | |
| 250 | |
| 251 | //------------------------------------------------- |
| 252 | // poll_navigation_keys |
| 253 | //------------------------------------------------- |
| 254 | |
| 255 | bool ui_menubar::poll_navigation_keys() |
| 256 | { |
| 257 | int code_previous_menu = IPT_INVALID; |
| 258 | int code_next_menu = IPT_INVALID; |
| 259 | int code_child_menu1 = IPT_INVALID; |
| 260 | int code_child_menu2 = IPT_INVALID; |
| 261 | int code_parent_menu = IPT_INVALID; |
| 262 | int code_previous_sub_menu = IPT_INVALID; |
| 263 | int code_next_sub_menu = IPT_INVALID; |
| 264 | int code_selected = (m_selected_item && m_selected_item->is_invokable()) |
| 265 | ? IPT_UI_SELECT |
| 266 | : IPT_INVALID; |
| 267 | |
| 268 | // are we navigating the menu? |
| 269 | if (m_selected_item != NULL) |
| 270 | { |
| 271 | // if so, are we in a pull down menu? |
| 272 | if (!m_selected_item->is_sub_menu()) |
| 273 | { |
| 274 | // no pull down menu selected |
| 275 | code_previous_menu = IPT_UI_LEFT; |
| 276 | code_next_menu = IPT_UI_RIGHT; |
| 277 | code_child_menu1 = IPT_UI_SELECT; |
| 278 | code_child_menu2 = IPT_UI_DOWN; |
| 279 | } |
| 280 | else |
| 281 | { |
| 282 | // pull down menu selected |
| 283 | code_previous_menu = IPT_UI_UP; |
| 284 | code_next_menu = IPT_UI_DOWN; |
| 285 | if (m_selected_item->child()) |
| 286 | { |
| 287 | code_child_menu1 = IPT_UI_SELECT; |
| 288 | code_child_menu2 = IPT_UI_RIGHT; |
| 289 | } |
| 290 | code_previous_sub_menu = IPT_UI_LEFT; |
| 291 | code_next_sub_menu = IPT_UI_RIGHT; |
| 292 | if (m_selected_item->parent()->is_sub_menu()) |
| 293 | code_parent_menu = IPT_UI_LEFT; |
| 294 | } |
| 295 | } |
| 296 | |
| 297 | bool result = true; |
| 298 | if (input_pressed_safe(code_previous_menu)) |
| 299 | result = walk_selection_previous(); |
| 300 | else if (input_pressed_safe(code_next_menu)) |
| 301 | result = walk_selection_next(); |
| 302 | else if (input_pressed_safe(code_child_menu1) || input_pressed_safe(code_child_menu2)) |
| 303 | result = walk_selection_child(); |
| 304 | else if (input_pressed_safe(IPT_UI_CANCEL)) |
| 305 | result = walk_selection_escape(); |
| 306 | else if (input_pressed_safe(code_parent_menu)) |
| 307 | result = walk_selection_parent(); |
| 308 | else if (input_pressed_safe(code_previous_sub_menu)) |
| 309 | result = walk_selection_previous_sub_menu(); |
| 310 | else if (input_pressed_safe(code_next_sub_menu)) |
| 311 | result = walk_selection_next_sub_menu(); |
| 312 | else if (input_pressed_safe(IPT_UI_CONFIGURE)) |
| 313 | toggle_selection(); |
| 314 | else if (input_pressed_safe(code_selected)) |
| 315 | invoke(m_selected_item); |
| 316 | else |
| 317 | result = false; // didn't do anything |
| 318 | |
| 319 | // if we changed something, set the active item accordingly |
| 320 | if (result) |
| 321 | m_active_item = m_selected_item; |
| 322 | |
| 323 | return result; |
| 324 | } |
| 325 | |
| 326 | |
| 327 | //------------------------------------------------- |
| 328 | // poll_shortcut_keys |
| 329 | //------------------------------------------------- |
| 330 | |
| 331 | bool ui_menubar::poll_shortcut_keys(bool swallow) |
| 332 | { |
| 333 | // loop through all shortcut items |
| 334 | for (menu_item *item = m_shortcuted_menu_items; item != NULL; item = item->next_with_shortcut()) |
| 335 | { |
| 336 | assert(item->is_invokable()); |
| 337 | |
| 338 | // did we press this shortcut? |
| 339 | if (input_pressed_safe(item->shortcut()) && !swallow) |
| 340 | { |
| 341 | // this shortcut was pressed and we're not swallowing them; invoke it |
| 342 | invoke(item); |
| 343 | return true; |
| 344 | } |
| 345 | } |
| 346 | return false; |
| 347 | } |
| 348 | |
| 349 | |
| 350 | //------------------------------------------------- |
| 351 | // toggle_selection |
| 352 | //------------------------------------------------- |
| 353 | |
| 354 | void ui_menubar::toggle_selection() |
| 355 | { |
| 356 | m_selected_item = m_selected_item != NULL |
| 357 | ? NULL |
| 358 | : m_menus.child(); |
| 359 | } |
| 360 | |
| 361 | |
| 362 | //------------------------------------------------- |
| 363 | // invoke |
| 364 | //------------------------------------------------- |
| 365 | |
| 366 | void ui_menubar::invoke(menu_item *menu) |
| 367 | { |
| 368 | // first, we're ending the menu; pop us off first |
| 369 | machine().ui().set_handler(NULL, 0); |
| 370 | |
| 371 | // and invoke the selection |
| 372 | menu->invoke(); |
| 373 | } |
| 374 | |
| 375 | |
| 376 | //------------------------------------------------- |
| 377 | // walk_selection_previous |
| 378 | //------------------------------------------------- |
| 379 | |
| 380 | bool ui_menubar::walk_selection_previous() |
| 381 | { |
| 382 | if (m_selected_item) |
| 383 | { |
| 384 | do |
| 385 | { |
| 386 | m_selected_item = m_selected_item->previous() |
| 387 | ? m_selected_item->previous() |
| 388 | : m_selected_item->parent()->last_child(); |
| 389 | } |
| 390 | while(!m_selected_item->is_enabled()); |
| 391 | } |
| 392 | else |
| 393 | { |
| 394 | m_selected_item = m_menus.last_child(); |
| 395 | } |
| 396 | return true; |
| 397 | } |
| 398 | |
| 399 | |
| 400 | //------------------------------------------------- |
| 401 | // walk_selection_next |
| 402 | //------------------------------------------------- |
| 403 | |
| 404 | bool ui_menubar::walk_selection_next() |
| 405 | { |
| 406 | if (m_selected_item) |
| 407 | { |
| 408 | do |
| 409 | { |
| 410 | m_selected_item = m_selected_item->next() |
| 411 | ? m_selected_item->next() |
| 412 | : m_selected_item->parent()->child(); |
| 413 | } |
| 414 | while(!m_selected_item->is_enabled()); |
| 415 | } |
| 416 | else |
| 417 | { |
| 418 | m_selected_item = m_menus.child(); |
| 419 | } |
| 420 | return true; |
| 421 | } |
| 422 | |
| 423 | |
| 424 | //------------------------------------------------- |
| 425 | // walk_selection_child |
| 426 | //------------------------------------------------- |
| 427 | |
| 428 | bool ui_menubar::walk_selection_child() |
| 429 | { |
| 430 | bool result = false; |
| 431 | if (m_selected_item && m_selected_item->child()) |
| 432 | { |
| 433 | m_selected_item = m_selected_item->child(); |
| 434 | result = true; |
| 435 | } |
| 436 | return result; |
| 437 | } |
| 438 | |
| 439 | |
| 440 | //------------------------------------------------- |
| 441 | // walk_selection_parent |
| 442 | //------------------------------------------------- |
| 443 | |
| 444 | bool ui_menubar::walk_selection_parent() |
| 445 | { |
| 446 | bool result = false; |
| 447 | if (m_selected_item && m_selected_item->parent() && m_selected_item->parent() != &m_menus) |
| 448 | { |
| 449 | m_selected_item = m_selected_item->parent(); |
| 450 | result = true; |
| 451 | } |
| 452 | return result; |
| 453 | } |
| 454 | |
| 455 | |
| 456 | //------------------------------------------------- |
| 457 | // walk_selection_escape |
| 458 | //------------------------------------------------- |
| 459 | |
| 460 | bool ui_menubar::walk_selection_escape() |
| 461 | { |
| 462 | bool result = walk_selection_parent(); |
| 463 | |
| 464 | if (!result && m_selected_item != NULL) |
| 465 | { |
| 466 | m_selected_item = NULL; |
| 467 | result = true; |
| 468 | } |
| 469 | |
| 470 | return result; |
| 471 | } |
| 472 | |
| 473 | |
| 474 | //------------------------------------------------- |
| 475 | // walk_selection_previous_sub_menu |
| 476 | //------------------------------------------------- |
| 477 | |
| 478 | bool ui_menubar::walk_selection_previous_sub_menu() |
| 479 | { |
| 480 | while(walk_selection_parent()) |
| 481 | ; |
| 482 | bool result = walk_selection_previous(); |
| 483 | if (result) |
| 484 | walk_selection_child(); |
| 485 | return result; |
| 486 | } |
| 487 | |
| 488 | |
| 489 | //------------------------------------------------- |
| 490 | // walk_selection_next_sub_menu |
| 491 | //------------------------------------------------- |
| 492 | |
| 493 | bool ui_menubar::walk_selection_next_sub_menu() |
| 494 | { |
| 495 | while(walk_selection_parent()) |
| 496 | ; |
| 497 | bool result = walk_selection_next(); |
| 498 | if (result) |
| 499 | walk_selection_child(); |
| 500 | return result; |
| 501 | } |
| 502 | |
| 503 | |
| 504 | //------------------------------------------------- |
| 505 | // draw_child_menu |
| 506 | //------------------------------------------------- |
| 507 | |
| 508 | void ui_menubar::draw_child_menu(menu_item *menu, float x, float y) |
| 509 | { |
| 510 | float text_height = machine().ui().get_line_height(); |
| 511 | float separator_height = text_height * SEPARATOR_HEIGHT; |
| 512 | float spacing = text_height / 10; |
| 513 | |
| 514 | // calculate the maximum width and menu item count |
| 515 | float max_widths[4] = {0, }; |
| 516 | float total_height = (spacing * 2); |
| 517 | float max_shortcuts_width = 0; |
| 518 | for(menu_item *mi = menu->child(); mi != NULL; mi = mi->next()) |
| 519 | { |
| 520 | // aggregate the maximum width for each column |
| 521 | tabbed_text_iterator iter(mi->text()); |
| 522 | while(iter.next()) |
| 523 | { |
| 524 | float width = machine().ui().get_string_width(iter.current()); |
| 525 | assert(iter.index() < ARRAY_LENGTH(max_widths)); |
| 526 | max_widths[iter.index()] = MAX(max_widths[iter.index()], width); |
| 527 | } |
| 528 | |
| 529 | // measure the shortcut |
| 530 | float shortcut_width = mi->shortcut_text_width(); |
| 531 | if (shortcut_width > 0) |
| 532 | max_shortcuts_width = MAX(max_shortcuts_width, shortcut_width + spacing); |
| 533 | |
| 534 | // increase the height |
| 535 | total_height += (mi->is_separator() ? separator_height : text_height); |
| 536 | } |
| 537 | |
| 538 | // get the aggregate maximum widths across all columns |
| 539 | float max_width = m_checkmark_width * 2 + max_shortcuts_width; |
| 540 | for (int i = 0; i < ARRAY_LENGTH(max_widths); i++) |
| 541 | max_width += max_widths[i]; |
| 542 | |
| 543 | // are we going to go over the right of the screen? |
| 544 | float right = x + max_width + (spacing * 3); |
| 545 | if (right > 1.0f) |
| 546 | x = MAX(0.0f, x - (right - 1.0f)); |
| 547 | |
| 548 | // draw the menu outline |
| 549 | machine().ui().draw_outlined_box( |
| 550 | container(), |
| 551 | x, |
| 552 | y, |
| 553 | x + max_width + (spacing * 2), |
| 554 | y + total_height, |
| 555 | adjust_color(UI_BACKGROUND_COLOR)); |
| 556 | |
| 557 | // draw the individual items |
| 558 | float my = y; |
| 559 | for(menu_item *mi = menu->child(); mi != NULL; mi = mi->next()) |
| 560 | { |
| 561 | if (mi->is_separator()) |
| 562 | { |
| 563 | // draw separator |
| 564 | container()->add_line( |
| 565 | x, |
| 566 | my + spacing + separator_height / 2, |
| 567 | x + max_width + (spacing * 2), |
| 568 | my + spacing + separator_height / 2, |
| 569 | separator_height / 8, |
| 570 | adjust_color(UI_BORDER_COLOR), |
| 571 | 0); |
| 572 | } |
| 573 | else |
| 574 | { |
| 575 | // draw normal text |
| 576 | draw_menu_item_text( |
| 577 | mi, |
| 578 | x + spacing, |
| 579 | my + spacing, |
| 580 | x + spacing + max_width, |
| 581 | my + spacing + text_height, |
| 582 | true, |
| 583 | max_widths); |
| 584 | } |
| 585 | |
| 586 | // move down... |
| 587 | my += (mi->is_separator() ? separator_height : text_height); |
| 588 | } |
| 589 | |
| 590 | // draw child menus |
| 591 | my = y; |
| 592 | for(menu_item *mi = menu->child(); mi != NULL; mi = mi->next()) |
| 593 | { |
| 594 | // child menu open? |
| 595 | if (!mi->is_separator() && is_child_menu_visible(mi)) |
| 596 | { |
| 597 | draw_child_menu( |
| 598 | mi, |
| 599 | x + max_width + (spacing * 2), |
| 600 | my); |
| 601 | } |
| 602 | |
| 603 | // move down... |
| 604 | my += (mi->is_separator() ? separator_height : text_height); |
| 605 | } |
| 606 | } |
| 607 | |
| 608 | |
| 609 | //------------------------------------------------- |
| 610 | // is_child_menu_visible |
| 611 | //------------------------------------------------- |
| 612 | |
| 613 | bool ui_menubar::is_child_menu_visible(menu_item *menu) const |
| 614 | { |
| 615 | menu_item *current_menu = m_active_item ? m_active_item : m_selected_item; |
| 616 | return current_menu && current_menu->is_child_of(menu); |
| 617 | } |
| 618 | |
| 619 | |
| 620 | //------------------------------------------------- |
| 621 | // draw_menu_item_text |
| 622 | //------------------------------------------------- |
| 623 | |
| 624 | void ui_menubar::draw_menu_item_text(menu_item *mi, float x0, float y0, float x1, float y1, bool decorations, const float *column_widths) |
| 625 | { |
| 626 | // set our area |
| 627 | mi->set_area(x0, y0, x1, y1); |
| 628 | |
| 629 | // choose the color |
| 630 | rgb_t fgcolor, bgcolor; |
| 631 | if (!mi->is_enabled()) |
| 632 | { |
| 633 | // disabled |
| 634 | fgcolor = UI_UNAVAILABLE_COLOR; |
| 635 | bgcolor = UI_TEXT_BG_COLOR; |
| 636 | } |
| 637 | else if (mi == m_selected_item) |
| 638 | { |
| 639 | // selected |
| 640 | fgcolor = UI_SELECTED_COLOR; |
| 641 | bgcolor = UI_SELECTED_BG_COLOR; |
| 642 | } |
| 643 | else if ((m_mouse_x >= x0) && (m_mouse_x < x1) && (m_mouse_y >= y0) && (m_mouse_y < y1)) |
| 644 | { |
| 645 | // hover |
| 646 | fgcolor = UI_MOUSEOVER_COLOR; |
| 647 | bgcolor = UI_MOUSEOVER_BG_COLOR; |
| 648 | } |
| 649 | else |
| 650 | { |
| 651 | // normal |
| 652 | fgcolor = UI_TEXT_COLOR; |
| 653 | bgcolor = UI_TEXT_BG_COLOR; |
| 654 | } |
| 655 | |
| 656 | // highlight? |
| 657 | if (bgcolor != UI_TEXT_BG_COLOR) |
| 658 | ui_menu::highlight(container(), x0, y0, x1, y1, adjust_color(bgcolor)); |
| 659 | |
| 660 | // do we have to draw additional decorations? |
| 661 | if (decorations) |
| 662 | { |
| 663 | // account for the checkbox |
| 664 | if (mi->is_checked()) |
| 665 | machine().ui().draw_text_full(container(), CHECKMARK, x0, y0, 1.0f - x0, JUSTIFY_LEFT, WRAP_WORD, DRAW_NORMAL, adjust_color(fgcolor), adjust_color(bgcolor)); |
| 666 | x0 += m_checkmark_width; |
| 667 | |
| 668 | // expanders? |
| 669 | if (mi->child()) |
| 670 | { |
| 671 | float lr_arrow_width = 0.4f * (y1 - y0) * machine().render().ui_aspect(); |
| 672 | ui_menu::draw_arrow( |
| 673 | container(), |
| 674 | x1 - lr_arrow_width, |
| 675 | y0 + (0.1f * (y1 - y0)), |
| 676 | x1, |
| 677 | y0 + (0.9f * (y1 - y0)), |
| 678 | adjust_color(fgcolor), |
| 679 | ROT90); |
| 680 | } |
| 681 | |
| 682 | // shortcut? |
| 683 | machine().ui().draw_text_full( |
| 684 | container(), |
| 685 | mi->shortcut_text(), |
| 686 | x0, |
| 687 | y0, |
| 688 | x1 - x0, |
| 689 | JUSTIFY_RIGHT, |
| 690 | WRAP_WORD, |
| 691 | DRAW_NORMAL, |
| 692 | adjust_color(fgcolor), |
| 693 | adjust_color(bgcolor)); |
| 694 | } |
| 695 | |
| 696 | tabbed_text_iterator iter(mi->text()); |
| 697 | while(iter.next()) |
| 698 | { |
| 699 | machine().ui().draw_text_full(container(), iter.current(), x0, y0, 1.0f - x0, JUSTIFY_LEFT, WRAP_WORD, DRAW_NORMAL, adjust_color(fgcolor), adjust_color(bgcolor)); |
| 700 | if (column_widths != NULL) |
| 701 | x0 += column_widths[iter.index()]; |
| 702 | } |
| 703 | } |
| 704 | |
| 705 | |
| 706 | //------------------------------------------------- |
| 707 | // find_mouse |
| 708 | //------------------------------------------------- |
| 709 | |
| 710 | bool ui_menubar::find_mouse(float &mouse_x, float &mouse_y, bool &mouse_button) |
| 711 | { |
| 712 | bool result = false; |
| 713 | mouse_x = -1; |
| 714 | mouse_y = -1; |
| 715 | |
| 716 | INT32 mouse_target_x, mouse_target_y; |
| 717 | render_target *mouse_target = ui_input_find_mouse(machine(), &mouse_target_x, &mouse_target_y, &mouse_button); |
| 718 | if (mouse_target != NULL) |
| 719 | { |
| 720 | if (mouse_target->map_point_container(mouse_target_x, mouse_target_y, *container(), mouse_x, mouse_y)) |
| 721 | result = true; |
| 722 | } |
| 723 | |
| 724 | return result; |
| 725 | } |
| 726 | |
| 727 | |
| 728 | //------------------------------------------------- |
| 729 | // get_menubar_visibility |
| 730 | //------------------------------------------------- |
| 731 | |
| 732 | ui_menubar::menubar_visibility_t ui_menubar::get_menubar_visibility() |
| 733 | { |
| 734 | menubar_visibility_t result; |
| 735 | |
| 736 | // is the mouse in the menu bar? |
| 737 | bool in_menu_bar = (m_mouse_y >= 0) && (m_mouse_y <= machine().ui().get_line_height()); |
| 738 | |
| 739 | // did we recently move the mouse? |
| 740 | bool recently_moved = (m_last_mouse_move != 0) |
| 741 | && ((osd_ticks() - m_last_mouse_move) * 5 / osd_ticks_per_second() < 1); |
| 742 | |
| 743 | // make the choice |
| 744 | if ((m_selected_item != NULL) || (m_active_item != NULL)) |
| 745 | result = MENUBAR_VISIBILITY_VISIBLE; |
| 746 | else if (in_menu_bar || recently_moved) |
| 747 | result = MENUBAR_VISIBILITY_TRANSLUCENT; |
| 748 | else |
| 749 | result = MENUBAR_VISIBILITY_INVISIBLE; |
| 750 | |
| 751 | return result; |
| 752 | } |
| 753 | |
| 754 | |
| 755 | //------------------------------------------------- |
| 756 | // adjust_color |
| 757 | //------------------------------------------------- |
| 758 | |
| 759 | rgb_t ui_menubar::adjust_color(rgb_t color) |
| 760 | { |
| 761 | switch(m_menubar_visibility) |
| 762 | { |
| 763 | case MENUBAR_VISIBILITY_INVISIBLE: |
| 764 | color = rgb_t(0, 0, 0, 0); |
| 765 | break; |
| 766 | |
| 767 | case MENUBAR_VISIBILITY_TRANSLUCENT: |
| 768 | color = rgb_t( |
| 769 | color.a() / 4, |
| 770 | color.r(), |
| 771 | color.g(), |
| 772 | color.b()); |
| 773 | break; |
| 774 | |
| 775 | case MENUBAR_VISIBILITY_VISIBLE: |
| 776 | default: |
| 777 | // do nothing |
| 778 | break; |
| 779 | } |
| 780 | return color; |
| 781 | } |
| 782 | |
| 783 | |
| 784 | //************************************************************************** |
| 785 | // MENU ITEMS |
| 786 | //************************************************************************** |
| 787 | |
| 788 | //------------------------------------------------- |
| 789 | // menu_item::ctor |
| 790 | //------------------------------------------------- |
| 791 | |
| 792 | ui_menubar::menu_item::menu_item(ui_menubar &menubar, const char *text, ui_menubar::menu_item *parent, bool is_invokable, int shortcut) |
| 793 | : m_menubar(menubar) |
| 794 | { |
| 795 | if (text != NULL) |
| 796 | m_text.cpy(text); |
| 797 | m_is_invokable = is_invokable; |
| 798 | m_parent = parent; |
| 799 | m_first_child = NULL; |
| 800 | m_last_child = NULL; |
| 801 | m_previous = NULL; |
| 802 | m_next = NULL; |
| 803 | m_is_checked = false; |
| 804 | m_is_enabled = true; |
| 805 | m_is_separator = false; |
| 806 | m_shortcut = shortcut; |
| 807 | m_shortcut_text_width = -1; |
| 808 | clear_area(); |
| 809 | } |
| 810 | |
| 811 | |
| 812 | //------------------------------------------------- |
| 813 | // menu_item::dtor |
| 814 | //------------------------------------------------- |
| 815 | |
| 816 | ui_menubar::menu_item::~menu_item() |
| 817 | { |
| 818 | menu_item *mi = m_first_child; |
| 819 | while (mi) |
| 820 | { |
| 821 | menu_item *next = mi->m_next; |
| 822 | delete mi; |
| 823 | mi = next; |
| 824 | } |
| 825 | } |
| 826 | |
| 827 | |
| 828 | //------------------------------------------------- |
| 829 | // menu_item::set_area |
| 830 | //------------------------------------------------- |
| 831 | |
| 832 | void ui_menubar::menu_item::set_area(float x0, float y0, float x1, float y1) |
| 833 | { |
| 834 | m_x0 = x0; |
| 835 | m_y0 = y0; |
| 836 | m_x1 = x1; |
| 837 | m_y1 = y1; |
| 838 | } |
| 839 | |
| 840 | |
| 841 | //------------------------------------------------- |
| 842 | // menu_item::clear_area_recursive |
| 843 | //------------------------------------------------- |
| 844 | |
| 845 | void ui_menubar::menu_item::clear_area_recursive() |
| 846 | { |
| 847 | clear_area(); |
| 848 | if (m_first_child) |
| 849 | m_first_child->clear_area_recursive(); |
| 850 | if (m_next) |
| 851 | m_next->clear_area_recursive(); |
| 852 | } |
| 853 | |
| 854 | |
| 855 | //------------------------------------------------- |
| 856 | // menu_item::initialize |
| 857 | //------------------------------------------------- |
| 858 | |
| 859 | void ui_menubar::menu_item::initialize(ui_menubar::menu_item &child) |
| 860 | { |
| 861 | // link this back to the previous item |
| 862 | child.m_previous = m_last_child; |
| 863 | |
| 864 | // link the end of the chain to this new item |
| 865 | if (m_last_child) |
| 866 | m_last_child->m_next = &child; |
| 867 | else |
| 868 | m_first_child = &child; |
| 869 | |
| 870 | // this new child is now last in the chain |
| 871 | m_last_child = &child; |
| 872 | |
| 873 | // link this up into the shortcut list, if appropriate |
| 874 | if (child.shortcut() != 0) |
| 875 | { |
| 876 | child.set_next_with_shortcut(m_menubar.m_shortcuted_menu_items); |
| 877 | m_menubar.m_shortcuted_menu_items = &child; |
| 878 | } |
| 879 | } |
| 880 | |
| 881 | |
| 882 | //------------------------------------------------- |
| 883 | // menu_item::append |
| 884 | //------------------------------------------------- |
| 885 | |
| 886 | ui_menubar::menu_item &ui_menubar::menu_item::append(const char *text) |
| 887 | { |
| 888 | menu_item *child = new menu_item(m_menubar, text, this); |
| 889 | initialize(*child); |
| 890 | return *child; |
| 891 | } |
| 892 | |
| 893 | |
| 894 | //------------------------------------------------- |
| 895 | // menu_item::append_separator |
| 896 | //------------------------------------------------- |
| 897 | |
| 898 | void ui_menubar::menu_item::append_separator() |
| 899 | { |
| 900 | menu_item &separator = append("-"); |
| 901 | separator.set_enabled(false); |
| 902 | separator.m_is_separator = true; |
| 903 | } |
| 904 | |
| 905 | |
| 906 | //------------------------------------------------- |
| 907 | // menu_item::find_point |
| 908 | //------------------------------------------------- |
| 909 | |
| 910 | ui_menubar::menu_item *ui_menubar::menu_item::find_point(float x, float y) |
| 911 | { |
| 912 | menu_item *result = NULL; |
| 913 | |
| 914 | if (m_is_enabled && (x >= m_x0) && (y >= m_y0) && (x <= m_x1) && (y <= m_y1)) |
| 915 | result = this; |
| 916 | |
| 917 | if (!result && m_first_child) |
| 918 | result = m_first_child->find_point(x, y); |
| 919 | if (!result && m_next) |
| 920 | result = m_next->find_point(x, y); |
| 921 | return result; |
| 922 | } |
| 923 | |
| 924 | |
| 925 | //------------------------------------------------- |
| 926 | // menu_item::find_child |
| 927 | //------------------------------------------------- |
| 928 | |
| 929 | ui_menubar::menu_item &ui_menubar::menu_item::find_child(const char *target) |
| 930 | { |
| 931 | menu_item *item = find_child_internal(target); |
| 932 | assert(item != NULL); |
| 933 | return *item; |
| 934 | } |
| 935 | |
| 936 | |
| 937 | //------------------------------------------------- |
| 938 | // menu_item::find_child_internal |
| 939 | //------------------------------------------------- |
| 940 | |
| 941 | ui_menubar::menu_item *ui_menubar::menu_item::find_child_internal(const char *target) |
| 942 | { |
| 943 | if (!strcmp(target, text())) |
| 944 | return this; |
| 945 | |
| 946 | for(menu_item *item = child(); item != NULL; item = item->next()) |
| 947 | { |
| 948 | menu_item *result = item->find_child_internal(target); |
| 949 | if (result != NULL) |
| 950 | return result; |
| 951 | } |
| 952 | return NULL; |
| 953 | } |
| 954 | |
| 955 | |
| 956 | //------------------------------------------------- |
| 957 | // menu_item::shortcut_text |
| 958 | //------------------------------------------------- |
| 959 | |
| 960 | const char *ui_menubar::menu_item::shortcut_text() |
| 961 | { |
| 962 | // do we have to calculate this stuff? |
| 963 | if (m_shortcut_text_width < 0) |
| 964 | { |
| 965 | // clear the text |
| 966 | m_shortcut_text.cpy(""); |
| 967 | |
| 968 | // first, do we even have a shortcut? |
| 969 | if (shortcut() != 0) |
| 970 | { |
| 971 | // iterate over the input ports and add menu items |
| 972 | for (input_type_entry *entry = m_menubar.machine().ioport().first_type(); entry != NULL; entry = entry->next()) |
| 973 | { |
| 974 | // add if we match the group and we have a valid name */ |
| 975 | if (entry->group() == IPG_UI_SHORTCUT && entry->name() != NULL && entry->name()[0] != 0 && entry->type() == shortcut()) |
| 976 | { |
| 977 | const input_seq &seq = m_menubar.machine().ioport().type_seq(entry->type(), entry->player(), SEQ_TYPE_STANDARD); |
| 978 | sensible_seq_name(m_shortcut_text, seq); |
| 979 | break; |
| 980 | } |
| 981 | } |
| 982 | } |
| 983 | |
| 984 | // finally calculate the text width |
| 985 | m_shortcut_text_width = m_menubar.machine().ui().get_string_width(m_shortcut_text); |
| 986 | } |
| 987 | |
| 988 | // return the text |
| 989 | return m_shortcut_text; |
| 990 | } |
| 991 | |
| 992 | |
| 993 | //------------------------------------------------- |
| 994 | // menu_item::shortcut_text_width |
| 995 | //------------------------------------------------- |
| 996 | |
| 997 | float ui_menubar::menu_item::shortcut_text_width() |
| 998 | { |
| 999 | // force a calculation, if we didn't have one |
| 1000 | shortcut_text(); |
| 1001 | |
| 1002 | // and return the text width |
| 1003 | return m_shortcut_text_width; |
| 1004 | } |
| 1005 | |
| 1006 | |
| 1007 | //------------------------------------------------- |
| 1008 | // menu_item::sensible_seq_name |
| 1009 | //------------------------------------------------- |
| 1010 | |
| 1011 | void ui_menubar::menu_item::sensible_seq_name(astring &text, const input_seq &seq) |
| 1012 | { |
| 1013 | // special case; we don't want 'None' |
| 1014 | if (seq[0] == input_seq::end_code) |
| 1015 | m_shortcut_text.cpy(""); |
| 1016 | else |
| 1017 | m_menubar.machine().input().seq_name(m_shortcut_text, seq); |
| 1018 | } |
| 1019 | |
| 1020 | |
| 1021 | //------------------------------------------------- |
| 1022 | // menu_item::is_child_of |
| 1023 | //------------------------------------------------- |
| 1024 | |
| 1025 | bool ui_menubar::menu_item::is_child_of(ui_menubar::menu_item *that) const |
| 1026 | { |
| 1027 | for(menu_item *mi = m_parent; mi != NULL; mi = mi->m_parent) |
| 1028 | { |
| 1029 | if (mi == that) |
| 1030 | return true; |
| 1031 | } |
| 1032 | return false; |
| 1033 | } |
| 1034 | |
| 1035 | |
| 1036 | //------------------------------------------------- |
| 1037 | // menu_item::invoke |
| 1038 | //------------------------------------------------- |
| 1039 | |
| 1040 | void ui_menubar::menu_item::invoke() |
| 1041 | { |
| 1042 | // do nothing |
| 1043 | } |
| 1044 | |
| 1045 | |
| 1046 | //************************************************************************** |
| 1047 | // TABBED TEXT ITERATOR |
| 1048 | //************************************************************************** |
| 1049 | |
| 1050 | //------------------------------------------------- |
| 1051 | // tabbed_text_iterator::ctor |
| 1052 | //------------------------------------------------- |
| 1053 | |
| 1054 | tabbed_text_iterator::tabbed_text_iterator(const char *text) |
| 1055 | { |
| 1056 | m_text = text; |
| 1057 | m_current = NULL; |
| 1058 | m_position = 0; |
| 1059 | m_index = -1; |
| 1060 | } |
| 1061 | |
| 1062 | |
| 1063 | //------------------------------------------------- |
| 1064 | // tabbed_text_iterator::next |
| 1065 | //------------------------------------------------- |
| 1066 | |
| 1067 | bool tabbed_text_iterator::next() |
| 1068 | { |
| 1069 | const char *current_text = &m_text[m_position]; |
| 1070 | const char *tabpos = strchr(current_text, '\t'); |
| 1071 | |
| 1072 | if (tabpos != NULL) |
| 1073 | { |
| 1074 | int count = tabpos - current_text; |
| 1075 | m_buffer.cpy(current_text, count); |
| 1076 | m_position += count + 1; |
| 1077 | m_current = m_buffer; |
| 1078 | m_index++; |
| 1079 | } |
| 1080 | else if (*current_text != '\0') |
| 1081 | { |
| 1082 | m_current = current_text; |
| 1083 | m_position += strlen(m_current); |
| 1084 | m_index++; |
| 1085 | } |
| 1086 | else |
| 1087 | { |
| 1088 | m_current = NULL; |
| 1089 | } |
| 1090 | return m_current != NULL; |
| 1091 | } |
trunk/src/emu/ui/menubar.h
| r0 | r29578 | |
| 1 | /*************************************************************************** |
| 2 | |
| 3 | menubar.h |
| 4 | |
| 5 | Internal MAME menu bar for the user interface. |
| 6 | |
| 7 | Copyright Nicola Salmoria and the MAME Team. |
| 8 | Visit http://mamedev.org for licensing and usage restrictions. |
| 9 | |
| 10 | ***************************************************************************/ |
| 11 | |
| 12 | #pragma once |
| 13 | |
| 14 | #ifndef __UI_MENUBAR_H__ |
| 15 | #define __UI_MENUBAR_H__ |
| 16 | |
| 17 | #include "render.h" |
| 18 | |
| 19 | |
| 20 | //************************************************************************** |
| 21 | // MENU BAR |
| 22 | //************************************************************************** |
| 23 | |
| 24 | class ui_menubar |
| 25 | { |
| 26 | public: |
| 27 | ui_menubar(running_machine &machine); |
| 28 | virtual ~ui_menubar(); |
| 29 | |
| 30 | // menu item |
| 31 | class menu_item |
| 32 | { |
| 33 | public: |
| 34 | menu_item(ui_menubar &menubar, const char *text = NULL, menu_item *parent = NULL, bool is_invokable = false, int shortcut = 0); |
| 35 | virtual ~menu_item(); |
| 36 | |
| 37 | // methods |
| 38 | menu_item &append(const char *text); |
| 39 | void append_separator(); |
| 40 | bool is_child_of(menu_item *that) const; |
| 41 | virtual void invoke(); |
| 42 | void clear_area_recursive(); |
| 43 | menu_item *find_point(float x, float y); |
| 44 | menu_item &find_child(const char *target); |
| 45 | const char *shortcut_text(); |
| 46 | float shortcut_text_width(); |
| 47 | void sensible_seq_name(astring &text, const input_seq &seq); |
| 48 | |
| 49 | // template methods; look I tried to use delegate.h but I got humbled... |
| 50 | template<class _Target> menu_item &append(const char *text, void (_Target::*callback)(), _Target &obj, int shortcut = 0) |
| 51 | { |
| 52 | menu_item *child = new invokable_menu_item<_Target>(m_menubar, text, this, callback, obj, shortcut); |
| 53 | initialize(*child); |
| 54 | return *child; |
| 55 | } |
| 56 | template<class _Target, typename _Arg> menu_item &append(const char *text, void (_Target::*callback)(_Arg), _Target &obj, _Arg arg, int shortcut = 0) |
| 57 | { |
| 58 | menu_item *child = new arg_invokable_menu_item<_Target, _Arg>(m_menubar, text, this, callback, obj, arg, shortcut); |
| 59 | initialize(*child); |
| 60 | return *child; |
| 61 | } |
| 62 | template<class _Target, typename _Arg1, typename _Arg2> menu_item &append(const char *text, void (_Target::*callback)(_Arg1, _Arg2), _Target &obj, _Arg1 arg1, _Arg2 arg2, int shortcut = 0) |
| 63 | { |
| 64 | menu_item *child = new arg2_invokable_menu_item<_Target, _Arg1, _Arg2>(m_menubar, text, this, callback, obj, arg1, arg2, shortcut); |
| 65 | initialize(*child); |
| 66 | return *child; |
| 67 | } |
| 68 | template<class _Target> menu_item &append(const char *text, void (_Target::*set_callback)(bool), bool (_Target::*get_callback)() const, _Target &obj, int shortcut = 0) |
| 69 | { |
| 70 | // tailored for a toggle |
| 71 | bool current_value = ((obj).*(get_callback))(); |
| 72 | menu_item &menu = append(text, set_callback, obj, !current_value, shortcut); |
| 73 | menu.set_checked(current_value); |
| 74 | return menu; |
| 75 | } |
| 76 | template<class _Target, typename _Arg> menu_item &append(const char *text, void (_Target::*set_callback)(_Arg), _Arg (_Target::*get_callback)() const, _Target &obj, _Arg arg, int shortcut = 0) |
| 77 | { |
| 78 | // tailored for a set operation |
| 79 | _Arg current_value = ((obj).*(get_callback))(); |
| 80 | menu_item &menu = append(text, set_callback, obj, arg, shortcut); |
| 81 | menu.set_checked(current_value == arg); |
| 82 | return menu; |
| 83 | } |
| 84 | |
| 85 | // getters |
| 86 | bool is_empty() const { return !m_first_child; } |
| 87 | bool is_invokable() const { return m_is_invokable; } |
| 88 | bool is_checked() const { return m_is_checked; } |
| 89 | bool is_enabled() const { return m_is_enabled; } |
| 90 | bool is_separator() const { return m_is_separator; } |
| 91 | bool has_children() const { return m_first_child ? true : false; } |
| 92 | int shortcut() const { return m_shortcut; } |
| 93 | const astring &text() const { return m_text; } |
| 94 | menu_item *parent() { return m_parent; } |
| 95 | menu_item *child() { return m_first_child; } |
| 96 | menu_item *last_child() { return m_last_child; } |
| 97 | menu_item *previous() { return m_previous; } |
| 98 | menu_item *next() { return m_next; } |
| 99 | menu_item *next_with_shortcut() { return m_next_with_shortcut; } |
| 100 | bool is_sub_menu() const { return m_parent && m_parent->m_parent; } |
| 101 | |
| 102 | // setters |
| 103 | void set_area(float x0, float y0, float x1, float y1); |
| 104 | void clear_area() { set_area(-1, -1, -1, -1); } |
| 105 | void set_checked(bool checked) { m_is_checked = checked; } |
| 106 | void set_enabled(bool enabled) { m_is_enabled = enabled; } |
| 107 | void set_text(const char *text) { m_text.cpy(text); } |
| 108 | void set_next_with_shortcut(menu_item *item) { m_next_with_shortcut = item; } |
| 109 | |
| 110 | private: |
| 111 | // private variables |
| 112 | ui_menubar & m_menubar; |
| 113 | astring m_text; |
| 114 | int m_shortcut; |
| 115 | astring m_shortcut_text; |
| 116 | float m_shortcut_text_width; |
| 117 | bool m_is_invokable; |
| 118 | bool m_is_checked; |
| 119 | bool m_is_enabled; |
| 120 | bool m_is_separator; |
| 121 | menu_item * m_parent; |
| 122 | menu_item * m_first_child; |
| 123 | menu_item * m_last_child; |
| 124 | menu_item * m_previous; |
| 125 | menu_item * m_next; |
| 126 | menu_item * m_next_with_shortcut; |
| 127 | float m_x0; |
| 128 | float m_y0; |
| 129 | float m_x1; |
| 130 | float m_y1; |
| 131 | |
| 132 | // private methods |
| 133 | void initialize(menu_item &child); |
| 134 | menu_item *find_child_internal(const char *target); |
| 135 | }; |
| 136 | |
| 137 | // methods |
| 138 | virtual void reset(); |
| 139 | virtual void handle(render_container *container); |
| 140 | |
| 141 | // getters |
| 142 | bool is_visible() const { return m_menubar_visibility != MENUBAR_VISIBILITY_INVISIBLE; } |
| 143 | bool has_selection() const { return m_selected_item != NULL; } |
| 144 | menu_item &root_menu() { return m_menus; } |
| 145 | |
| 146 | protected: |
| 147 | // implemented by child classes |
| 148 | virtual void menubar_build_menus() = 0; |
| 149 | virtual void menubar_draw_ui_elements() = 0; |
| 150 | |
| 151 | // accessors |
| 152 | running_machine &machine() { return m_machine; } |
| 153 | render_container *container() { return m_container; } |
| 154 | |
| 155 | private: |
| 156 | // classes |
| 157 | template<class _Target> |
| 158 | class invokable_menu_item : public menu_item |
| 159 | { |
| 160 | public: |
| 161 | invokable_menu_item(ui_menubar &menubar, const char *name, menu_item *parent, void (_Target::*callback)(), _Target &obj, int shortcut) |
| 162 | : menu_item(menubar, name, parent, true, shortcut), m_callback(callback), m_obj(obj) |
| 163 | { |
| 164 | } |
| 165 | |
| 166 | virtual void invoke() { ((m_obj).*(m_callback))(); } |
| 167 | |
| 168 | private: |
| 169 | void (_Target::*m_callback)(); |
| 170 | _Target &m_obj; |
| 171 | }; |
| 172 | |
| 173 | template<class _Target, typename _Arg> |
| 174 | class arg_invokable_menu_item : public menu_item |
| 175 | { |
| 176 | public: |
| 177 | arg_invokable_menu_item(ui_menubar &menubar, const char *name, menu_item *parent, void (_Target::*callback)(_Arg), _Target &obj, _Arg arg, int shortcut) |
| 178 | : menu_item(menubar, name, parent, true, shortcut), m_callback(callback), m_obj(obj), m_arg(arg) |
| 179 | { |
| 180 | } |
| 181 | |
| 182 | virtual void invoke() { ((m_obj).*(m_callback))(m_arg); } |
| 183 | |
| 184 | private: |
| 185 | void (_Target::*m_callback)(_Arg); |
| 186 | _Target &m_obj; |
| 187 | _Arg m_arg; |
| 188 | }; |
| 189 | |
| 190 | template<class _Target, typename _Arg1, typename _Arg2> |
| 191 | class arg2_invokable_menu_item : public menu_item |
| 192 | { |
| 193 | public: |
| 194 | arg2_invokable_menu_item(ui_menubar &menubar, const char *name, menu_item *parent, void (_Target::*callback)(_Arg1, _Arg2), _Target &obj, _Arg1 arg1, _Arg2 arg2, int shortcut) |
| 195 | : menu_item(menubar, name, parent, true, shortcut), m_callback(callback), m_obj(obj), m_arg1(arg1), m_arg2(arg2) |
| 196 | { |
| 197 | } |
| 198 | |
| 199 | virtual void invoke() { ((m_obj).*(m_callback))(m_arg1, m_arg2); } |
| 200 | |
| 201 | private: |
| 202 | void (_Target::*m_callback)(_Arg1, _Arg2); |
| 203 | _Target &m_obj; |
| 204 | _Arg1 m_arg1; |
| 205 | _Arg2 m_arg2; |
| 206 | }; |
| 207 | |
| 208 | // menubar visibility |
| 209 | enum menubar_visibility_t |
| 210 | { |
| 211 | MENUBAR_VISIBILITY_INVISIBLE, |
| 212 | MENUBAR_VISIBILITY_TRANSLUCENT, |
| 213 | MENUBAR_VISIBILITY_VISIBLE |
| 214 | }; |
| 215 | |
| 216 | // instance variables |
| 217 | running_machine & m_machine; |
| 218 | render_container * m_container; |
| 219 | menu_item m_menus; // the root menu item |
| 220 | menu_item * m_shortcuted_menu_items; // list of menu items with shortcuts |
| 221 | menu_item * m_selected_item; // current selection |
| 222 | menu_item * m_active_item; // active menu item |
| 223 | bool m_dragged; // have we dragged over at least one item? |
| 224 | float m_mouse_x, m_mouse_y; |
| 225 | bool m_mouse_button; |
| 226 | float m_checkmark_width; |
| 227 | osd_ticks_t m_last_mouse_move; |
| 228 | menubar_visibility_t m_menubar_visibility; |
| 229 | bool m_first_time; |
| 230 | |
| 231 | // selection walking |
| 232 | bool walk_selection_previous(); |
| 233 | bool walk_selection_next(); |
| 234 | bool walk_selection_child(); |
| 235 | bool walk_selection_parent(); |
| 236 | bool walk_selection_escape(); |
| 237 | bool walk_selection_previous_sub_menu(); |
| 238 | bool walk_selection_next_sub_menu(); |
| 239 | |
| 240 | // miscellaneous |
| 241 | void draw_child_menu(menu_item *menu, float x, float y); |
| 242 | bool is_child_menu_visible(menu_item *menu) const; |
| 243 | void draw_menu_item_text(menu_item *mi, float x0, float y0, float x1, float y1, bool decorations, const float *column_widths = NULL); |
| 244 | bool event_loop(); |
| 245 | bool poll_navigation_keys(); |
| 246 | bool poll_shortcut_keys(bool swallow); |
| 247 | bool input_pressed_safe(int key); |
| 248 | void toggle_selection(); |
| 249 | void invoke(menu_item *menu); |
| 250 | bool find_mouse(float &mouse_x, float &mouse_y, bool &mouse_button); |
| 251 | menubar_visibility_t get_menubar_visibility(); |
| 252 | rgb_t adjust_color(rgb_t color); |
| 253 | }; |
| 254 | |
| 255 | |
| 256 | #endif /* __UI_MENUBAR_H__ */ |
trunk/src/emu/ui/emenubar.c
| r0 | r29578 | |
| 1 | /*************************************************************************** |
| 2 | |
| 3 | emenubar.c |
| 4 | |
| 5 | Internal MAME menu bar for the user interface. |
| 6 | |
| 7 | Copyright Nicola Salmoria and the MAME Team. |
| 8 | Visit http://mamedev.org for licensing and usage restrictions. |
| 9 | |
| 10 | ***************************************************************************/ |
| 11 | |
| 12 | #include "emu.h" |
| 13 | #include "ui/emenubar.h" |
| 14 | #include "ui/selgame.h" |
| 15 | #include "ui/miscmenu.h" |
| 16 | #include "ui/filesel.h" |
| 17 | #include "ui/imginfo.h" |
| 18 | #include "ui/tapectrl.h" |
| 19 | #include "ui/bbcontrl.h" |
| 20 | #include "ui/swlist.h" |
| 21 | #include "ui/viewgfx.h" |
| 22 | #include "ui/barcode.h" |
| 23 | #include "softlist.h" |
| 24 | #include "cheat.h" |
| 25 | |
| 26 | |
| 27 | //************************************************************************** |
| 28 | // CONSTANTS |
| 29 | //************************************************************************** |
| 30 | |
| 31 | #ifdef MAME_PROFILER |
| 32 | #define HAS_PROFILER 1 |
| 33 | #else // !MAME_PROFILER |
| 34 | #define HAS_PROFILER 0 |
| 35 | #endif // MAME_PROFILER |
| 36 | |
| 37 | |
| 38 | //************************************************************************** |
| 39 | // MENUBAR IMPLEMENTATION |
| 40 | //************************************************************************** |
| 41 | |
| 42 | astring ui_emu_menubar::s_softlist_result; |
| 43 | device_image_interface *ui_emu_menubar::s_softlist_image; |
| 44 | |
| 45 | |
| 46 | //------------------------------------------------- |
| 47 | // ctor |
| 48 | //------------------------------------------------- |
| 49 | |
| 50 | ui_emu_menubar::ui_emu_menubar(running_machine &machine) |
| 51 | : ui_menubar(machine) |
| 52 | { |
| 53 | } |
| 54 | |
| 55 | |
| 56 | //------------------------------------------------- |
| 57 | // handle |
| 58 | //------------------------------------------------- |
| 59 | |
| 60 | void ui_emu_menubar::handle(render_container *container) |
| 61 | { |
| 62 | // check to see if we have a softlist selection |
| 63 | if (s_softlist_result.len() > 0) |
| 64 | { |
| 65 | // do the load |
| 66 | s_softlist_image->load(s_softlist_result); |
| 67 | |
| 68 | // clear out state |
| 69 | s_softlist_image = NULL; |
| 70 | s_softlist_result.reset(); |
| 71 | } |
| 72 | |
| 73 | // call inherited method |
| 74 | ui_menubar::handle(container); |
| 75 | } |
| 76 | |
| 77 | |
| 78 | //------------------------------------------------- |
| 79 | // start_menu |
| 80 | //------------------------------------------------- |
| 81 | |
| 82 | void ui_emu_menubar::start_menu(ui_menu *menu) |
| 83 | { |
| 84 | machine().ui().set_handler(ui_menu::ui_handler, 0); |
| 85 | ui_menu::stack_push(menu); |
| 86 | } |
| 87 | |
| 88 | |
| 89 | //------------------------------------------------- |
| 90 | // start_menu |
| 91 | //------------------------------------------------- |
| 92 | |
| 93 | template<class _Menu> |
| 94 | void ui_emu_menubar::start_menu() |
| 95 | { |
| 96 | start_menu(auto_alloc_clear(machine(), _Menu(machine(), container()))); |
| 97 | } |
| 98 | |
| 99 | |
| 100 | //------------------------------------------------- |
| 101 | // menubar_draw_ui_elements |
| 102 | //------------------------------------------------- |
| 103 | |
| 104 | void ui_emu_menubar::menubar_draw_ui_elements() |
| 105 | { |
| 106 | // first draw the FPS counter |
| 107 | if (machine().ui().show_fps_counter()) |
| 108 | { |
| 109 | astring tempstring; |
| 110 | machine().ui().draw_text_full(container(), machine().video().speed_text(tempstring), 0.0f, 0.0f, 1.0f, |
| 111 | JUSTIFY_RIGHT, WRAP_WORD, DRAW_OPAQUE, ARGB_WHITE, ARGB_BLACK, NULL, NULL); |
| 112 | } |
| 113 | |
| 114 | // draw the profiler if visible |
| 115 | if (machine().ui().show_profiler()) |
| 116 | { |
| 117 | const char *text = g_profiler.text(machine()); |
| 118 | machine().ui().draw_text_full(container(), text, 0.0f, 0.0f, 1.0f, JUSTIFY_LEFT, WRAP_WORD, DRAW_OPAQUE, ARGB_WHITE, ARGB_BLACK, NULL, NULL); |
| 119 | } |
| 120 | |
| 121 | // check for fast forward |
| 122 | if (machine().ioport().type_pressed(IPT_UI_FAST_FORWARD)) |
| 123 | { |
| 124 | machine().video().set_fastforward(true); |
| 125 | machine().ui().show_fps_temp(0.5); |
| 126 | } |
| 127 | else |
| 128 | machine().video().set_fastforward(false); |
| 129 | |
| 130 | } |
| 131 | |
| 132 | |
| 133 | //------------------------------------------------- |
| 134 | // menubar_build_menus |
| 135 | //------------------------------------------------- |
| 136 | |
| 137 | void ui_emu_menubar::menubar_build_menus() |
| 138 | { |
| 139 | // build normal menus |
| 140 | build_file_menu(); |
| 141 | if (has_images()) |
| 142 | build_images_menu(); |
| 143 | build_options_menu(); |
| 144 | build_settings_menu(); |
| 145 | build_help_menu(); |
| 146 | |
| 147 | // and customize them |
| 148 | machine().osd().customize_menubar(*this); |
| 149 | } |
| 150 | |
| 151 | |
| 152 | //------------------------------------------------- |
| 153 | // build_file_menu |
| 154 | //------------------------------------------------- |
| 155 | |
| 156 | void ui_emu_menubar::build_file_menu() |
| 157 | { |
| 158 | astring menu_text; |
| 159 | menu_item &file_menu = root_menu().append("File"); |
| 160 | |
| 161 | // show gfx |
| 162 | if (ui_gfx_is_relevant(machine())) |
| 163 | file_menu.append("Show Graphics/Palette...", &ui_emu_menubar::set_ui_handler, *this, ui_gfx_ui_handler, (UINT32) machine().paused(), IPT_UI_SHOW_GFX); |
| 164 | |
| 165 | // save screen snapshot |
| 166 | file_menu.append("Save Screen Snapshot(s)", &video_manager::save_active_screen_snapshots, machine().video(), IPT_UI_SNAPSHOT); |
| 167 | |
| 168 | // record movie |
| 169 | menu_item &record_movie_menu = file_menu.append("Record Movie", &video_manager::toggle_record_movie, machine().video(), IPT_UI_RECORD_MOVIE); |
| 170 | record_movie_menu.set_checked(machine().video().is_recording()); |
| 171 | |
| 172 | // save state |
| 173 | file_menu.append("Save State...", &ui_emu_menubar::set_ui_handler, *this, ui_manager::ui_handler_load_save, (UINT32) LOADSAVE_SAVE, IPT_UI_SAVE_STATE); |
| 174 | |
| 175 | // load state |
| 176 | file_menu.append("Load State...", &ui_emu_menubar::set_ui_handler, *this, ui_manager::ui_handler_load_save, (UINT32) LOADSAVE_LOAD, IPT_UI_LOAD_STATE); |
| 177 | |
| 178 | // separator |
| 179 | file_menu.append_separator(); |
| 180 | |
| 181 | // paste |
| 182 | if (machine().ioport().has_keyboard() && machine().ioport().natkeyboard().can_post()) |
| 183 | { |
| 184 | menu_item &paste_menu = file_menu.append("Paste", &ui_manager::paste, machine().ui(), IPT_UI_PASTE); |
| 185 | paste_menu.set_enabled(machine().ui().can_paste()); |
| 186 | } |
| 187 | |
| 188 | // pause |
| 189 | menu_item &pause_menu = file_menu.append("Pause", &running_machine::toggle_pause, machine(), IPT_UI_PAUSE); |
| 190 | pause_menu.set_checked(machine().paused()); |
| 191 | |
| 192 | // reset |
| 193 | menu_item &reset_menu = file_menu.append("Reset"); |
| 194 | reset_menu.append("Hard", &running_machine::schedule_hard_reset, machine(), IPT_UI_RESET_MACHINE); |
| 195 | reset_menu.append("Soft", &running_machine::schedule_soft_reset, machine(), IPT_UI_SOFT_RESET); |
| 196 | |
| 197 | // separator |
| 198 | file_menu.append_separator(); |
| 199 | |
| 200 | // select new game |
| 201 | menu_text.printf("Select New %s...", emulator_info::get_capstartgamenoun()); |
| 202 | file_menu.append(menu_text, &ui_emu_menubar::select_new_game, *this); |
| 203 | |
| 204 | // exit |
| 205 | file_menu.append("Exit", &ui_manager::request_quit, machine().ui(), IPT_UI_EXIT); |
| 206 | } |
| 207 | |
| 208 | |
| 209 | //------------------------------------------------- |
| 210 | // build_images_menu |
| 211 | //------------------------------------------------- |
| 212 | |
| 213 | void ui_emu_menubar::build_images_menu() |
| 214 | { |
| 215 | // add the root "Images" menu |
| 216 | menu_item &images_menu = root_menu().append("Images"); |
| 217 | |
| 218 | // loop through all devices |
| 219 | image_interface_iterator iter(machine().root_device()); |
| 220 | for (device_image_interface *image = iter.first(); image != NULL; image = iter.next()) |
| 221 | { |
| 222 | bool is_loaded = image->basename() != NULL; |
| 223 | |
| 224 | astring buffer; |
| 225 | buffer.printf("%s (%s): \t%s", |
| 226 | image->device().name(), |
| 227 | image->brief_instance_name(), |
| 228 | is_loaded ? image->basename() : "[empty]"); |
| 229 | |
| 230 | // append the menu item for this device |
| 231 | menu_item &menu = images_menu.append(buffer); |
| 232 | |
| 233 | // software list |
| 234 | if (image->image_interface() != NULL) |
| 235 | { |
| 236 | if (build_software_list_menus(menu, image)) |
| 237 | menu.append_separator(); |
| 238 | } |
| 239 | |
| 240 | // load |
| 241 | menu.append("Load...", &ui_emu_menubar::load, *this, image); |
| 242 | |
| 243 | // unload |
| 244 | menu_item &unload_menu = menu.append("Unload", &device_image_interface::unload, *image); |
| 245 | unload_menu.set_enabled(is_loaded); |
| 246 | |
| 247 | // tape control |
| 248 | cassette_image_device *cassette = dynamic_cast<cassette_image_device *>(image); |
| 249 | if (cassette != NULL) |
| 250 | { |
| 251 | menu_item &control_menu = menu.append("Tape Control...", &ui_emu_menubar::tape_control, *this, cassette); |
| 252 | control_menu.set_enabled(is_loaded); |
| 253 | } |
| 254 | |
| 255 | // bitbanger control |
| 256 | bitbanger_device *bitbanger = dynamic_cast<bitbanger_device *>(image); |
| 257 | if (bitbanger != NULL) |
| 258 | { |
| 259 | menu_item &control_menu = menu.append("Bitbanger Control...", &ui_emu_menubar::bitbanger_control, *this, bitbanger); |
| 260 | control_menu.set_enabled(is_loaded); |
| 261 | } |
| 262 | } |
| 263 | } |
| 264 | |
| 265 | |
| 266 | //------------------------------------------------- |
| 267 | // build_software_list_menus |
| 268 | //------------------------------------------------- |
| 269 | |
| 270 | bool ui_emu_menubar::build_software_list_menus(menu_item &menu, device_image_interface *image) |
| 271 | { |
| 272 | int item_count = 0; |
| 273 | menu_item *last_menu_item = NULL; |
| 274 | astring description; |
| 275 | softlist_type types[] = { SOFTWARE_LIST_ORIGINAL_SYSTEM, SOFTWARE_LIST_COMPATIBLE_SYSTEM }; |
| 276 | software_list_device_iterator softlist_iter(machine().config().root_device()); |
| 277 | |
| 278 | // first do "original system" softlists, then do compatible ones |
| 279 | for (int typenum = 0; typenum < ARRAY_LENGTH(types); typenum++) |
| 280 | { |
| 281 | for (software_list_device *swlist = softlist_iter.first(); swlist != NULL; swlist = softlist_iter.next()) |
| 282 | { |
| 283 | if ((swlist->list_type() == types[typenum]) && is_softlist_relevant(swlist, image->image_interface(), description)) |
| 284 | { |
| 285 | // we've found a softlist; append the menu item |
| 286 | last_menu_item = &menu.append(description, &ui_emu_menubar::select_from_software_list, *this, image, swlist); |
| 287 | item_count++; |
| 288 | } |
| 289 | } |
| 290 | } |
| 291 | |
| 292 | // if we only had one list, lets use a generic name |
| 293 | if (last_menu_item != NULL && (item_count == 1)) |
| 294 | last_menu_item->set_text("Software list..."); |
| 295 | |
| 296 | return item_count > 0; |
| 297 | } |
| 298 | |
| 299 | |
| 300 | //------------------------------------------------- |
| 301 | // build_options_menu |
| 302 | //------------------------------------------------- |
| 303 | |
| 304 | void ui_emu_menubar::build_options_menu() |
| 305 | { |
| 306 | astring menu_text; |
| 307 | menu_item &options_menu = root_menu().append("Options"); |
| 308 | |
| 309 | // throttle |
| 310 | float throttle_rates[] = { 10.0f, 5.0f, 2.0f, 1.0f, 0.5f, 0.2f, 0.1f, 0.0f }; |
| 311 | float current_throttle_rate = machine().video().throttled() |
| 312 | ? machine().video().throttle_rate() |
| 313 | : 0.0f; |
| 314 | menu_item &throttle_menu = options_menu.append("Throttle"); |
| 315 | for (int i = 0; i < ARRAY_LENGTH(throttle_rates); i++) |
| 316 | { |
| 317 | const char *item = "Unthrottled"; |
| 318 | if (throttle_rates[i] != 0) |
| 319 | { |
| 320 | menu_text.printf("%d%%", (int) (throttle_rates[i] * 100)); |
| 321 | item = menu_text; |
| 322 | } |
| 323 | |
| 324 | menu_item &menu = throttle_menu.append(item, &ui_emu_menubar::set_throttle_rate, *this, throttle_rates[i]); |
| 325 | menu.set_checked(current_throttle_rate == throttle_rates[i]); |
| 326 | } |
| 327 | |
| 328 | // frame skip |
| 329 | menu_item &frameskip_menu = options_menu.append("Frame Skip"); |
| 330 | for (int i = -1; i <= MAX_FRAMESKIP; i++) |
| 331 | { |
| 332 | const char *item = "Auto"; |
| 333 | if (i >= 0) |
| 334 | { |
| 335 | menu_text.printf("%d", i); |
| 336 | item = menu_text; |
| 337 | } |
| 338 | |
| 339 | menu_item &menu = frameskip_menu.append(item, &video_manager::set_frameskip, machine().video(), i); |
| 340 | menu.set_checked(machine().video().frameskip() == i); |
| 341 | } |
| 342 | |
| 343 | // separator |
| 344 | frameskip_menu.append_separator(); |
| 345 | |
| 346 | // increase |
| 347 | frameskip_menu.append("Increase", &ui_manager::increase_frameskip, machine().ui(), IPT_UI_FRAMESKIP_INC); |
| 348 | |
| 349 | // decrease |
| 350 | frameskip_menu.append("Decrease", &ui_manager::decrease_frameskip, machine().ui(), IPT_UI_FRAMESKIP_DEC); |
| 351 | |
| 352 | // show fps |
| 353 | options_menu.append("Show Frames Per Second", &ui_manager::set_show_fps, &ui_manager::show_fps, machine().ui(), IPT_UI_SHOW_FPS); |
| 354 | |
| 355 | // show profiler |
| 356 | if (HAS_PROFILER) |
| 357 | options_menu.append("Show Profiler", &ui_manager::set_show_profiler, &ui_manager::show_profiler, machine().ui(), IPT_UI_SHOW_PROFILER); |
| 358 | |
| 359 | // video |
| 360 | // do different things if we actually have multiple render targets |
| 361 | menu_item &video_menu = options_menu.append("Video"); |
| 362 | if (machine().render().target_by_index(1) != NULL) |
| 363 | { |
| 364 | // multiple targets |
| 365 | int targetnum = 0; |
| 366 | render_target *target; |
| 367 | while((target = machine().render().target_by_index(targetnum)) != NULL) |
| 368 | { |
| 369 | astring buffer; |
| 370 | buffer.printf("Screen #%d", targetnum++); |
| 371 | menu_item &target_menu = options_menu.append(buffer); |
| 372 | build_video_target_menu(target_menu, *target); |
| 373 | } |
| 374 | } |
| 375 | else |
| 376 | { |
| 377 | // single target |
| 378 | build_video_target_menu(video_menu, *machine().render().first_target()); |
| 379 | } |
| 380 | |
| 381 | // separator |
| 382 | options_menu.append_separator(); |
| 383 | |
| 384 | // slot devices |
| 385 | slot_interface_iterator slotiter(machine().root_device()); |
| 386 | if (slotiter.first() != NULL) |
| 387 | options_menu.append<ui_emu_menubar>("Slot Devices...", &ui_emu_menubar::start_menu<ui_menu_slot_devices>, *this); |
| 388 | |
| 389 | // barcode reader |
| 390 | barcode_reader_device_iterator bcriter(machine().root_device()); |
| 391 | if (bcriter.first() != NULL) |
| 392 | options_menu.append<ui_emu_menubar>("Barcode Reader...", &ui_emu_menubar::start_menu<ui_menu_barcode_reader>, *this); |
| 393 | |
| 394 | // network devices |
| 395 | network_interface_iterator netiter(machine().root_device()); |
| 396 | if (netiter.first() != NULL) |
| 397 | options_menu.append<ui_emu_menubar>("Network Devices...", &ui_emu_menubar::start_menu<ui_menu_network_devices>, *this); |
| 398 | |
| 399 | // keyboard |
| 400 | if (machine().ioport().has_keyboard() && machine().ioport().natkeyboard().can_post()) |
| 401 | { |
| 402 | menu_item &keyboard_menu = options_menu.append("Keyboard"); |
| 403 | keyboard_menu.append("Emulated", &ui_manager::set_use_natural_keyboard, &ui_manager::use_natural_keyboard, machine().ui(), false); |
| 404 | keyboard_menu.append("Natural", &ui_manager::set_use_natural_keyboard, &ui_manager::use_natural_keyboard, machine().ui(), true); |
| 405 | } |
| 406 | |
| 407 | // crosshair options |
| 408 | if (crosshair_get_usage(machine())) |
| 409 | options_menu.append<ui_emu_menubar>("Crosshair Options...", &ui_emu_menubar::start_menu<ui_menu_crosshair>, *this); |
| 410 | |
| 411 | // memory card |
| 412 | if (machine().config().m_memcard_handler != NULL) |
| 413 | options_menu.append<ui_emu_menubar>("Memory Card...", &ui_emu_menubar::start_menu<ui_menu_memory_card>, *this); |
| 414 | |
| 415 | // cheat |
| 416 | if (machine().options().cheat() && machine().cheat().first() != NULL) |
| 417 | { |
| 418 | options_menu.append_separator(); |
| 419 | options_menu.append("Cheats enabled", &cheat_manager::set_enable, &cheat_manager::enabled, machine().cheat(), IPT_UI_TOGGLE_CHEAT); |
| 420 | options_menu.append<ui_emu_menubar>("Cheat...", &ui_emu_menubar::start_menu<ui_menu_cheat>, *this); |
| 421 | } |
| 422 | } |
| 423 | |
| 424 | |
| 425 | //------------------------------------------------- |
| 426 | // build_video_target_menu |
| 427 | //------------------------------------------------- |
| 428 | |
| 429 | void ui_emu_menubar::build_video_target_menu(menu_item &target_menu, render_target &target) |
| 430 | { |
| 431 | astring tempstring; |
| 432 | const char *view_name; |
| 433 | |
| 434 | // add the menu items for each view |
| 435 | for(int viewnum = 0; (view_name = target.view_name(viewnum)) != NULL; viewnum++) |
| 436 | { |
| 437 | // replace spaces with underscores |
| 438 | tempstring.cpy(view_name).replace(0, "_", " "); |
| 439 | |
| 440 | // append the menu |
| 441 | target_menu.append(tempstring, &render_target::set_view, &render_target::view, target, viewnum); |
| 442 | } |
| 443 | |
| 444 | // separator |
| 445 | target_menu.append_separator(); |
| 446 | |
| 447 | // rotation |
| 448 | menu_item &rotation_menu = target_menu.append("Rotation"); |
| 449 | rotation_menu.append("None", &render_target::set_orientation, &render_target::orientation, target, ROT0); |
| 450 | rotation_menu.append("Clockwise 90", &render_target::set_orientation, &render_target::orientation, target, ROT90); |
| 451 | rotation_menu.append("180", &render_target::set_orientation, &render_target::orientation, target, ROT180); |
| 452 | rotation_menu.append("Counterclockwise 90", &render_target::set_orientation, &render_target::orientation, target, ROT270); |
| 453 | |
| 454 | // show backdrops |
| 455 | target_menu.append("Show Backdrops", &render_target::set_backdrops_enabled, &render_target::backdrops_enabled, target); |
| 456 | |
| 457 | // show overlay |
| 458 | target_menu.append("Show Overlays", &render_target::set_overlays_enabled, &render_target::overlays_enabled, target); |
| 459 | |
| 460 | // show bezel |
| 461 | target_menu.append("Show Bezels", &render_target::set_bezels_enabled, &render_target::bezels_enabled, target); |
| 462 | |
| 463 | // show cpanel |
| 464 | target_menu.append("Show CPanels", &render_target::set_cpanels_enabled, &render_target::cpanels_enabled, target); |
| 465 | |
| 466 | // show marquee |
| 467 | target_menu.append("Show Marquees", &render_target::set_marquees_enabled, &render_target::marquees_enabled, target); |
| 468 | |
| 469 | // view |
| 470 | menu_item &view_menu = target_menu.append("View"); |
| 471 | view_menu.append("Cropped", &render_target::set_zoom_to_screen, &render_target::zoom_to_screen, target, true); |
| 472 | view_menu.append("Full", &render_target::set_zoom_to_screen, &render_target::zoom_to_screen, target, false); |
| 473 | } |
| 474 | |
| 475 | |
| 476 | //------------------------------------------------- |
| 477 | // build_settings_menu |
| 478 | //------------------------------------------------- |
| 479 | |
| 480 | void ui_emu_menubar::build_settings_menu() |
| 481 | { |
| 482 | astring menu_text; |
| 483 | menu_item &settings_menu = root_menu().append("Settings"); |
| 484 | |
| 485 | // general input |
| 486 | // TODO - BREAK THIS APART? |
| 487 | settings_menu.append<ui_emu_menubar>("General Input...", &ui_emu_menubar::start_menu<ui_menu_input_groups>, *this); |
| 488 | |
| 489 | // game input |
| 490 | menu_text.printf("%s Input...", emulator_info::get_capstartgamenoun()); |
| 491 | settings_menu.append<ui_emu_menubar>(menu_text, &ui_emu_menubar::start_menu<ui_menu_input_specific>, *this); |
| 492 | |
| 493 | // analog controls |
| 494 | if (machine().ioport().has_analog()) |
| 495 | settings_menu.append<ui_emu_menubar>("Analog Controls...", &ui_emu_menubar::start_menu<ui_menu_analog>, *this); |
| 496 | |
| 497 | // dip switches |
| 498 | if (machine().ioport().has_dips()) |
| 499 | settings_menu.append<ui_emu_menubar>("Dip Switches...", &ui_emu_menubar::start_menu<ui_menu_settings_dip_switches>, *this); |
| 500 | |
| 501 | // driver configuration |
| 502 | if (machine().ioport().has_configs()) |
| 503 | { |
| 504 | menu_text.printf("%s Configuration...", emulator_info::get_capstartgamenoun()); |
| 505 | settings_menu.append<ui_emu_menubar>(menu_text, &ui_emu_menubar::start_menu<ui_menu_settings_driver_config>, *this); |
| 506 | } |
| 507 | |
| 508 | // bios selection |
| 509 | if (machine().ioport().has_bioses()) |
| 510 | settings_menu.append<ui_emu_menubar>("Bios Selection...", &ui_emu_menubar::start_menu<ui_menu_bios_selection>, *this); |
| 511 | |
| 512 | // sliders |
| 513 | settings_menu.append<ui_emu_menubar>("Sliders...", &ui_emu_menubar::start_menu<ui_menu_sliders>, *this, IPT_UI_ON_SCREEN_DISPLAY); |
| 514 | } |
| 515 | |
| 516 | |
| 517 | //------------------------------------------------- |
| 518 | // build_help_menu |
| 519 | //------------------------------------------------- |
| 520 | |
| 521 | void ui_emu_menubar::build_help_menu() |
| 522 | { |
| 523 | astring menu_text; |
| 524 | menu_item &help_menu = root_menu().append("Help"); |
| 525 | |
| 526 | // bookkeeping info |
| 527 | help_menu.append<ui_emu_menubar>("Bookkeeping info...", &ui_emu_menubar::start_menu<ui_menu_bookkeeping>, *this); |
| 528 | |
| 529 | // game info |
| 530 | menu_text.printf("%s Information...", emulator_info::get_capstartgamenoun()); |
| 531 | help_menu.append<ui_emu_menubar>(menu_text, &ui_emu_menubar::start_menu<ui_menu_game_info>, *this); |
| 532 | |
| 533 | // image information |
| 534 | image_interface_iterator imgiter(machine().root_device()); |
| 535 | if (imgiter.first() != NULL) |
| 536 | help_menu.append<ui_emu_menubar>("Image Information...", &ui_emu_menubar::start_menu<ui_menu_image_info>, *this); |
| 537 | } |
| 538 | |
| 539 | |
| 540 | //------------------------------------------------- |
| 541 | // is_softlist_relevant |
| 542 | //------------------------------------------------- |
| 543 | |
| 544 | bool ui_emu_menubar::is_softlist_relevant(software_list_device *swlist, const char *interface, astring &list_description) |
| 545 | { |
| 546 | bool result = false; |
| 547 | |
| 548 | for (software_info *swinfo = swlist->first_software_info(); swinfo != NULL; swinfo = swinfo->next()) |
| 549 | { |
| 550 | software_part *part = swinfo->find_part(NULL, NULL); |
| 551 | if (part->matches_interface(interface)) |
| 552 | { |
| 553 | list_description.printf("%s...", swlist->description()); |
| 554 | result = true; |
| 555 | break; |
| 556 | } |
| 557 | } |
| 558 | |
| 559 | return result; |
| 560 | } |
| 561 | |
| 562 | |
| 563 | //------------------------------------------------- |
| 564 | // set_ui_handler |
| 565 | //------------------------------------------------- |
| 566 | |
| 567 | void ui_emu_menubar::set_ui_handler(ui_callback callback, UINT32 param) |
| 568 | { |
| 569 | // first pause |
| 570 | machine().pause(); |
| 571 | |
| 572 | // and transfer control |
| 573 | machine().ui().set_handler(callback, param); |
| 574 | } |
| 575 | |
| 576 | |
| 577 | //------------------------------------------------- |
| 578 | // select_new_game |
| 579 | //------------------------------------------------- |
| 580 | |
| 581 | void ui_emu_menubar::select_new_game() |
| 582 | { |
| 583 | start_menu(auto_alloc_clear(machine(), ui_menu_select_game(machine(), container(), machine().system().name))); |
| 584 | } |
| 585 | |
| 586 | |
| 587 | //------------------------------------------------- |
| 588 | // select_from_software_list |
| 589 | //------------------------------------------------- |
| 590 | |
| 591 | void ui_emu_menubar::select_from_software_list(device_image_interface *image, software_list_device *swlist) |
| 592 | { |
| 593 | s_softlist_image = image; |
| 594 | start_menu(auto_alloc_clear(machine(), ui_menu_software_list(machine(), container(), swlist, image->image_interface(), s_softlist_result))); |
| 595 | } |
| 596 | |
| 597 | |
| 598 | //------------------------------------------------- |
| 599 | // tape_control |
| 600 | //------------------------------------------------- |
| 601 | |
| 602 | void ui_emu_menubar::tape_control(cassette_image_device *image) |
| 603 | { |
| 604 | start_menu(auto_alloc_clear(machine(), ui_menu_mess_tape_control(machine(), container(), image))); |
| 605 | } |
| 606 | |
| 607 | |
| 608 | //------------------------------------------------- |
| 609 | // bitbanger_control |
| 610 | //------------------------------------------------- |
| 611 | |
| 612 | void ui_emu_menubar::bitbanger_control(bitbanger_device *image) |
| 613 | { |
| 614 | start_menu(auto_alloc_clear(machine(), ui_menu_mess_bitbanger_control(machine(), container(), image))); |
| 615 | } |
| 616 | |
| 617 | |
| 618 | //------------------------------------------------- |
| 619 | // load |
| 620 | //------------------------------------------------- |
| 621 | |
| 622 | void ui_emu_menubar::load(device_image_interface *image) |
| 623 | { |
| 624 | start_menu(image->get_selection_menu(machine(), container())); |
| 625 | } |
| 626 | |
| 627 | |
| 628 | //------------------------------------------------- |
| 629 | // has_images |
| 630 | //------------------------------------------------- |
| 631 | |
| 632 | bool ui_emu_menubar::has_images() |
| 633 | { |
| 634 | image_interface_iterator iter(machine().root_device()); |
| 635 | return iter.first() != NULL; |
| 636 | } |
| 637 | |
| 638 | |
| 639 | //------------------------------------------------- |
| 640 | // set_throttle_rate |
| 641 | //------------------------------------------------- |
| 642 | |
| 643 | void ui_emu_menubar::set_throttle_rate(float throttle_rate) |
| 644 | { |
| 645 | machine().video().set_throttled(throttle_rate != 0.0); |
| 646 | if (throttle_rate != 0.0) |
| 647 | machine().video().set_throttle_rate(throttle_rate); |
| 648 | } |