Example #1
0
    def __init__(self):
        cb = self.callbacks = UICallbacks()

        self.help = UIHelp()
        
        self.actions = gtk.ActionGroup("All")
        
        # name, icon ID, label, accel, tooltip, callback
        self.actions.add_toggle_actions((
        # TODO: how to know when these are changed from inside Hatari?
        ("recanim", gtk.STOCK_MEDIA_RECORD, "Record animation", "<Ctrl>A", "Record animation", cb.recanim),
        ("recsound", gtk.STOCK_MEDIA_RECORD, "Record sound", "<Ctrl>W", "Record YM/Wav", cb.recsound),
        ("pause", gtk.STOCK_MEDIA_PAUSE, "Pause", "<Ctrl>P", "Pause Hatari to save battery", cb.pause),
        ("forward", gtk.STOCK_MEDIA_FORWARD, "Forward", "<Ctrl>F", "Whether to fast forward Hatari (needs fast machine)", cb.set_fastforward, cb.get_fastforward())
        ))
        
        # name, icon ID, label, accel, tooltip, callback
        self.actions.add_actions((
        ("load", gtk.STOCK_OPEN, "Load snapshot...", "<Ctrl>L", "Load emulation snapshot", cb.load),
        ("save", gtk.STOCK_SAVE, "Save snapshot", "<Ctrl>S", "Save emulation snapshot", cb.save),
        ("shot", gtk.STOCK_MEDIA_RECORD, "Grab screenshot", "<Ctrl>G", "Grab a screenshot", cb.screenshot),
        ("quit", gtk.STOCK_QUIT, "Quit", "<Ctrl>Q", "Quit Hatari UI", cb.quit),
        
        ("run", gtk.STOCK_MEDIA_PLAY, "Run", "<Ctrl>R", "(Re-)run Hatari", cb.run),
        ("full", gtk.STOCK_FULLSCREEN, "Fullscreen", "<Ctrl>U", "Toggle whether Hatari is fullscreen", cb.set_fullscreen),
        ("input", gtk.STOCK_SPELL_CHECK, "Inputs...", "<Ctrl>N", "Simulate text input and mouse clicks", cb.inputs),
        ("reset", gtk.STOCK_REFRESH, "Reset...", "<Ctrl>E", "Warm or cold reset Hatari", cb.reset),
        
        ("display", gtk.STOCK_PREFERENCES, "Display...", "<Ctrl>Y", "Display settings", cb.display),
        ("floppy", gtk.STOCK_FLOPPY, "Floppies...", "<Ctrl>D", "Floppy images", cb.floppydisk),
        ("harddisk", gtk.STOCK_HARDDISK, "Hard disks...", "<Ctrl>H", "Hard disk images and directories", cb.harddisk),
        ("joystick", gtk.STOCK_CONNECT, "Joysticks...", "<Ctrl>J", "Joystick settings", cb.joystick),
        ("machine", gtk.STOCK_HARDDISK, "Machine...", "<Ctrl>M", "Hatari st/e/tt/falcon configuration", cb.machine),
        ("device", gtk.STOCK_PRINT, "Peripherals...", "<Ctrl>V", "Toggle Midi, Printer, RS232 peripherals", cb.peripheral),
        ("sound", gtk.STOCK_PROPERTIES, "Sound...", "<Ctrl>O", "Sound settings", cb.sound),

        ("path", gtk.STOCK_DIRECTORY, "Paths...", None, "Device & save file paths", cb.path),
        ("lconfig", gtk.STOCK_OPEN, "Load config...", "<Ctrl>C", "Load configuration", self.config_load),
        ("sconfig", gtk.STOCK_SAVE_AS, "Save config as...", None, "Save configuration", cb.config_save),
        
        ("debug", gtk.STOCK_FIND, "Debugger...", "<Ctrl>B", "Activate Hatari debugger", cb.debugger),
        ("trace", gtk.STOCK_EXECUTE, "Trace settings...", "<Ctrl>T", "Hatari tracing setup", cb.trace),
        
        ("manual", None, "Hatari manual", None, None, self.help.view_hatari_manual),
        ("compatibility", None, "Hatari compatibility list", None, None, self.help.view_hatari_compatibility),
        ("release", None, "Hatari release notes", None, None, self.help.view_hatari_releasenotes),
        ("todo", None, "Hatari TODO", None, None, self.help.view_hatari_todo),
        ("bugs", None, "Report a bug", None, None, self.help.view_hatari_bugs),
        ("mails", None, "Hatari mailing lists", None, None, self.help.view_hatari_mails),
        ("changes", None, "Latest Hatari changes", None, None, self.help.view_hatari_repository),
        ("authors", None, "Hatari authors", None, None, self.help.view_hatari_authors),
        ("hatari", None, "Hatari home page", None, None, self.help.view_hatari_page),
        ("hatariui", None, "Hatari UI home page", None, None, self.help.view_hatariui_page),
        ("about", gtk.STOCK_INFO, "Hatari UI info", "<Ctrl>I", "Hatari UI information", cb.about)
        ))
        self.action_names = [x.get_name() for x in self.actions.list_actions()]

        # no actions set yet to panels or toolbars
        self.toolbars = {}
        self.panels = []
Example #2
0
    def __init__(self):
        cb = self.callbacks = UICallbacks()

        self.help = UIHelp()
        
        self.actions = gtk.ActionGroup("All")
        
        # name, icon ID, label, accel, tooltip, callback
        self.actions.add_toggle_actions((
        # TODO: how to know when these are changed from inside Previous?
        ("recanim", gtk.STOCK_MEDIA_RECORD, "Record animation", "<Ctrl>A", "Record animation", cb.recanim),
        ("recsound", gtk.STOCK_MEDIA_RECORD, "Record sound", "<Ctrl>W", "Record YM/Wav", cb.recsound),
        ("pause", gtk.STOCK_MEDIA_PAUSE, "Pause", "<Ctrl>P", "Pause Previous to save battery", cb.pause),
        ("forward", gtk.STOCK_MEDIA_FORWARD, "Forward", "<Ctrl>F", "Whether to fast forward Previous (needs fast machine)", cb.set_fastforward, cb.get_fastforward())
        ))
        
        # name, icon ID, label, accel, tooltip, callback
        self.actions.add_actions((
        ("load", gtk.STOCK_OPEN, "Load snapshot...", "<Ctrl>L", "Load emulation snapshot", cb.load),
        ("save", gtk.STOCK_SAVE, "Save snapshot", "<Ctrl>S", "Save emulation snapshot", cb.save),
        ("shot", gtk.STOCK_MEDIA_RECORD, "Grab screenshot", "<Ctrl>G", "Grab a screenshot", cb.screenshot),
        ("quit", gtk.STOCK_QUIT, "Quit", "<Ctrl>Q", "Quit Previous UI", cb.quit),
        
        ("run", gtk.STOCK_MEDIA_PLAY, "Run", "<Ctrl>R", "(Re-)run Previous", cb.run),
        ("full", gtk.STOCK_FULLSCREEN, "Fullscreen", "<Ctrl>U", "Toggle whether Previous is fullscreen", cb.set_fullscreen),
        ("input", gtk.STOCK_SPELL_CHECK, "Inputs...", "<Ctrl>N", "Simulate text input and mouse clicks", cb.inputs),
        ("reset", gtk.STOCK_REFRESH, "Reset...", "<Ctrl>E", "Warm or cold reset Previous", cb.reset),
        
        ("display", gtk.STOCK_PREFERENCES, "Display...", "<Ctrl>Y", "Display settings", cb.display),
        ("floppy", gtk.STOCK_FLOPPY, "Floppies...", "<Ctrl>D", "Floppy images", cb.floppydisk),
        ("harddisk", gtk.STOCK_HARDDISK, "Hard disks...", "<Ctrl>H", "Hard disk images and directories", cb.harddisk),
        ("joystick", gtk.STOCK_CONNECT, "Joysticks...", "<Ctrl>J", "Joystick settings", cb.joystick),
        ("machine", gtk.STOCK_HARDDISK, "Machine...", "<Ctrl>M", "Previous st/e/tt/falcon configuration", cb.machine),
        ("device", gtk.STOCK_PRINT, "Peripherals...", "<Ctrl>V", "Toggle Midi, Printer, RS232 peripherals", cb.peripheral),
        ("sound", gtk.STOCK_PROPERTIES, "Sound...", "<Ctrl>O", "Sound settings", cb.sound),

        ("path", gtk.STOCK_DIRECTORY, "Paths...", None, "Device & save file paths", cb.path),
        ("lconfig", gtk.STOCK_OPEN, "Load config...", "<Ctrl>C", "Load configuration", self.config_load),
        ("sconfig", gtk.STOCK_SAVE_AS, "Save config as...", None, "Save configuration", cb.config_save),
        
        ("debug", gtk.STOCK_FIND, "Debugger...", "<Ctrl>B", "Activate Previous debugger", cb.debugger),
        ("trace", gtk.STOCK_EXECUTE, "Trace settings...", "<Ctrl>T", "Previous tracing setup", cb.trace),
        
        ("manual", None, "Previous manual", None, None, self.help.view_previous_manual),
        ("compatibility", None, "Previous compatibility list", None, None, self.help.view_previous_compatibility),
        ("release", None, "Previous release notes", None, None, self.help.view_previous_releasenotes),
        ("todo", None, "Previous TODO", None, None, self.help.view_previous_todo),
        ("bugs", None, "Report a bug", None, None, self.help.view_previous_bugs),
        ("mails", None, "Previous mailing lists", None, None, self.help.view_previous_mails),
        ("changes", None, "Latest Previous changes", None, None, self.help.view_previous_repository),
        ("authors", None, "Previous authors", None, None, self.help.view_previous_authors),
        ("previous", None, "Previous home page", None, None, self.help.view_previous_page),
        ("previousui", None, "Previous UI home page", None, None, self.help.view_previousui_page),
        ("about", gtk.STOCK_INFO, "Previous UI info", "<Ctrl>I", "Previous UI information", cb.about)
        ))
        self.action_names = [x.get_name() for x in self.actions.list_actions()]

        # no actions set yet to panels or toolbars
        self.toolbars = {}
        self.panels = []
Example #3
0
class UIActions:
    def __init__(self):
        cb = self.callbacks = UICallbacks()

        self.help = UIHelp()
        
        self.actions = gtk.ActionGroup("All")
        
        # name, icon ID, label, accel, tooltip, callback
        self.actions.add_toggle_actions((
        # TODO: how to know when these are changed from inside Hatari?
        ("recanim", gtk.STOCK_MEDIA_RECORD, "Record animation", "<Ctrl>A", "Record animation", cb.recanim),
        ("recsound", gtk.STOCK_MEDIA_RECORD, "Record sound", "<Ctrl>W", "Record YM/Wav", cb.recsound),
        ("pause", gtk.STOCK_MEDIA_PAUSE, "Pause", "<Ctrl>P", "Pause Hatari to save battery", cb.pause),
        ("forward", gtk.STOCK_MEDIA_FORWARD, "Forward", "<Ctrl>F", "Whether to fast forward Hatari (needs fast machine)", cb.set_fastforward, cb.get_fastforward())
        ))
        
        # name, icon ID, label, accel, tooltip, callback
        self.actions.add_actions((
        ("load", gtk.STOCK_OPEN, "Load snapshot...", "<Ctrl>L", "Load emulation snapshot", cb.load),
        ("save", gtk.STOCK_SAVE, "Save snapshot", "<Ctrl>S", "Save emulation snapshot", cb.save),
        ("shot", gtk.STOCK_MEDIA_RECORD, "Grab screenshot", "<Ctrl>G", "Grab a screenshot", cb.screenshot),
        ("quit", gtk.STOCK_QUIT, "Quit", "<Ctrl>Q", "Quit Hatari UI", cb.quit),
        
        ("run", gtk.STOCK_MEDIA_PLAY, "Run", "<Ctrl>R", "(Re-)run Hatari", cb.run),
        ("full", gtk.STOCK_FULLSCREEN, "Fullscreen", "<Ctrl>U", "Toggle whether Hatari is fullscreen", cb.set_fullscreen),
        ("input", gtk.STOCK_SPELL_CHECK, "Inputs...", "<Ctrl>N", "Simulate text input and mouse clicks", cb.inputs),
        ("reset", gtk.STOCK_REFRESH, "Reset...", "<Ctrl>E", "Warm or cold reset Hatari", cb.reset),
        
        ("display", gtk.STOCK_PREFERENCES, "Display...", "<Ctrl>Y", "Display settings", cb.display),
        ("floppy", gtk.STOCK_FLOPPY, "Floppies...", "<Ctrl>D", "Floppy images", cb.floppydisk),
        ("harddisk", gtk.STOCK_HARDDISK, "Hard disks...", "<Ctrl>H", "Hard disk images and directories", cb.harddisk),
        ("joystick", gtk.STOCK_CONNECT, "Joysticks...", "<Ctrl>J", "Joystick settings", cb.joystick),
        ("machine", gtk.STOCK_HARDDISK, "Machine...", "<Ctrl>M", "Hatari st/e/tt/falcon configuration", cb.machine),
        ("device", gtk.STOCK_PRINT, "Peripherals...", "<Ctrl>V", "Toggle Midi, Printer, RS232 peripherals", cb.peripheral),
        ("sound", gtk.STOCK_PROPERTIES, "Sound...", "<Ctrl>O", "Sound settings", cb.sound),

        ("path", gtk.STOCK_DIRECTORY, "Paths...", None, "Device & save file paths", cb.path),
        ("lconfig", gtk.STOCK_OPEN, "Load config...", "<Ctrl>C", "Load configuration", self.config_load),
        ("sconfig", gtk.STOCK_SAVE_AS, "Save config as...", None, "Save configuration", cb.config_save),
        
        ("debug", gtk.STOCK_FIND, "Debugger...", "<Ctrl>B", "Activate Hatari debugger", cb.debugger),
        ("trace", gtk.STOCK_EXECUTE, "Trace settings...", "<Ctrl>T", "Hatari tracing setup", cb.trace),
        
        ("manual", None, "Hatari manual", None, None, self.help.view_hatari_manual),
        ("compatibility", None, "Hatari compatibility list", None, None, self.help.view_hatari_compatibility),
        ("release", None, "Hatari release notes", None, None, self.help.view_hatari_releasenotes),
        ("todo", None, "Hatari TODO", None, None, self.help.view_hatari_todo),
        ("mails", None, "Hatari mailing lists", None, None, self.help.view_hatari_mails),
        ("changes", None, "Latest Hatari changes", None, None, self.help.view_hatari_repository),
        ("authors", None, "Hatari authors", None, None, self.help.view_hatari_authors),
        ("hatari", None, "Hatari home page", None, None, self.help.view_hatari_page),
        ("hatariui", None, "Hatari UI home page", None, None, self.help.view_hatariui_page),
        ("about", gtk.STOCK_INFO, "Hatari UI info", "<Ctrl>I", "Hatari UI information", cb.about)
        ))
        self.action_names = [x.get_name() for x in self.actions.list_actions()]

        # no actions set yet to panels or toolbars
        self.toolbars = {}
        self.panels = []

    def config_load(self, widget):
        # user loads a new configuration?
        if self.callbacks.config_load(widget):
            print("TODO: reset toggle actions")

    # ----- toolbar / panel additions ---------
    def set_actions(self, action_str, place):
        "set_actions(actions,place) -> error string, None if all OK"
        actions = action_str.split(",")
        for action in actions:
            if action in self.action_names:
                # regular action
                continue
            if action in self.panels:
                # user specified panel
                continue
            if action in ("close", ">"):
                if place != "panel":
                    return "'close' and '>' can be only in a panel"
                continue
            if action == "|":
                # divider
                continue
            if action.find("=") >= 0:
                # special keycode/string action
                continue
            return "unrecognized action '%s'" % action

        if place in ("left", "right", "top", "bottom"):
            self.toolbars[place] = actions
            return None
        if place == "panel":
            if len(actions) < 3:
                return "panel has too few items to be useful"
            return None
        return "unknown actions position '%s'" % place

    def add_panel(self, spec):
        "add_panel(panel_specification) -> error string, None if all is OK"
        offset = spec.find(",")
        if offset <= 0:
            return "invalid panel specification '%s'" % spec

        name, panelcontrols = spec[:offset], spec[offset+1:]
        error = self.set_actions(panelcontrols, "panel")
        if error:
            return error

        if ",>," in panelcontrols:
            box = gtk.VBox()
            splitcontrols = panelcontrols.split(",>,")
            for controls in splitcontrols:
                box.add(self._get_container(controls.split(",")))
        else:
            box = self._get_container(panelcontrols.split(","))
            
        self.panels.append(name)
        self.actions.add_actions(
            ((name, gtk.STOCK_ADD, name, None, name, self.callbacks.panel),),
            box
        )
        return None

    def list_actions(self):
        yield ("|", "Separator between controls")
        yield (">", "Start next toolbar row in panel windows")
        # generate the list from action information
        for act in self.actions.list_actions():
            note = act.get_property("tooltip")
            if not note:
                note = act.get_property("label")
            yield(act.get_name(), note)
        yield ("<panel name>", "Button for the specified panel window")
        yield ("<name>=<string/code>", "Synthetize string or single key <code>")

    # ------- panel special actions -----------
    def _close_cb(self, widget):
        widget.get_toplevel().hide()

    # ------- key special action -----------
    def _create_key_control(self, name, textcode):
        "Simulate Atari key press/release and string inserting"
        if not textcode:
            return None
        widget = gtk.ToolButton(gtk.STOCK_PASTE)
        widget.set_label(name)
        try:
            # part after "=" converts to an int?
            code = int(textcode, 0)
            widget.connect("clicked", self.callbacks.keypress, code)
            tip = "keycode: %d" % code
        except ValueError:
            # no, assume a string macro is wanted instead
            widget.connect("clicked", self.callbacks.textinsert, textcode)
            tip = "string '%s'" % textcode
        widget.set_tooltip_text("Insert " + tip)
        return widget

    def _get_container(self, actions, horiz = True):
        "return Gtk container with the specified actions or None for no actions"
        if not actions:
            return None

        #print("ACTIONS:", actions)
        if len(actions) > 1:
            bar = gtk.Toolbar()
            if horiz:
                bar.set_orientation(gtk.ORIENTATION_HORIZONTAL)
            else:
                bar.set_orientation(gtk.ORIENTATION_VERTICAL)
            bar.set_style(gtk.TOOLBAR_BOTH)
            # disable overflow menu to get toolbar sized correctly for panels
            bar.set_show_arrow(False)
        else:
            bar = None
        
        for action in actions:
            #print(action)
            offset = action.find("=")
            if offset >= 0:
                # handle "<name>=<keycode>" action specification
                name = action[:offset]
                text = action[offset+1:]
                widget = self._create_key_control(name, text)
            elif action == "|":
                widget = gtk.SeparatorToolItem()
            elif action == "close":
                if bar:
                    widget = create_toolbutton(gtk.STOCK_CLOSE, self._close_cb)
                else:
                    widget = create_button("Close", self._close_cb)
            else:
                widget = self.actions.get_action(action).create_tool_item()
            if not widget:
                continue
            if bar:
                if action != "|":
                    widget.set_expand(True)
                bar.insert(widget, -1)
        if bar:
            return bar
        return widget

    # ------------- handling menu -------------
    def _add_submenu(self, bar, title, items):
        submenu = gtk.Menu()
        for name in items:
            if name:
                action = self.actions.get_action(name)
                item = action.create_menu_item()
            else:
                item = gtk.SeparatorMenuItem()
            submenu.add(item)
        baritem = gtk.MenuItem(title, False)
        baritem.set_submenu(submenu)
        bar.add(baritem)

    def _get_menu(self):
        allmenus = (
        ("File", ("load", "save", None, "shot", "recanim", "recsound", None, "quit")),
        ("Emulation", ("run", "pause", "forward", None, "full", None, "input", None, "reset")),
        ("Devices", ("display", "floppy", "harddisk", "joystick", "machine", "device", "sound")),
        ("Configuration", ("path", None, "lconfig", "sconfig")),
        ("Debug", ("debug", "trace")),
        ("Help", ("manual", "compatibility", "release", "todo", None, "mails", "changes", None, "authors", "hatari", "hatariui", "about",))
        )
        bar = gtk.MenuBar()

        for title, items in allmenus:
            self._add_submenu(bar, title, items)

        if self.panels:
            self._add_submenu(bar, "Panels", self.panels)

        return bar

    # ------------- run the whole UI -------------
    def run(self, floppy, havemenu, fullscreen, embed):
        accelgroup = None
        # create menu?
        if havemenu:
            # this would steal keys from embedded Hatari
            if not embed:
                accelgroup = gtk.AccelGroup()
                for action in self.actions.list_actions():
                    action.set_accel_group(accelgroup)
            menu = self._get_menu()
        else:
            menu = None

        # create toolbars
        toolbars = { "left":None, "right":None, "top":None, "bottom":None}
        for side in ("left", "right"):
            if side in self.toolbars:
                toolbars[side] = self._get_container(self.toolbars[side], False)
        for side in ("top", "bottom"):
            if side in self.toolbars:
                toolbars[side] = self._get_container(self.toolbars[side], True)

        self.callbacks.create_ui(accelgroup, menu, toolbars, fullscreen, embed)
        self.help.set_mainwin(self.callbacks.mainwin)
        self.callbacks.set_floppy(floppy)

        # ugly, Hatari socket window ID can be gotten only
        # after Socket window is realized by gtk_main()
        gobject.idle_add(self.callbacks.run)
        gtk.main()