Games-Axmud

 view release on metacpan or  search on metacpan

README.rst  view on Meta::CPAN

- `RPM package (for RHEL-based distros, e.g. Fedora) <https://sourceforge.net/projects/axmud/files/Axmud-2.0.0/perl-Games-Axmud-2.0.0.noarch.rpm/download>`__ from Sourceforge

Source code:

- `Source code <https://sourceforge.net/projects/axmud/files/Axmud-2.0.0/Games-Axmud-2.0.0.tar.gz/download>`__ from Sourceforge (see also the source code for `MS Windows <https://sourceforge.net/projects/axmud/files/Axmud-2.0.0/Games-Axmud-2.0.0.tar....
- `Source code <https://github.com/axcore/axmud>`__ and `support <https://github.com/axcore/axmud/issues>`__ from GitHub

3 Running Axmud
===============

There are several ways to install Axmud (see below). Most of them will add an Axmud icon to your desktop, and an entry in your Start Menu.

There are actually two versions of Axmud: a 'normal' version, and a version with optimised settings for visually-impaired users.

The optimised version will start talking at you, as soon as you start it. (If you don't hear anything, then perhaps there are no text-to-speech engines installed on your system.)

If you're running Axmud from the command line, visually-impaired users can run this script:

        **baxmud.pl**

Other users can run this script:

lib/Games/Axmud/Client.pm  view on Meta::CPAN

            # ...where 'cage_name' is an item in $self->cageTypeList, and 'cage_package' is the
            #   package name of the Perl object
            pluginCagePackageHash       => {},
            # For cages that have been added by a plugin, a registry hash of 'edit' windows added by
            #   the plugin (where available)
            # Hash in the form
            #   $pluginCageEditWinHash{cage_name} = config_window_package_name
            # NB If no 'edit' window exists for a particular cage, 'edit_window_package_name' will
            #   be 'undef'
            pluginCageEditWinHash       => {},
            # Registry hash of functions to call every time a menu strip object (GA::Strip::MenuBar)
            #   creates a menu in an 'internal' window, in order to add menu menu items for the
            #   plugin. Hash in the form
            #   $pluginMenuFuncHash{plugin_name} = func_ref
            #   ...where 'func_ref' is a reference to a function within a plugin that creates menu
            #   items, when passed an existing Gtk3::Menu widget
            pluginMenuFuncHash          => {},
            # For MXP file filters that must be passed to a plugin, a registry hash of the plugin
            #   functions to call when the filter is applied to a file. Hash in the form
            #   $pluginMxpFilterHash{package_name} = reference_to_function
            pluginMxpFilterHash         => {},

            # System loops
            # ------------

            # The client time (used by various parts of the code that need a time that stays
            #   consistent for some measured period, but which is updated frequently). Set by

lib/Games/Axmud/Client.pm  view on Meta::CPAN

            # Flag set to TRUE if the user should be prompted for a confirmation if they try to
            #   close a 'main' window by clicking on its 'X' widget, and any of the sessions using
            #   the window are connected to a world
            confirmCloseMainWinFlag     => TRUE,        # [config]
            # Flag set to TRUE if the user should be prompted for a confirmation if they try to
            #   close a tab by clicking on its 'X' widget, and the session is connected to a world
            confirmCloseTabFlag         => TRUE,        # [config]
            # Equivalent flag set to TRUE if the user should be prompted for a confirmation if they
            #   try to stop the session by clicking the main window menu, and the session is
            #   connected to a world
            confirmCloseMenuFlag  => TRUE,              # [config]
            # Equivalent flag set to TRUE if the user should be prompted for a confirmation if they
            #   try to stop the session by clicking the main window toolbutton, and the session is
            #   connected to a world
            confirmCloseToolButtonFlag  => TRUE,        # [config]

            # The default character set to use. Must be one of the character sets available with the
            #   Perl Encode module
            constCharSet                => 'iso-8859-1',
            # The current character set. For each individual session, if the current world's
            #   ->worldCharSet IV is set, that character set is used instead

lib/Games/Axmud/Client.pm  view on Meta::CPAN


            # Axmud keeps two lists of strip objects - one for Axmud's built-in strip objects, and
            #   another for all strip objects (built-in objects and custom objects added via a
            #   plugin, which should inherit from GA::Strip::Custom)
            #
            # The constant registry of strip objects (these values never change). A hash in the form
            #   $constStripHash{package_name} = pretty_name
            # NB Both 'package_name' and 'pretty_name' should be unique. To avoid problems, use the
            #   plugin name in 'pretty_name', e.g. 'Myplugin toolbar'
            constStripHash              => {
                'Games::Axmud::Strip::MenuBar'
                                        => $axmud::SCRIPT . ' menu bar',
                'Games::Axmud::Strip::Toolbar'
                                        => $axmud::SCRIPT . ' toolbar',
                'Games::Axmud::Strip::Table'
                                        => $axmud::SCRIPT . ' table',
                'Games::Axmud::Strip::GaugeBox'
                                        => $axmud::SCRIPT . ' gauge box',
                'Games::Axmud::Strip::SearchBox'
                                        => $axmud::SCRIPT . ' search box',
                'Games::Axmud::Strip::Entry'

lib/Games/Axmud/Client.pm  view on Meta::CPAN

        }

        return 1;
    }

    sub stop {

        # Called by axmud.pl on shutdown
        # Also called by $self->stopSession, GA::Cmd::StopClient->do, GA::Cmd::Panic->do,
        #   GA::Cmd::RestoreWorld->do, GA::Win::Internal->setDeleteEvent and
        #   GA::Strip::MenuBar->drawWorldColumn
        # Stops the client
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments
        #   1 otherwise

        my ($self, $check) = @_;

lib/Games/Axmud/Client.pm  view on Meta::CPAN

                push (@returnArray, $session);
            }
        }

        # Return the list of matching sessions (may be empty)
        return @returnArray;
    }

    sub checkSessions {

        # Called by GA::Strip::MenuBar->drawWorldColumn just before doing the ';stopsession' or
        #   ';stopclient' commands
        # Checks every session to see whether any of them are connected, and whether there are any
        #   unsaved files at all (if not, the 'main' window doesn't have to prompt the user for
        #   confirmation, before stopping the session/client).
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Optional arguments
        #   $session    - If specified, ignore other GA::Session objects (but still check the

lib/Games/Axmud/Client.pm  view on Meta::CPAN


                # The TRUE argument means 'don't display a message for each cage created/destroyed'
                $session->updateCages(TRUE);
            }
        }

        # Operation complete
        return $count;
    }

    sub addPluginMenus {

        # Called by any Axmud plugin
        # Adds menu items defined in the plugin to any menu strip object (GA::Strip::MenuBar)
        #   displayed in any 'internal' window while the client is running (and the plugin is
        #   enabled)
        #
        # Expected arguments
        #   $plugin     - The plugin's main package (declared in the file header)
        #
        # Optional arguments
        #   $funcRef    - Reference to a function which contain the code to add menu items to a
        #                   Gtk3::Menu widget, pre-existing or created by this function. The
        #                   referenced function must accept the strip object and Gtk3::Menu as
        #                   arguments, and return 'undef' on failure or 1 on success
        #
        # Return values
        #   'undef' on improper arguments or if the menu items can't be added
        #   1 otherwise

        my ($self, $plugin, $funcRef, $check) = @_;

        # Local variables
        my ($pluginObj, $subMenu);

        # Check for improper arguments
        if (! defined $plugin || ! defined $funcRef || defined $check) {

             return $axmud::CLIENT->writeImproper($self->_objClass . '->addPluginWidgets', @_);
        }

        # Find the plugin object
        $pluginObj = $self->ivShow('pluginHash', $plugin);
        if (! $pluginObj) {

            # Plugin not found - a very unlikely occurrence for this function, but it's worth
            #   checking anyway
            return undef;
        }

        # Each plugin can only call this function once
        if ($self->ivExists('pluginMenuFuncHash', $plugin)) {

            return undef;

        } else {

            $self->ivAdd('pluginMenuFuncHash', $plugin, $funcRef);
        }

        # Any 'internal' windows which already exist and which have a menu strip object should add a
        #   sub-menu for this plugin now; any new 'internal' windows created from now will
        #   automatically call the referenced function to add their own sub-menus
        foreach my $winObj ($self->desktopObj->ivValues('gridWinHash')) {

            my ($stripObj, $subMenu);

            if (
                $winObj->winType eq 'main'
                || $winObj->winType eq 'protocol'
                || $winObj->winType eq 'custom'
            ) {
                $stripObj = $winObj->ivShow('firstStripHash', 'Games::Axmud::Strip::MenuBar');
                if ($stripObj) {

                    $subMenu = $stripObj->addPluginWidgets($plugin);
                    if (! $subMenu) {

                        return undef;
                    }

                    # Call the referenced function to add menu items to this sub-menu
                    if (! &$funcRef($stripObj, $subMenu)) {

                        return undef;
                    }

                    # Update the window to show the new menu items
                    $winObj->winShowAll($self->_objClass . '->addPluginMenus');
                }
            }
        }

        return 1;
    }

    sub addPluginMxpFilters {

        # Called by any Axmud plugin

lib/Games/Axmud/Client.pm  view on Meta::CPAN

            $cmd =~ s/%s/$path/;

            system $cmd;

            return 1;
        }
    }

    sub openURL {

        # Called by GA::Strip::MenuBar->drawHelpColumn, GA::Obj::TextView->setButtonPressEvent,
        #   GA::OtherWin::Connect->createTableWidgets or any other function
        # Opens a URL link in an external web browser (if allowed)
        #
        # Expected arguments
        #   $link   - The URL to open
        #
        # Return values
        #   'undef' on improper arguments or if the link can't be opened
        #   1 otherwise

lib/Games/Axmud/Client.pm  view on Meta::CPAN

            $iv = 'simpleTabFlag';
        } elsif ($type eq 'close_main') {
            $iv = 'confirmCloseMainWinFlag';
        } elsif ($type eq 'close_tab') {
            $iv = 'confirmCloseTabFlag';
        } elsif ($type eq 'switch_offline') {
            $iv = 'offlineOnDisconnectFlag';
        } elsif ($type eq 'close_menu') {
            $iv = 'confirmCloseToolButtonFlag';
        } elsif ($type eq 'close_toolbutton') {
            $iv = 'confirmCloseMenuFlag';
        }

        if ($self->$iv) {
            $self->ivPoke($iv, FALSE);
        } else {
            $self->ivPoke($iv, TRUE);
        }

        # Redraw the tab title in every session
        if ($type ne 'switch_offline') {

lib/Games/Axmud/Client.pm  view on Meta::CPAN

    sub pluginStripObjHash
        { my $self = shift; return %{$self->{pluginStripObjHash}}; }
    sub pluginTableObjHash
        { my $self = shift; return %{$self->{pluginTableObjHash}}; }
    sub pluginCageHash
        { my $self = shift; return %{$self->{pluginCageHash}}; }
    sub pluginCagePackageHash
        { my $self = shift; return %{$self->{pluginCagePackageHash}}; }
    sub pluginCageEditWinHash
        { my $self = shift; return %{$self->{pluginCageEditWinHash}}; }
    sub pluginMenuFuncHash
        { my $self = shift; return %{$self->{pluginMenuFuncHash}}; }
    sub pluginMxpFilterHash
        { my $self = shift; return %{$self->{pluginMxpFilterHash}}; }

    sub clientTime
        { $_[0]->{clientTime} }
    sub suspendSessionLoopFlag
        { $_[0]->{suspendSessionLoopFlag} }

    sub clientLoopObj
        { $_[0]->{clientLoopObj} }

lib/Games/Axmud/Client.pm  view on Meta::CPAN

    sub xTermTitleFlag
        { $_[0]->{xTermTitleFlag} }
    sub longTabLabelFlag
        { $_[0]->{longTabLabelFlag} }
    sub simpleTabFlag
        { $_[0]->{simpleTabFlag} }
    sub confirmCloseMainWinFlag
        { $_[0]->{confirmCloseMainWinFlag} }
    sub confirmCloseTabFlag
        { $_[0]->{confirmCloseTabFlag} }
    sub confirmCloseMenuFlag
        { $_[0]->{confirmCloseMenuFlag} }
    sub confirmCloseToolButtonFlag
        { $_[0]->{confirmCloseToolButtonFlag} }

    sub constCharSet
        { $_[0]->{constCharSet} }
    sub charSet
        { $_[0]->{charSet} }
    sub charSetList
        { my $self = shift; return @{$self->{charSetList}}; }

lib/Games/Axmud/Cmd.pm  view on Meta::CPAN

            } else {
                $session->writeText('   Confirm before click-closing \'main\' window   - ON');
            }

            if (! $axmud::CLIENT->confirmCloseTabFlag) {
                $session->writeText('   Confirm before click-closing tabs              - OFF');
            } else {
                $session->writeText('   Confirm before click-closing tabs              - ON');
            }

            if (! $axmud::CLIENT->confirmCloseMenuFlag) {
                $session->writeText('   Confirm before closing session from menu       - OFF');
            } else {
                $session->writeText('   Confirm before closing session from menu       - ON');
            }

            if (! $axmud::CLIENT->confirmCloseToolButtonFlag) {
                $session->writeText('   Confirm before closing session from toolbar    - OFF');
            } else {
                $session->writeText('   Confirm before closing session from toolbar    - ON');
            }

lib/Games/Axmud/Cmd.pm  view on Meta::CPAN


                return $self->complete(
                    $session, $standardCmd,
                    'Confirm before click-closing tabs turned ON',
                );
            }

        } elsif ($switch eq '-e') {

            $axmud::CLIENT->toggle_sessionFlag('close_menu');
            if (! $axmud::CLIENT->confirmCloseMenuFlag) {

                return $self->complete(
                    $session, $standardCmd,
                    'Confirm before closing session from menu turned OFF',
                );

            } else {

                return $self->complete(
                    $session, $standardCmd,

lib/Games/Axmud/Cmd.pm  view on Meta::CPAN

                    $session, $standardCmd,
                    'The Automapper window will no longer open when ' . $axmud::SCRIPT . ' starts',
                );
            }

        } else {

            # ;tam -e
            if ($switch eq '-e') {

                $session->worldModelObj->toggle_componentFlag('showMenuBarFlag');
                if ($session->worldModelObj->showMenuBarFlag) {
                    $msg = 'Automapper window menu bar(s) shown';
                } else {
                    $msg = 'Automapper window menu bar(s) hidden';
                }

            # ;tam -t
            } elsif ($switch eq '-t') {

                $session->worldModelObj->toggle_componentFlag('showToolbarFlag');
                if ($session->worldModelObj->showToolbarFlag) {

lib/Games/Axmud/EditWin.pm  view on Meta::CPAN

                $self->editObj->doModify('saveChanges');
            }

            # Update the current session's data viewer window, if it is open
            if ($self->session->viewerWin) {

                $self->session->viewerWin->updateNotebook();
            }

            # Redraw menu bars/toolbars in all automapper windows using this world model
            $self->session->worldModelObj->updateMapMenuToolbars();
        }

        return 1;
    }

    # Notebook tabs

    sub roomTab {

        # Room tab

lib/Games/Axmud/EditWin.pm  view on Meta::CPAN


        return 1;
    }

    sub stripsTab_checkPackage {

        # Called by $self->stripsTab_updateCombo2
        # Checks whether a strip object package name exists in the ->stripInitList IV, or not
        #
        # Expected arguments
        #   $package    - The package name to check, e.g. 'Games::Axmud::Strip::MenuBar'
        #
        # Return values
        #   'undef' on improper arguments or if the package name is not in ->stripInitList
        #   1 if the package name is found in ->stripInitList

        my ($self, $package, $check) = @_;

        # Local variables
        my @ivList;

lib/Games/Axmud/EditWin.pm  view on Meta::CPAN

                $self->ivDelete('editHash', 'defaultRoomWidthPixels');
                $self->ivDelete('editHash', 'defaultBlockHeightPixels');
                $self->ivDelete('editHash', 'defaultRoomHeightPixels');
            }

            # Some widgets (especially those in $self->settingsXTabs) require a call to the world
            #   model object, when they are changed. Deal with them each in turn

            # (Automapper window components)
            @ivList = (
                'showMenuBarFlag', 'showToolbarFlag', 'showTreeViewFlag', 'showCanvasFlag',
            );

            foreach my $iv (@ivList) {

                if ($self->ivExists('editHash', $iv)) {

                    if ($self->ivShow('editHash', $iv) ne $self->editObj->$iv) {

                        $self->editObj->toggleWinComponents(
                            $iv,

lib/Games/Axmud/EditWin.pm  view on Meta::CPAN

            ],
        );

        # Settings (1/8)
        $self->addLabel($grid, '<b>Settings (1/8)</b>',
            0, 12, 0, 1);

        # Left column
        $self->addLabel($grid, '<u>Window components</u>',
            1, 6, 1, 2);
        $self->addCheckButton($grid, 'Show menu bar', 'showMenuBarFlag', TRUE,
            1, 6, 2, 3);
        $self->addCheckButton($grid, 'Show toolbar', 'showToolbarFlag', TRUE,
            1, 6, 3, 4);
        $self->addCheckButton($grid, 'Show region list', 'showTreeViewFlag', TRUE,
            1, 6, 4, 5);
        $self->addCheckButton($grid, 'Show map', 'showCanvasFlag', TRUE,
            1, 6, 5, 6);

        $self->addLabel($grid, '<u>Label alignment</u>',
            1, 6, 6, 7);

lib/Games/Axmud/Generic.pm  view on Meta::CPAN

            #   parent window, set to FALSE if any number of instances can be added
            jealousyFlag                => TRUE,
            # Flag set to TRUE if this strip object can be added when $axmud::BLIND_MODE_FLAG is
            #   TRUE, FALSE if it can't be added (because it's not useful for visually-impaired
            #   users)
            blindFlag                   => FALSE,
            # Flag set to TRUE if the main container widget, stored in $self->packingBox, should be
            #   allowed to accept the focus, FALSE if not. The restriction is applied during the
            #   call to GA::Win::Internal->drawWidgets and ->addStripObj. Even if FALSE, widgets in
            #   the container widget can be set to accept the focus (e.g. the Gtk3::Entry in
            #   GA::Strip::MenuBar)
            allowFocusFlag              => FALSE,

            # Initialisation settings stored as a hash (see the comments above)
            initHash                    => \%modHash,
            # Reference to a function to call when some widget is used. This IV is set only when
            #   required by this type of strip object. It can be set by a call to
            #   $self->set_func() or by some setting in $self->initHash, which is applied in the
            #   call to $self->objEnable(). To obtain a reference to an OOP method, you can use the
            #   generic object function Games::Axmud->getMethodRef()
            funcRef                     => undef,

lib/Games/Axmud/Obj/Desktop.pm  view on Meta::CPAN

        }

        foreach my $winObj ($self->ivValues('gridWinHash')) {

            if (
                $winObj->winType eq 'main'
                || $winObj->winType eq 'protocol'
                || $winObj->winType eq 'custom'
            ) {
                # Update menu bars in all 'internal' windows
                $winObj->restrictMenuBars();
                # Update toolbars in all 'internal' windows
                $winObj->restrictToolbars();
            }
        }

        return 1;
    }

    # 'grid' windows

lib/Games/Axmud/Obj/File.pm  view on Meta::CPAN

                $self->convert($client->xTermTitleFlag),
            '# Use long world names in tab labels',
                $self->convert($client->longTabLabelFlag),
            '# Don\'t use tab labels when only one session open',
                $self->convert($client->simpleTabFlag),
            '# Prompt user before closing \'main\' window',
                $self->convert($client->confirmCloseMainWinFlag),
            '# Prompt user before closing \'main\' window tabs',
                $self->convert($client->confirmCloseTabFlag),
            '# Prompt user before closing session from the \'main\' window menu',
                $self->convert($client->confirmCloseMenuFlag),
            '# Prompt user before closing session from the \'main\' window toolbar',
                $self->convert($client->confirmCloseToolButtonFlag),
            '# Character set',
                $client->charSet,
            '# Maximum concurrent sessions',
                $client->sessionMax,
            '# Switch to \'offline\' mode on disconnection',
                $self->convert($client->offlineOnDisconnectFlag),
            '# Store connection history',
                $self->convert($client->connectHistoryFlag),

lib/Games/Axmud/Obj/File.pm  view on Meta::CPAN

            $client->ivPoke('longTabLabelFlag', $dataHash{'long_tab_label_flag'});
            $client->ivPoke('simpleTabFlag', $dataHash{'simple_tab_flag'});
        }
        if ($self->scriptConvertVersion >= 1_000_917) {

            $client->ivPoke('confirmCloseMainWinFlag', $dataHash{'confirm_close_main_win_flag'});
            $client->ivPoke('confirmCloseTabFlag', $dataHash{'confirm_close_tab_flag'});
        }
        if ($self->scriptConvertVersion >= 1_002_102) {

            $client->ivPoke('confirmCloseMenuFlag', $dataHash{'confirm_close_menu_flag'});
            $client->ivPoke(
                'confirmCloseToolButtonFlag',
                $dataHash{'confirm_close_tool_button_flag'},
            );
        }
        if ($self->scriptConvertVersion >= 1_000_185) {

            $client->ivPoke('charSet', $dataHash{'char_set'});
        }
        if ($self->scriptConvertVersion >= 1_000_616) {

lib/Games/Axmud/Obj/Map.pm  view on Meta::CPAN

                }
            }
        }

        return 1;
    }

    sub createNewRoom {

        # Called by $self->moveKnownDirSeen, ->autoProcessNewRoom and ->reactRandomExit
        # Also called by GA::Win::Map->enableCanvasPopupMenu, ->canvasEventHandler,
        #   ->addFirstRoomCallback, ->addRoomAtBlockCallback
        # Creates a new room - adding a new object to the world model. At the moment, new rooms can
        #   only be created when the automapper window is open, but this function checks for that
        #   (just in case of future changes)
        # If the process fails, deletes the world model object (if already created) and displays an
        #   error
        #
        # Expected arguments
        #   $regionmapObj   - The GA::Obj::Regionmap in which the new room will be created. Usually
        #                       (but not always) matches the regionmap visible in the automapper

lib/Games/Axmud/Obj/TextView.pm  view on Meta::CPAN

            # Widgets
            textView                    => undef,           # Gtk3::TextView
            textView2                   => undef,           # Gtk3::TextView
            buffer                      => undef,           # Gtk3::TextBuffer
            vPaned                      => undef,           # Gtk3::VPaned
            scroll                      => undef,           # Gtk3::ScrolledWindow
            scroll2                     => undef,           # Gtk3::ScrolledWindow
            startMark                   => undef,           # Gtk3::TextMark
            endMark                     => undef,           # Gtk3::TextMark
            searchMark                  => undef,           # Gtk3::TextMark
            popupMenu                   => undef,           # Gtk3::Menu

            # Other IVs

            # Flag set to TRUE when the scroll lock is enabled, FALSE when it is disabled (only
            #   applies to the original Gtk3::TextView)
            scrollLockFlag              => TRUE,
            # What type of scroll lock to apply - 'top' if the original textview should remain
            #   scrolled to the top, 'bottom' if it should remain scrolled to the bottom
            scrollLockType              => 'bottom',
            # Split screen mode. Because of performance issues with very large Gtk3::TextBuffers,

lib/Games/Axmud/Obj/TextView.pm  view on Meta::CPAN

                        }
                    }

                # Right button
                } elsif ($event->button == 3) {

                    if ($self->currentLinkObj->type eq 'cmd' && $self->currentLinkObj->popupFlag) {

                        # Create a popup menu, and send a world command if the user clicks on a menu
                        #   item
                        $result = $self->createPopupMenu($event);
                    }
                }

                # Clicking on a link resets the cursor
                $self->ivUndef('currentLinkObj');
                $textView->get_window('text')->set_cursor($axmud::CLIENT->constNormalCursor);
                return $result;
            }

            # Otherwise return 'undef' to show that we haven't interfered with the widget

lib/Games/Axmud/Obj/TextView.pm  view on Meta::CPAN

            $self->ivAdd(
                'tooltipHash',
                ($iter->get_line() + $self->nextDeleteLine),
                'Line ' . $sessionLineNum . ', ' . $axmud::CLIENT->localTime,
            );
        }

        return 1;
    }

    sub createPopupMenu {

        # Called by ->signal_connect in $self->setButtonPressEvent
        # After the user has clicked on $self->currentLinkObj, creates a popup menu from which the
        #   user can select one of several menu items. If the user clicks on a menu item, the
        #   corresponding world command is sent
        # The menu options and corresponding world commands are (usually) set by an MXP
        #   <SEND>..</SEND> construction
        #
        # Expected arguments
        #   $event          - The 'button_press_event' signal emitted when the user clicks on a

lib/Games/Axmud/Obj/TextView.pm  view on Meta::CPAN


        # Local variables
        my (
            $linkObj, $count,
            @optionList,
        );

        # Check for improper arguments
        if (! defined $event || defined $check) {

             return $axmud::CLIENT->writeImproper($self->_objClass . '->createPopupMenu', @_);
        }

        # Check there is a current link object set (no reason why there shouldn't be)
        if (! $self->currentLinkObj) {

            return undef;

        } else {

            # $self->currentLinkObj will be set to 'undef' as soon as the popup menu is clicked,
            #   and before this function returns, so store the object as a local variable)
            $linkObj = $self->currentLinkObj;
        }

        # Create the popup menu
        my $menu = Gtk3::Menu->new();

        # The GA::Obj::Link stores menu items and corresponding world commands each as a single
        #   string, with items/commands separated by a | character
        # (If there was an extra item in @optionList, representing an extra tooltip hint to show
        #   e.g. "Click to see the menu", it has already been removed)
        @optionList = $linkObj->popupItemList;

        $count = -1;
        foreach my $cmd ($linkObj->popupCmdList) {

            my ($hint, $menuItem);

            $count++;

            # Prefer to use a hint over a raw command, if a hint was supplied
            $hint = shift (@optionList);
            $menuItem = Gtk3::MenuItem->new_with_label('');

            my $label = $menuItem->get_child();
            if ($hint) {

                if (! $count) {
                    $label->set_markup('<b>' . $hint . '</b>');
                } else {
                    $label->set_markup($hint);
                }

lib/Games/Axmud/Obj/TextView.pm  view on Meta::CPAN


        $menu->popup(
            undef, undef, undef, undef,
            $event->button,
            $event->time,
        );

        $menu->show_all();

        # Store as an IV, so that $self->resetCurrentLink can destroy it, if the link expires
        $self->ivPoke('popupMenu', $menu);
        $menu->signal_connect('delete-event' => sub {

            $self->ivUndef('popupMenu');

            return undef;
        });

        return 1;
    }

    sub resetCurrentLink {

        # Called by GA::Session->processMxpOfficialElement when the GA::Obj::Link object stored in

lib/Games/Axmud/Obj/TextView.pm  view on Meta::CPAN

        # Hide tooltips, if visible
        $self->hideTooltips();

        # Reset the cursor
        if ($self->textView) {

            $self->textView->get_window('text')->set_cursor($axmud::CLIENT->constNormalCursor);
        }

        # Close the popup menu
        if ($self->popupMenu) {

            $self->popupMenu->destroy();

            $self->ivUndef('popupMenu');
        }

        return 1;
    }

    sub toggleScrollLock {

        # Called by GA::Table::Pane->toggleScrollLock
        # Enables or disables this textview object's scroll lock mode, in which the textview scrolls
        #   to the bottom every time text is received from the world. (If split screen mode is

lib/Games/Axmud/Obj/TextView.pm  view on Meta::CPAN

    sub scroll
        { $_[0]->{scroll} }
    sub scroll2
        { $_[0]->{scroll2} }
    sub startMark
        { $_[0]->{startMark} }
    sub endMark
        { $_[0]->{endMark} }
    sub searchMark
        { $_[0]->{searchMark} }
    sub popupMenu
        { $_[0]->{popupMenu} }

    sub scrollLockFlag
        { $_[0]->{scrollLockFlag} }
    sub scrollLockType
        { $_[0]->{scrollLockType} }
    sub splitScreenMode
        { $_[0]->{splitScreenMode} }

    sub colourScheme
        { $_[0]->{colourScheme} }

lib/Games/Axmud/Obj/Winmap.pm  view on Meta::CPAN

        # (These IVs the same for all standard winmaps)
        $self->ivPoke('orientation', 'top');

        # Set up $self->stripInitList
        if ($self->name eq 'main_wait') {

            # From top to bottom, the window will contain a menu bar, toolbar, Gtk3::Grid and an
            #   entry box
            $self->ivPush(
                'stripInitList',
                    'Games::Axmud::Strip::MenuBar',
                        undef,
                    'Games::Axmud::Strip::Toolbar',
                        undef,
                    'Games::Axmud::Strip::Table',
                        undef,
                    'Games::Axmud::Strip::Entry',
                        undef,
            );

        } elsif ($self->name eq 'internal_wait') {

lib/Games/Axmud/Obj/Winmap.pm  view on Meta::CPAN


        } elsif (
            $self->name eq 'main_fill'
            || $self->name eq 'main_part'
            || $self->name eq 'main_empty'
        ) {
            # From top to bottom, the window will contain a menu bar, toolbar, Gtk3::Grid, a gauge
            #   box, an entry box and an info box
            $self->ivPush(
                'stripInitList',
                    'Games::Axmud::Strip::MenuBar',
                        undef,
                    'Games::Axmud::Strip::Toolbar',
                        undef,
                    'Games::Axmud::Strip::Table',
                        undef,
                    'Games::Axmud::Strip::GaugeBox',
                        undef,
                    'Games::Axmud::Strip::SearchBox',
                        undef,
                    'Games::Axmud::Strip::Entry',

lib/Games/Axmud/Obj/WorldModel.pm  view on Meta::CPAN

            # ---------------------

            # Should the Automapper window open automatically when Axmud starts? (TRUE for yes,
            #   FALSE for no)
            autoOpenWinFlag             => FALSE,
            # Should the Automapper window open inside the session's 'main' window, if possible, and
            #   open as a normal 'grid' window, if not possible? (TRUE for yes, FALSE for no)
            pseudoWinFlag               => TRUE,
            # When the Automapper window opens, which parts of it should be visible? (TRUE for
            #   visible, FALSE for not visible)
            showMenuBarFlag             => TRUE,
            showToolbarFlag             => TRUE,
            showTreeViewFlag            => TRUE,
            showCanvasFlag              => TRUE,
            # The automapper window can show one or more toolbars, each with a set of buttons
            # A list specifying how many toolbars should be shown, besides the (compulsory) first
            #   one. The list comprises the names of the button sets to use in each additional
            #   toolbar. (This list is updated whenever the user adds/removes button sets, so it's
            #   remembered between sessions)
            # The list can contain 0, 1 or more of the button set names specified by
            #   GA::Win::Map->constButtonSetList, except for 'default'

lib/Games/Axmud/Obj/WorldModel.pm  view on Meta::CPAN


                $mapWin->markObjs(@list);
            }

            $mapWin->doDraw();
        }

        return 1;
    }

    sub updateMapMenuToolbars {

        # Can be called by anything in the automapper object (GA::Obj::Map) and the Automapper
        #   window (GA::Win::Map) to update every Automapper window using this world model
        # Also called by the painter's edit window, when ->saveChanges is applied
        # Redraws the menu bars and/or toolbars in all automapper windows using this world model
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments
        #   1 otherwise

        my ($self, $check) = @_;

        # Check for improper arguments
        if (defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->updateMapMenuToolbars', @_);
        }

        foreach my $mapWin ($self->collectMapWins()) {

            $mapWin->redrawWidgets('menu_bar', 'toolbar');
        }

        return 1;
    }

lib/Games/Axmud/Obj/WorldModel.pm  view on Meta::CPAN

            foreach my $name ($self->roomFlagOrderedList) {

                my $thisObj = $self->ivShow('roomFlagHash', $name);

                $count++;
                $thisObj->ivPoke('priority', $count);
            }

            # Must redraw the menu in any automapper windows, so that the new room flag appears in
            #   them
            $self->updateMapMenuToolbars();
        }

        # Operation complete
        return 1;
    }

    sub deleteRoomFlag {

        # Called by GA::EditWin::WorldModel->roomFlags1Tab
        # Deletes custom room flag and updates the priority list for all room flags

lib/Games/Axmud/Obj/WorldModel.pm  view on Meta::CPAN

            foreach my $name ($self->roomFlagOrderedList) {

                my $thisObj = $self->ivShow('roomFlagHash', $name);

                $count++;
                $thisObj->ivPoke('priority', $count);
            }

            # Must redraw the menu in any automapper windows, so that the old room flag no longer
            #   appears in them
            $self->updateMapMenuToolbars();
        }

        # Operation complete
        return 1;
    }

    sub toggleRoomFlags {

        # Called by GA::Win::Map->enableRoomsColumn_filterSubMenu
        # Toggles a room flag in one or more rooms. Redraws the rooms (if permitted) and
        #   recalculates the regionmap's paths (if necessary)
        #
        # Expected arguments
        #   $session    - The calling function's GA::Session
        #   $updateFlag - Flag set to TRUE if all Automapper windows using this world model should
        #                   be updated now, FALSE if not (in which case, they can be updated later
        #                   by the calling function, when it is ready)
        #   $roomFlag   - The room flag to toggle (matches one of the keys in
        #                   $self->roomFlagHash)

lib/Games/Axmud/Obj/WorldModel.pm  view on Meta::CPAN


        # Update every Automapper window using this world model
        foreach my $mapWin ($self->collectMapWins()) {

            if ($drawFlag) {

                # Redraw all drawn regions
                $mapWin->redrawRegions();
            }

            $mapWin->set_ignoreMenuUpdateFlag(TRUE);

            # Update the menu item
            if ($menuName) {

                $mapWin->setActiveItem($menuName, $self->$iv);
            }

            # Set the equivalent toolbar button, if there is one
            if ($iconName) {

                $mapWin->setActiveItem($iconName, $self->$iv);
            }

            $mapWin->set_ignoreMenuUpdateFlag(FALSE);
        }

        return 1;
    }

    sub switchMode {

        # Called by anonymous function in GA::Win::Map->enableXXXColumn
        # Sets the new value of an IV and updates each Automapper window
        #

lib/Games/Axmud/Obj/WorldModel.pm  view on Meta::CPAN

                }

                if ($mapWin->mapObj->ghostRoom) {

                    $mapWin->markObjs('room', $mapWin->mapObj->ghostRoom);
                }

                $mapWin->doDraw();
            }

            $mapWin->set_ignoreMenuUpdateFlag(TRUE);

            # Update the menu item
            if ($menuName) {

                $mapWin->setActiveItem($menuName, TRUE);
            }

            # Set the equivalent toolbar button, if there is one
            if ($iconName) {

                $mapWin->setActiveItem($iconName, TRUE);
            }

            $mapWin->set_ignoreMenuUpdateFlag(FALSE);

            # Sensitise/desensitise menu bar/toolbar items, depending on current conditions
            $mapWin->restrictWidgets();
        }

        return 1;
    }

    sub toggleWinComponents {

        # Called by anonymous function in GA::Win::Map->enableViewColumn
        # Shows (or hides) each Automapper window's major components (the menu, toolbar, treeview
        #   and canvas)
        #
        # Expected arguments
        #   $iv     - The IV matching the component to show (or hide) - one of 'showMenuBarFlag',
        #               'showToolbarFlag', 'showTreeViewFlag', 'showCanvasFlag'
        #   $flag   - The new value of the IV - TRUE or FALSE
        #
        # Return values
        #   'undef' on improper arguments
        #   1 otherwise

        my ($self, $iv, $flag, $check) = @_;

        # Check for improper arguments

lib/Games/Axmud/Obj/WorldModel.pm  view on Meta::CPAN

            $self->ivPoke($iv, TRUE);
        } else {
            $self->ivPoke($iv, FALSE);
        }

        # Show (or hide) the component in every Automapper window using this world model
        foreach my $mapWin ($self->collectMapWins()) {

            my $menuItem;

            if ($iv eq 'showMenuBarFlag') {

                $mapWin->redrawWidgets('menu_bar');
                $mapWin->setActiveItem('show_menu_bar', $self->$iv);

            } elsif ($iv eq 'showToolbarFlag') {

                $mapWin->redrawWidgets('toolbar');
                $mapWin->setActiveItem('show_toolbar', $self->$iv);

            } elsif ($iv eq 'showTreeViewFlag') {

lib/Games/Axmud/Obj/WorldModel.pm  view on Meta::CPAN

        } else {
            $self->ivAdd('roomFilterApplyHash', $filter, FALSE);
        }

        # Update every Automapper window using this world model
        foreach my $mapWin ($self->collectMapWins()) {

            # Redraw all drawn regions
            $mapWin->redrawRegions();

            $mapWin->set_ignoreMenuUpdateFlag(TRUE);

            # Update the menu item
            $mapWin->setActiveItem($filter . '_filter', $flag);

            # Set the equivalent toolbar button
            $mapWin->setActiveItem('icon_' . $filter . '_filter', $flag);

            $mapWin->set_ignoreMenuUpdateFlag(FALSE);
        }

        return 1;
    }

    sub switchRoomInteriorMode {

        # Called by anonymous function in GA::Win::Map->enableViewColumn
        # Sets the value of $self->roomInteriorMode and updates each Automapper window
        #

lib/Games/Axmud/Obj/WorldModel.pm  view on Meta::CPAN

        }

        $self->ivPoke('roomInteriorMode', $mode);

        # Update every Automapper window using this world model
        foreach my $mapWin ($self->collectMapWins()) {

            # Redraw all drawn regions
            $mapWin->redrawRegions();

            $mapWin->set_ignoreMenuUpdateFlag(TRUE);

            # Update the menu item
            $mapWin->setActiveItem('interior_mode_' . $mode, TRUE);

            # Set the equivalent toolbar button
            $mapWin->setActiveItem('icon_interior_mode_' . $mode, TRUE);

            $mapWin->set_ignoreMenuUpdateFlag(FALSE);
        }

        return 1;
    }

    sub switchRegionDrawExitMode {

        # Called by anonymous function in GA::Win::Map->enableViewColumn
        # Sets the value of GA::Obj::Regionmap->drawExitMode and updates each Automapper window
        #

lib/Games/Axmud/Obj/WorldModel.pm  view on Meta::CPAN

        $regionmapObj->ivPoke('drawExitMode', $mode);

        # Update every Automapper window using this world model
        foreach my $mapWin ($self->collectMapWins()) {

            my ($menuName, $menuItem);

            # Redraw the specified regionmap (the TRUE argument means don't redraw other regionmaps)
            $mapWin->redrawRegions($regionmapObj, TRUE);

            $mapWin->set_ignoreMenuUpdateFlag(TRUE);

            # Update the menu item
            if ($mode eq 'no_exit') {
                $menuName = 'region_draw_no_exits';
            } elsif ($mode eq 'simple_exit') {
                $menuName = 'region_draw_simple_exits';
            } elsif ($mode eq 'complex_exit') {
                $menuName = 'region_draw_complex_exits';
            }

            $mapWin->setActiveItem($menuName, FALSE);

            $mapWin->set_ignoreMenuUpdateFlag(FALSE);

            # Sensitise/desensitise menu bar/toolbar items, depending on current conditions
            $mapWin->restrictWidgets();
        }

        return 1;
    }

    sub toggleObscuredExitFlag {

lib/Games/Axmud/Obj/WorldModel.pm  view on Meta::CPAN


        # Update every Automapper window using this world model
        foreach my $mapWin ($self->collectMapWins()) {

            my ($menuName, $menuItem);

            # Redraw the specified regionmap (the TRUE argument means don't redraw other regionmaps)
            $mapWin->redrawRegions($regionmapObj, TRUE);

            # Update the menu item
            $mapWin->set_ignoreMenuUpdateFlag(TRUE);
            $mapWin->setActiveItem('obscured_exits_region', $regionmapObj->obscuredExitFlag);
            $mapWin->set_ignoreMenuUpdateFlag(FALSE);

            # Sensitise/desensitise menu bar/toolbar items, depending on current conditions
            $mapWin->restrictWidgets();
        }

        return 1;
    }

    sub toggleObscuredExitRedrawFlag {

lib/Games/Axmud/Obj/WorldModel.pm  view on Meta::CPAN


        # Update every Automapper window using this world model
        foreach my $mapWin ($self->collectMapWins()) {

            my ($menuName, $menuItem);

            # Redraw the specified regionmap (the TRUE argument means don't redraw other regionmaps)
            $mapWin->redrawRegions($regionmapObj, TRUE);

            # Update the menu item
            $mapWin->set_ignoreMenuUpdateFlag(TRUE);
            $mapWin->setActiveItem(
                'auto_redraw_obscured_region',
                $regionmapObj->obscuredExitRedrawFlag,
            );
            $mapWin->set_ignoreMenuUpdateFlag(FALSE);

            # Sensitise/desensitise menu bar/toolbar items, depending on current conditions
            $mapWin->restrictWidgets();
        }

        return 1;
    }

    sub toggleDrawOrnamentsFlag {

lib/Games/Axmud/Obj/WorldModel.pm  view on Meta::CPAN


        # Update every Automapper window using this world model
        foreach my $mapWin ($self->collectMapWins()) {

            my ($menuName, $menuItem);

            # Redraw the specified regionmap (the TRUE argument means don't redraw other regionmaps)
            $mapWin->redrawRegions($regionmapObj, TRUE);

            # Update the menu item
            $mapWin->set_ignoreMenuUpdateFlag(TRUE);
            $mapWin->setActiveItem('draw_ornaments_region', $regionmapObj->drawOrnamentsFlag);
            $mapWin->set_ignoreMenuUpdateFlag(FALSE);

            # Sensitise/desensitise menu bar/toolbar items, depending on current conditions
            $mapWin->restrictWidgets();
        }

        return 1;
    }

    sub setMagnification {

lib/Games/Axmud/Obj/WorldModel.pm  view on Meta::CPAN

            if ($sensitivity == 0) {
                $menuName = 'track_always';
            } elsif ($sensitivity == 0.33) {
                $menuName = 'track_near_centre';
            } elsif ($sensitivity == 0.66) {
                $menuName = 'track_near_edge';
            } else {
                $menuName = 'track_not_visible';
            }

            $mapWin->set_ignoreMenuUpdateFlag(TRUE);

            # Update the menu item
            $mapWin->setActiveItem($menuName, TRUE);

            # Set the equivalent toolbar button
            $mapWin->setActiveItem('icon_' . $menuName, TRUE);

            $mapWin->set_ignoreMenuUpdateFlag(FALSE);
        }

        return 1;
    }

    # (Called from GA::Win::Map menu, 'Mode' column)

    sub setAutoCompareMode {

        # Called by anonymous function in GA::Win::Map->enableModeColumn

lib/Games/Axmud/Obj/WorldModel.pm  view on Meta::CPAN


            return $axmud::CLIENT->writeImproper($self->_objClass . '->setAutoCompareMode', @_);
        }

        # Update the IV
        $self->ivPoke('autoCompareMode', $mode);

        # Update every Automapper window using this world model
        foreach my $mapWin ($self->collectMapWins()) {

            $mapWin->set_ignoreMenuUpdateFlag(TRUE);

            # Update the menu item
            if ($mode eq 'default') {
                $mapWin->setActiveItem('auto_compare_default', TRUE);
            } elsif ($mode eq 'default') {
                $mapWin->setActiveItem('auto_compare_new', TRUE);
            } elsif ($mode eq 'default') {
                $mapWin->setActiveItem('auto_compare_current', TRUE);
            }

            $mapWin->set_ignoreMenuUpdateFlag(FALSE);

            # If interior counts are currently showing the number of rooms that match the current
            #   room, redraw the current room to show the counts
            if ($self->roomInteriorMode eq 'compare_count' && $mapWin->mapObj->currentRoom) {

                $mapWin->markObjs('room', $mapWin->mapObj->currentRoom);
                $mapWin->doDraw();
            }
        }

lib/Games/Axmud/Obj/WorldModel.pm  view on Meta::CPAN

        # Update the IV
        if (! $flag) {
            $self->ivPoke('autoCompareAllFlag', FALSE);
        } else {
            $self->ivPoke('autoCompareAllFlag', TRUE);
        }

        # Update every Automapper window using this world model
        foreach my $mapWin ($self->collectMapWins()) {

            $mapWin->set_ignoreMenuUpdateFlag(TRUE);

            # Update the menu item
            if (! $flag) {
                $mapWin->setActiveItem('auto_compare_region', TRUE);
            } else {
                $mapWin->setActiveItem('auto_compare_model', TRUE);
            }

            $mapWin->set_ignoreMenuUpdateFlag(FALSE);
        }

        return 1;
    }

    sub setAutoSlideMode {

        # Called by anonymous function in GA::Win::Map->enableModeColumn
        # Updates the world model's ->autoSlideMode and updates each Automapper window using this
        #   world model

lib/Games/Axmud/Obj/WorldModel.pm  view on Meta::CPAN

        }

        # Update the IV
        $self->ivPoke('autoSlideMode', $mode);

        # Update every Automapper window using this world model
        foreach my $mapWin ($self->collectMapWins()) {

            my $menuItem;

            $mapWin->set_ignoreMenuUpdateFlag(TRUE);

            # Update the menu item
            if ($mode eq 'default') {
                $mapWin->setActiveItem('slide_default', TRUE);
            } elsif ($mode eq 'orig_pull') {
                $mapWin->setActiveItem('slide_orig_pull', TRUE);
            } elsif ($mode eq 'orig_push') {
                $mapWin->setActiveItem('slide_orig_push', TRUE);
            } elsif ($mode eq 'other_pull') {
                $mapWin->setActiveItem('slide_other_pull', TRUE);
            } elsif ($mode eq 'other_push') {
                $mapWin->setActiveItem('slide_other_push', TRUE);
            } elsif ($mode eq 'dest_pull') {
                $mapWin->setActiveItem('slide_dest_pull', TRUE);
            } elsif ($mode eq 'dest_push') {
                $mapWin->setActiveItem('slide_dest_push', TRUE);
            }

            $mapWin->set_ignoreMenuUpdateFlag(FALSE);
        }

        return 1;
    }

    sub toggleDisableUpdateModeFlag {

        # Called by anonymous function in GA::Win::Map->enableModeColumn
        # Toggles the world model's ->disableUpdateModeFlag and updates each Automapper window using
        #   this world model

lib/Games/Axmud/Obj/WorldModel.pm  view on Meta::CPAN

        # Update the IV
        if ($flag) {
            $self->ivPoke('disableUpdateModeFlag', TRUE);
        } else {
            $self->ivPoke('disableUpdateModeFlag', FALSE);
        }

        # Update every Automapper window using this world model
        foreach my $mapWin ($self->collectMapWins()) {

            $mapWin->set_ignoreMenuUpdateFlag(TRUE);

            # Update the menu item
            $mapWin->setActiveItem('disable_update_mode', $self->disableUpdateModeFlag);

            # The call to ->setMode makes sure the Automapper window's mode is switched from
            #   'update' to 'follow' if 'update' mode has just been disabled, and also makes sure
            #   the menu/toolbar buttons are sensitised or not, as appropriate
            $mapWin->setMode($mapWin->mode);

            $mapWin->set_ignoreMenuUpdateFlag(FALSE);
        }

        return 1;
    }

    sub toggleShowTooltipsFlag {

        # Called by anonymous function in GA::Win::Map->enableModeColumn
        # Toggles the world model's ->showTooltipsFlag and updates each Automapper window using this
        #   world model

lib/Games/Axmud/Obj/WorldModel.pm  view on Meta::CPAN

        # Update the IV
        if ($flag) {
            $self->ivPoke('showTooltipsFlag', TRUE);
        } else {
            $self->ivPoke('showTooltipsFlag', FALSE);
        }

        # Update every Automapper window using this world model
        foreach my $mapWin ($self->collectMapWins()) {

            $mapWin->set_ignoreMenuUpdateFlag(TRUE);

            # Update the menu item
            $mapWin->setActiveItem('show_tooltips', $self->showTooltipsFlag);

            $mapWin->set_ignoreMenuUpdateFlag(FALSE);

            if (! $flag) {

                # If the tooltip window is currently visible, hide it
                $mapWin->hideTooltips();
            }
        }

        return 1;
    }

lib/Games/Axmud/Obj/WorldModel.pm  view on Meta::CPAN


            return $axmud::CLIENT->writeImproper($self->_objClass . '->setCheckableDirMode', @_);
        }

        # Update the IV
        $self->ivPoke('checkableDirMode', $mode);

        # Update every Automapper window using this world model
        foreach my $mapWin ($self->collectMapWins()) {

            $mapWin->set_ignoreMenuUpdateFlag(TRUE);

            # Update the menu item
            if ($mode eq 'simple') {
                $mapWin->setActiveItem('checkable_dir_simple', TRUE);
            } elsif ($mode eq 'diku') {
                $mapWin->setActiveItem('checkable_dir_diku', TRUE);
            } elsif ($mode eq 'lp') {
                $mapWin->setActiveItem('checkable_dir_lp', TRUE);
            } elsif ($mode eq 'complex') {
                $mapWin->setActiveItem('checkable_dir_complex', TRUE);
            }

            $mapWin->set_ignoreMenuUpdateFlag(FALSE);

            # If interior counts are currently showing checked/checkable directions, redraw all
            #   drawn regions to update those counts
            if ($self->roomInteriorMode eq 'checked_count') {

                $mapWin->redrawRegions();
            }
        }

        return 1;

lib/Games/Axmud/Obj/WorldModel.pm  view on Meta::CPAN

        # Check for improper arguments
        if (! defined $mode || defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->set_roomFlagShowMode', @_);
        }

        # Update IVs
        $self->ivPoke('roomFlagShowMode', $mode);

        # Must redraw the menu in any automapper windows, so that the new room flag appears in them
        $self->updateMapMenuToolbars();

        return 1;
    }

    sub set_searchSelectRoomsFlag {

        my ($self, $flag, $check) = @_;

        # Check for improper arguments
        if (! defined $flag || defined $check) {

lib/Games/Axmud/Obj/WorldModel.pm  view on Meta::CPAN


        if ($flag) {
            $self->ivPoke('showCanvasFlag', TRUE);
        } else {
            $self->ivPoke('showCanvasFlag', FALSE);
        }

        return 1;
    }

    sub set_showMenuBarFlag {

        my ($self, $flag, $check) = @_;

        # Check for improper arguments
        if (! defined $flag || defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->set_showMenuBarFlag', @_);
        }

        if ($flag) {
            $self->ivPoke('showMenuBarFlag', TRUE);
        } else {
            $self->ivPoke('showMenuBarFlag', FALSE);
        }

        return 1;
    }

    sub set_showToolbarFlag {

        my ($self, $flag, $check) = @_;

        # Check for improper arguments

lib/Games/Axmud/Obj/WorldModel.pm  view on Meta::CPAN

    sub roomTagHash
        { my $self = shift; return %{$self->{roomTagHash}}; }

    sub teleportHash
        { my $self = shift; return %{$self->{teleportHash}}; }

    sub autoOpenWinFlag
        { $_[0]->{autoOpenWinFlag} }
    sub pseudoWinFlag
        { $_[0]->{pseudoWinFlag} }
    sub showMenuBarFlag
        { $_[0]->{showMenuBarFlag} }
    sub showToolbarFlag
        { $_[0]->{showToolbarFlag} }
    sub showTreeViewFlag
        { $_[0]->{showTreeViewFlag} }
    sub showCanvasFlag
        { $_[0]->{showCanvasFlag} }
    sub buttonSetList
        { my $self = shift; return @{$self->{buttonSetList}}; }
    sub preferRoomFlagList
        { my $self = shift; return @{$self->{preferRoomFlagList}}; }

lib/Games/Axmud/PrefWin.pm  view on Meta::CPAN

        $checkButton8->set_active($axmud::CLIENT->confirmCloseTabFlag);
        $checkButton8->signal_connect('toggled' => sub {

            $self->session->pseudoCmd('setsession -t', $self->pseudoCmdMode);
            $checkButton8->set_active($axmud::CLIENT->confirmCloseTabFlag);
        });

        my $checkButton9 = $self->addCheckButton(
            $grid, 'Confirm before closing from menu', undef, TRUE,
            7, 12, 9, 10);
        $checkButton9->set_active($axmud::CLIENT->confirmCloseMenuFlag);
        $checkButton9->signal_connect('toggled' => sub {

            $self->session->pseudoCmd('setsession -e', $self->pseudoCmdMode);
            $checkButton9->set_active($axmud::CLIENT->confirmCloseMenuFlag);
        });

        my $checkButton10 = $self->addCheckButton(
            $grid, 'Confirm before closing from toolbar', undef, TRUE,
            7, 12, 10, 11);
        $checkButton10->set_active($axmud::CLIENT->confirmCloseToolButtonFlag);
        $checkButton10->signal_connect('toggled' => sub {

            $self->session->pseudoCmd('setsession -r', $self->pseudoCmdMode);
            $checkButton10->set_active($axmud::CLIENT->confirmCloseToolButtonFlag);

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

# even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with this program. If not,
# see <http://www.gnu.org/licenses/>.
#
#
# Games::Axmud::Strip::xxx
# Objects handling strips within an 'internal' window's client area

{ package Games::Axmud::Strip::MenuBar;

    use strict;
    use warnings;
#   use diagnostics;

    use Glib qw(TRUE FALSE);

    our @ISA = qw(Games::Axmud::Generic::Strip Games::Axmud);

    ##################
    # Constructors

    sub new {

        # Called by GA::Win::Internal->drawWidgets or ->addStripObj
        # Creates the GA::Strip::MenuBar - a non-compulsory strip object containing a Gtk3::MenuBar
        #
        # Expected arguments
        #   $number     - The strip object's number within the parent window (matches
        #                   GA::Win::Internal->stripCount, or -1 for a temporary strip object
        #                   created to access its default IVs)
        #   $winObj     - The parent window object (GA::Win::Internal). 'temp' for temporary strip
        #                   objects
        #
        # Optional arguments
        #   %initHash   - A hash containing arbitrary data to use as the strip object's

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

            #   parent window, set to FALSE if any number of instances can be added
            jealousyFlag                => TRUE,
            # Flag set to TRUE if this strip object can be added when $axmud::BLIND_MODE_FLAG is
            #   TRUE, FALSE if it can't be added (because it's not useful for visually-impaired
            #   users)
            blindFlag                   => FALSE,
            # Flag set to TRUE if the main container widget, stored in $self->packingBox, should be
            #   allowed to accept the focus, FALSE if not. The restriction is applied during the
            #   call to GA::Win::Internal->drawWidgets and ->addStripObj. Even if FALSE, widgets in
            #   the container widget can be set to accept the focus (e.g. the Gtk3::Entry in
            #   GA::Strip::MenuBar)
            allowFocusFlag              => FALSE,

            # Initialisation settings stored as a hash (see the comments above)
            initHash                    => \%modHash,
            # Reference to a function to call when some widget is used. This IV is set only when
            #   required by this type of strip object. It can be set by a call to
            #   $self->set_func() or by some setting in $self->initHash, which is applied in the
            #   call to $self->objEnable(). To obtain a reference to an OOP method, you can use the
            #   generic object function Games::Axmud->getMethodRef()
            funcRef                     => undef,

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

            funcID                      => undef,

            # The container widget for this strip object (usually a Gtk3::HBox or Gtk3::VBox). This
            #   widget is the one added to the window's main Gtk3::HBox or Gtk3::VBox
            packingBox                  => undef,       # Gtk3::VBox

            # Other IVs
            # ---------

            # Widgets
            menuBar                     => undef,       # Gtk3::MenuBar

            # Menu items which will be sensitised or desensitised, depending on the context. Hash
            #   in the form:
            #       $menuItemHash{'item_name'} = Gtk3_widget
            #   ...where:
            #       'item_name' is a descriptive scalar, e.g. 'move_up_level'
            #       'Gtk3_widget' is the Gtk3 menu item
            menuItemHash                => {},

            # The menu column for 'plugins', which can be extended by any loaded plugins
            pluginMenu                  => undef,       # Gtk3::Menu
            # Hash of sub-menus in the 'plugins' menu column, one for each plugin that wants one, in
            #   the form
            #       $pluginHash{plugin_name} = menu_widget
            pluginHash                  => {},
            # Additional list of menu items added by plugins, which will be sensitised or
            #   desensitised, depending on the context. Hash in the form:
            #       $pluginMenuItemHash{'plugin_name'} = Gtk3_widget
            pluginMenuItemHash          => {},

            # Flag set to TRUE when the 'save all sessions' menu item is selected (desensitises
            #   some other menu items)
            saveAllSessionsFlag         => FALSE,
        };

        # Bless the object into existence
        bless $self, $class;

        return $self;

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

        # Check for improper arguments
        if (! defined $winmapObj || defined $check) {

             return $axmud::CLIENT->writeImproper($self->_objClass . '->objEnable', @_);
        }

        # Create a packing box
        my $vBox = Gtk3::VBox->new(FALSE, 0);
        $vBox->set_border_width(0);

        # Create a Gtk3::MenuBar
        my $menuBar = Gtk3::MenuBar->new();
        $vBox->pack_start($menuBar, TRUE, TRUE, 0);

        # 'World' column
        my $menuColumn_world = $self->drawWorldColumn();
        my $menuItem_world = Gtk3::MenuItem->new('_World');
        $menuItem_world->set_submenu($menuColumn_world);
        $menuBar->append($menuItem_world);

        # 'File' column
        my $menuColumn_file = $self->drawFileColumn();
        my $menuItem_file = Gtk3::MenuItem->new('_File');
        $menuItem_file->set_submenu($menuColumn_file);
        $menuBar->append($menuItem_file);

        # 'Edit' column
        my $menuColumn_edit = $self->drawEditColumn();
        my $menuItem_edit = Gtk3::MenuItem->new('_Edit');
        $menuItem_edit->set_submenu($menuColumn_edit);
        $menuBar->append($menuItem_edit);

        # 'Interfaces' column
        my $menuColumn_interfaces = $self->drawInterfacesColumn();
        my $menuItem_interfaces = Gtk3::MenuItem->new('_Interfaces');
        $menuItem_interfaces->set_submenu($menuColumn_interfaces);
        $menuBar->append($menuItem_interfaces);

        # 'Tasks' column
        my $menuColumn_tasks = $self->drawTasksColumn();
        my $menuItem_tasks = Gtk3::MenuItem->new('_Tasks');
        $menuItem_tasks->set_submenu($menuColumn_tasks);
        $menuBar->append($menuItem_tasks);

        # 'Display' column
        my $menuColumn_display = $self->drawDisplayColumn();
        my $menuItem_display = Gtk3::MenuItem->new('_Display');
        $menuItem_display->set_submenu($menuColumn_display);
        $menuBar->append($menuItem_display);

        # 'Commands' column
        my $menuColumn_commands = $self->drawCommandsColumn();
        my $menuItem_commands = Gtk3::MenuItem->new('_Commands');
        $menuItem_commands->set_submenu($menuColumn_commands);
        $menuBar->append($menuItem_commands);

        # 'Recordings' column
        my $menuColumn_recordings = $self->drawRecordingsColumn();
        my $menuItem_recordings = Gtk3::MenuItem->new('_Recordings');
        $menuItem_recordings->set_submenu($menuColumn_recordings);
        $menuBar->append($menuItem_recordings);

        # 'Axbasic' column
        my $menuColumn_basic = $self->drawAxbasicColumn();
        my $menuItem_basic = Gtk3::MenuItem->new('_' . $axmud::BASIC_NAME);
        $menuItem_basic->set_submenu($menuColumn_basic);
        $menuBar->append($menuItem_basic);

        # 'Plugins' column
        my $menuColumn_plugins = $self->drawPluginsColumn();
        my $menuItem_plugins = Gtk3::MenuItem->new('_Plugins');
        $menuItem_plugins->set_submenu($menuColumn_plugins);
        $menuBar->append($menuItem_plugins);

        # 'Help' column
        my $menuColumn_help = $self->drawHelpColumn();
        my $menuItem_help = Gtk3::MenuItem->new('_Help');
        $menuItem_help->set_submenu($menuColumn_help);
        $menuBar->append($menuItem_help);

        # Update IVs
        $self->ivPoke('packingBox', $vBox);
        $self->ivPoke('menuBar', $menuBar);
        $self->ivPoke('pluginMenu', $menuColumn_plugins);

        # If any plugins have registered their desire to create sub-menus, call those plugins and
        #   create the sub-menus now
        foreach my $pluginObj (sort {lc($a) cmp lc($b)} ($axmud::CLIENT->ivValues('pluginHash'))) {

            my ($funcRef, $subMenu);

            if (
                $pluginObj->enabledFlag
                && $axmud::CLIENT->ivExists('pluginMenuFuncHash', $pluginObj->name)
            ) {
                $funcRef = $axmud::CLIENT->ivShow('pluginMenuFuncHash', $pluginObj->name);
                $subMenu = $self->addPluginWidgets($pluginObj->name);

                if ($funcRef && $subMenu) {

                    &$funcRef($self, $subMenu);
                }
            }
        }

        # Sensitise/desensitise menu bar/toolbar items, depending on current conditions
        $axmud::CLIENT->desktopObj->restrictWidgets();

        return 1;
    }

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

#   sub setWidgetsIfSession {}              # Inherited from GA::Generic::Strip

#   sub setWidgetsChangeSession {}          # Inherited from GA::Generic::Strip

    # ->signal_connects are stored in $self->drawWorldColumn, etc

    # Other functions

    sub drawWorldColumn {

        # Called by $self->enableMenu
        # Sets up the menu's 'World' column
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments, or if the menu can't be created
        #   Otherwise returns the Gtk3::Menu created

        my ($self, $check) = @_;

        # Local variables
        my ($mode, $choice);

        # Check for improper arguments
        if (defined $check) {

             return $axmud::CLIENT->writeImproper($self->_objClass . '->drawWorldColumn', @_);
        }

        # Import IVs (for convenience)
        $mode = $self->winObj->pseudoCmdMode;

        # Set up column
        my $menuColumn_world = Gtk3::Menu->new();
        if (! $menuColumn_world) {

            return undef;
        }

        my $menuItem_connect = Gtk3::ImageMenuItem->new('_Connect...');
        my $menuImg_connect = Gtk3::Image->new_from_stock('gtk-connect', 'menu');
        $menuItem_connect->set_image($menuImg_connect);
        $menuItem_connect->signal_connect('activate' => sub {

            my $winObj;

            if ($self->winObj->visibleSession) {

                $self->winObj->visibleSession->pseudoCmd('connect', $mode);

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

                        # Only one Connections window can be open at a time
                        $axmud::CLIENT->set_connectWin($winObj);
                    }
                }
            }
        });
        $menuColumn_world->append($menuItem_connect);
        # (Desensitised only when the setup wizwin is open)
        $self->ivAdd('menuItemHash', 'connect', $menuItem_connect);

        my $menuItem_reconnect = Gtk3::ImageMenuItem->new('_Reconnect');
        my $menuImg_reconnect = Gtk3::Image->new_from_stock('gtk-connect', 'menu');
        $menuItem_reconnect->set_image($menuImg_reconnect);
        $menuItem_reconnect->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('reconnect', $mode);
        });
        $menuColumn_world->append($menuItem_reconnect);
        # (Requires a visible session)
        $self->ivAdd('menuItemHash', 'reconnect', $menuItem_reconnect);

        my $menuItem_reconnectOffline = Gtk3::MenuItem->new('Reconnect _offline');
        $menuItem_reconnectOffline->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('reconnect -o', $mode);
        });
        $menuColumn_world->append($menuItem_reconnectOffline);
        # (Requires a visible session)
        $self->ivAdd('menuItemHash', 'reconnect_offline', $menuItem_reconnectOffline);

        my $menuItem_xConnect = Gtk3::MenuItem->new('Reconnect (_no save)');
        $menuItem_xConnect->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('xconnect', $mode);
        });
        $menuColumn_world->append($menuItem_xConnect);
        # (Requires a visible session)
        $self->ivAdd('menuItemHash', 'xconnect', $menuItem_xConnect);

        my $menuItem_xConnectOffline = Gtk3::MenuItem->new('Reconnect offline (no _save)');
        $menuItem_xConnectOffline->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('xconnect -o', $mode);
        });
        $menuColumn_world->append($menuItem_xConnectOffline);
        # (Requires a visible session)
        $self->ivAdd('menuItemHash', 'xconnect_offline', $menuItem_xConnectOffline);

        $menuColumn_world->append(Gtk3::SeparatorMenuItem->new());   # Separator

        my $menuItem_login = Gtk3::ImageMenuItem->new('Character _login');
        my $menuImg_login = Gtk3::Image->new_from_stock('gtk-network', 'menu');
        $menuItem_login->set_image($menuImg_login);
        $menuItem_login->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('login', $mode);
        });
        $menuColumn_world->append($menuItem_login);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'login', $menuItem_login);

        $menuColumn_world->append(Gtk3::SeparatorMenuItem->new());   # Separator

        my $menuItem_quit = Gtk3::ImageMenuItem->new('Send _quit');
        my $menuImg_quit = Gtk3::Image->new_from_stock('gtk-disconnect', 'menu');
        $menuItem_quit->set_image($menuImg_quit);
        $menuItem_quit->signal_connect('activate' => sub {

            if (
                $self->promptUser(
                    'Confirm quit',
                    'Are you sure you want to send the \'quit\' command?',
                )
            ) {
                $self->winObj->visibleSession->pseudoCmd('quit', $mode);
            }
        });
        $menuColumn_world->append($menuItem_quit);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'quit', $menuItem_quit);

        my $menuItem_qquit = Gtk3::MenuItem->new('Send quit (no sa_ve)');
        $menuItem_qquit->signal_connect('activate' => sub {

            if (
                $self->promptUser(
                    'Confirm quit',
                    'Are you sure you want to send the \'quit\' command without saving?',
                )
            ) {
                $self->winObj->visibleSession->pseudoCmd('qquit', $mode);
            }
        });
        $menuColumn_world->append($menuItem_qquit);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'qquit', $menuItem_qquit);

        my $menuItem_quitAll = Gtk3::MenuItem->new('Send quit (_all sessions)');
        $menuItem_quitAll->signal_connect('activate' => sub {

            if (
                $self->promptUser(
                    'Confirm quit',
                    'Are you sure you want to send the \'quit\' command in all sessions?',
                )
            ) {
                $self->winObj->visibleSession->pseudoCmd('quitall', $mode);
            }
        });
        $menuColumn_world->append($menuItem_quitAll);
        # (Requires a visible session)
        $self->ivAdd('menuItemHash', 'quit_all', $menuItem_quitAll);

        $menuColumn_world->append(Gtk3::SeparatorMenuItem->new());   # Separator

        my $menuItem_exit = Gtk3::ImageMenuItem->new('_Exit session');
        my $menuImg_exit = Gtk3::Image->new_from_stock('gtk-disconnect', 'menu');
        $menuItem_exit->set_image($menuImg_exit);
        $menuItem_exit->signal_connect('activate' => sub {

            if (
                $self->promptUser(
                    'Confirm exit',
                    'Are you sure you want to exit this session?',
                )
            ) {
                $self->winObj->visibleSession->pseudoCmd('exit', $mode);
            }
        });
        $menuColumn_world->append($menuItem_exit);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'exit', $menuItem_exit);

        my $menuItem_xxit = Gtk3::MenuItem->new('E_xit session (no save)');
        $menuItem_xxit->signal_connect('activate' => sub {

            if (
                $self->promptUser(
                    'Confirm exit',
                    'Are you sure you want to exit this session without saving?',
                )
            ) {
                $self->winObj->visibleSession->pseudoCmd('xxit', $mode);
            }
        });
        $menuColumn_world->append($menuItem_xxit);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'xxit', $menuItem_xxit);

        my $menuItem_exitAll = Gtk3::MenuItem->new('Ex_it all sessions');
        $menuItem_exitAll->signal_connect('activate' => sub {

            if (
                $self->promptUser(
                    'Confirm exit',
                    'Are you sure you want to exit every session?',
                )
            ) {
                $self->winObj->visibleSession->pseudoCmd('exitall', $mode);
            }
        });
        $menuColumn_world->append($menuItem_exitAll);
        # (Requires a visible session)
        $self->ivAdd('menuItemHash', 'exit_all', $menuItem_exitAll);

        $menuColumn_world->append(Gtk3::SeparatorMenuItem->new());   # Separator

        my $menuItem_stopSession = Gtk3::ImageMenuItem->new('S_top session');
        my $menuImg_stopSession = Gtk3::Image->new_from_stock('gtk-close', 'menu');
        $menuItem_stopSession->set_image($menuImg_stopSession);
        $menuItem_stopSession->signal_connect('activate' => sub {

            if (
                $self->winObj->visibleSession->status eq 'connected'
                && $axmud::CLIENT->confirmCloseMenuFlag
            ) {
                $choice = $self->winObj->showMsgDialogue(
                    'Stop session',
                    'question',
                    'This session is connected to a world. Are you sure you want to stop it?',
                    'yes-no',
                );

                if ($choice eq 'yes') {

lib/Games/Axmud/Strip.pm  view on Meta::CPAN


            } else {

                $self->winObj->visibleSession->pseudoCmd('stopsession', $mode);
            }
        });
        $menuColumn_world->append($menuItem_stopSession);
        # (Requires a visible session)
        $self->ivAdd('menuItemHash', 'stop_session', $menuItem_stopSession);

        my $menuItem_stopClient = Gtk3::ImageMenuItem->new('Sto_p client');
        my $menuImg_stopClient = Gtk3::Image->new_from_stock('gtk-quit', 'menu');
        $menuItem_stopClient->set_image($menuImg_stopClient);
        $menuItem_stopClient->signal_connect('activate' => sub {

            # If there are any connected sessions or unsaved files, prompt the user before executing
            #   the client command; otherwise go ahead and do the ';stopclient' operation
            if (
                $axmud::CLIENT->checkSessions()
                || $self->promptUser(
                    'Confirm stop client',

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

        $menuColumn_world->append($menuItem_stopClient);
        # (Desensitised only when the setup wizwin is open)
        $self->ivAdd('menuItemHash', 'stop_client', $menuItem_stopClient);

        # Setup complete
        return $menuColumn_world;
    }

    sub drawFileColumn {

        # Called by $self->enableMenu
        # Sets up the menu's 'File' column
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments, or if the menu can't be created
        #   Otherwise returns the Gtk3::Menu created

        my ($self, $check) = @_;

        # Local variables
        my ($mode, $forceSwitch, $allSessionSwitch);

        # Check for improper arguments
        if (defined $check) {

             return $axmud::CLIENT->writeImproper($self->_objClass . '->drawFileColumn', @_);

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

        $mode = $self->winObj->pseudoCmdMode;

        # A pair of radio buttons toggle the value of this string between '' and ' -f', used with
        #   the ';save' command
        $forceSwitch = '';
        # Another pair of buttons toggle the value of this string between '' and ' -a', used with
        #   the ';save' command
        $allSessionSwitch = '';

        # Set up column
        my $menuColumn_file = Gtk3::Menu->new();
        if (! $menuColumn_file) {

            return undef;
        }

        my $menuItem_loadAll = Gtk3::ImageMenuItem->new('_Load all');
        my $menuImg_loadAll = Gtk3::Image->new_from_stock('gtk-open', 'menu');
        $menuItem_loadAll->set_image($menuImg_loadAll);
        $menuItem_loadAll->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('load', $mode);
        });
        $menuColumn_file->append($menuItem_loadAll);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'load_all', $menuItem_loadAll);

            # 'Load files' submenu
            my $subMenu_loadFile = Gtk3::Menu->new();

            my $menuItem_loadFile_worldModel = Gtk3::MenuItem->new('_World model file');
            $menuItem_loadFile_worldModel->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('load -m', $mode);
            });
            $subMenu_loadFile->append($menuItem_loadFile_worldModel);

            my $menuItem_loadFile_tasks = Gtk3::MenuItem->new('_Tasks file');
            $menuItem_loadFile_tasks->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('load -t', $mode);
            });
            $subMenu_loadFile->append($menuItem_loadFile_tasks);

            my $menuItem_loadFile_scripts = Gtk3::MenuItem->new('_Scripts file');
            $menuItem_loadFile_scripts->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('load -s', $mode);
            });
            $subMenu_loadFile->append($menuItem_loadFile_scripts);

            my $menuItem_loadFile_contacts = Gtk3::MenuItem->new('_Contacts file');
            $menuItem_loadFile_contacts->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('load -n', $mode);
            });
            $subMenu_loadFile->append($menuItem_loadFile_contacts);

            my $menuItem_loadFile_dicts = Gtk3::MenuItem->new('_Dictionaries file');
            $menuItem_loadFile_dicts->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('load -y', $mode);
            });
            $subMenu_loadFile->append($menuItem_loadFile_dicts);

            my $menuItem_loadFile_toolbar = Gtk3::MenuItem->new('Tool_bar file');
            $menuItem_loadFile_toolbar->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('load -b', $mode);
            });
            $subMenu_loadFile->append($menuItem_loadFile_toolbar);

            my $menuItem_loadFile_userComm = Gtk3::MenuItem->new('_User commands file');
            $menuItem_loadFile_userComm->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('load -u', $mode);
            });
            $subMenu_loadFile->append($menuItem_loadFile_userComm);

            my $menuItem_loadFile_zonemaps = Gtk3::MenuItem->new('_Zonemaps file');
            $menuItem_loadFile_zonemaps->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('load -z', $mode);
            });
            $subMenu_loadFile->append($menuItem_loadFile_zonemaps);

            my $menuItem_loadFile_winmaps = Gtk3::MenuItem->new('Win_maps file');
            $menuItem_loadFile_winmaps->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('load -p', $mode);
            });
            $subMenu_loadFile->append($menuItem_loadFile_winmaps);

            my $menuItem_loadFile_ttsObjs = Gtk3::MenuItem->new('T_ext-to-speech file');
            $menuItem_loadFile_ttsObjs->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('load -x', $mode);
            });
            $subMenu_loadFile->append($menuItem_loadFile_ttsObjs);

        my $menuItem_loadFile = Gtk3::MenuItem->new('L_oad files');
        $menuItem_loadFile->set_submenu($subMenu_loadFile);
        $menuColumn_file->append($menuItem_loadFile);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'load_file', $menuItem_loadFile);

        $menuColumn_file->append(Gtk3::SeparatorMenuItem->new());   # Separator

        my $menuItem_saveAll = Gtk3::ImageMenuItem->new('_Save all');
        my $menuImg_saveAll = Gtk3::Image->new_from_stock('gtk-save', 'menu');
        $menuItem_saveAll->set_image($menuImg_saveAll);
        $menuItem_saveAll->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd(
                'save ' . $forceSwitch . $allSessionSwitch,
                $mode,
            );
        });
        $menuColumn_file->append($menuItem_saveAll);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'save_all', $menuItem_saveAll);

            # 'Save files' submenu
            my $subMenu_saveFile = Gtk3::Menu->new();

            my $menuItem_saveFile_config = Gtk3::MenuItem->new('_Config file');
            $menuItem_saveFile_config->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('save -i' . $forceSwitch, $mode);
            });
            $subMenu_saveFile->append($menuItem_saveFile_config);

            $subMenu_saveFile->append(Gtk3::SeparatorMenuItem->new());  # Separator

            my $menuItem_saveFile_prof = Gtk3::MenuItem->new('_Profile files');
            $menuItem_saveFile_prof->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('save -d' . $forceSwitch, $mode);
            });
            $subMenu_saveFile->append($menuItem_saveFile_prof);

            my $menuItem_saveFile_currentProf = Gtk3::MenuItem->new('C_urrent profile files');
            $menuItem_saveFile_currentProf->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('save -c' . $forceSwitch, $mode);
            });
            $subMenu_saveFile->append($menuItem_saveFile_currentProf);

            my $menuItem_saveFile_worldProf = Gtk3::MenuItem->new('_World definition...');
            $menuItem_saveFile_worldProf->signal_connect('activate' => sub {

                # Display a 'dialogue' window, so the user can choose a world profile
                my (
                    $choice,
                    @worldList,
                );

                # Get an ordered list of all world profiles
                @worldList = $self->getWorldList();

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

                    if ($choice) {

                        # Save the file
                        $self->winObj->visibleSession->pseudoCmd(
                            'save -o ' . $choice . $forceSwitch,
                            $mode,
                        );
                    }
                }
            });
            $subMenu_saveFile->append($menuItem_saveFile_worldProf);

            my $menuItem_saveFile_currentWorld = Gtk3::MenuItem->new('Cu_rrent world files');
            $menuItem_saveFile_currentWorld->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('save -w' . $forceSwitch, $mode);
            });
            $subMenu_saveFile->append($menuItem_saveFile_currentWorld);

            $subMenu_saveFile->append(Gtk3::SeparatorMenuItem->new());  # Separator

            my $menuItem_saveFile_worldModel = Gtk3::MenuItem->new('World _model file');
            $menuItem_saveFile_worldModel->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('save -m' . $forceSwitch, $mode);
            });
            $subMenu_saveFile->append($menuItem_saveFile_worldModel);

            my $menuItem_saveFile_tasks = Gtk3::MenuItem->new('_Tasks file');
            $menuItem_saveFile_tasks->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('save -t' . $forceSwitch, $mode);
            });
            $subMenu_saveFile->append($menuItem_saveFile_tasks);

            my $menuItem_saveFile_scripts = Gtk3::MenuItem->new('_Scripts file');
            $menuItem_saveFile_scripts->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('save -s' . $forceSwitch, $mode);
            });
            $subMenu_saveFile->append($menuItem_saveFile_scripts);

            my $menuItem_saveFile_contacts = Gtk3::MenuItem->new('C_ontacts file');
            $menuItem_saveFile_contacts->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('save -n' . $forceSwitch, $mode);
            });
            $subMenu_saveFile->append($menuItem_saveFile_contacts);

            my $menuItem_saveFile_dicts = Gtk3::MenuItem->new('_Dictionaries file');
            $menuItem_saveFile_dicts->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('save -y' . $forceSwitch, $mode);
            });
            $subMenu_saveFile->append($menuItem_saveFile_dicts);

            my $menuItem_saveFile_toolbar = Gtk3::MenuItem->new('Tool_bar file');
            $menuItem_saveFile_toolbar->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('save -b' . $forceSwitch, $mode);
            });
            $subMenu_saveFile->append($menuItem_saveFile_toolbar);

            my $menuItem_saveFile_userComm = Gtk3::MenuItem->new('Us_er commands file');
            $menuItem_saveFile_userComm->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('save -u' . $forceSwitch, $mode);
            });
            $subMenu_saveFile->append($menuItem_saveFile_userComm);

            my $menuItem_saveFile_zonemaps = Gtk3::MenuItem->new('_Zonemaps file');
            $menuItem_saveFile_zonemaps->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('save -z' . $forceSwitch, $mode);
            });
            $subMenu_saveFile->append($menuItem_saveFile_zonemaps);

            my $menuItem_saveFile_winmaps = Gtk3::MenuItem->new('W_inmaps file');
            $menuItem_saveFile_winmaps->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('save -p' . $forceSwitch, $mode);
            });
            $subMenu_saveFile->append($menuItem_saveFile_winmaps);

            my $menuItem_saveFile_ttsObjs = Gtk3::MenuItem->new('Te_xt-to-speech file');
            $menuItem_saveFile_ttsObjs->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('save -x' . $forceSwitch, $mode);
            });
            $subMenu_saveFile->append($menuItem_saveFile_ttsObjs);

        my $menuItem_saveFile = Gtk3::MenuItem->new('S_ave files');
        $menuItem_saveFile->set_submenu($subMenu_saveFile);
        $menuColumn_file->append($menuItem_saveFile);
        # (Requires a visible session whose status is 'connected' or 'offline' and
        #   $self->saveAllSessionsFlag set to FALSE)
        $self->ivAdd('menuItemHash', 'save_file', $menuItem_saveFile);

            # 'Save options' submenu
            my $subMenu_saveOptions = Gtk3::Menu->new();

            my $menuColumn_forced_radio1 = Gtk3::RadioMenuItem->new_with_mnemonic(
                undef,
                'Forced saves o_ff',
            );
            $menuColumn_forced_radio1->signal_connect('toggled' => sub {

                if ($menuColumn_forced_radio1->get_active()) {
                    $forceSwitch = '';
                } else {
                    $forceSwitch = ' -f';
                }
            });
            $subMenu_saveOptions->append($menuColumn_forced_radio1);

            my $menuColumn_forced_radio2 = Gtk3::RadioMenuItem->new_with_mnemonic(
                $menuColumn_forced_radio1->get_group(),
                'Forced saves o_n',
            );
            $subMenu_saveOptions->append($menuColumn_forced_radio2);

            $subMenu_saveOptions->append(Gtk3::SeparatorMenuItem->new());  # Separator

            my $menuColumn_allSession_radio1 = Gtk3::RadioMenuItem->new_with_mnemonic(
                undef,
                'Save in _this session',
            );
            $menuColumn_allSession_radio1->signal_connect('toggled' => sub {

                if ($menuColumn_allSession_radio1->get_active()) {

                    $allSessionSwitch = '';
                    $self->ivPoke('saveAllSessionsFlag', FALSE);

                } else {

                    $allSessionSwitch = ' -a';
                    $self->ivPoke('saveAllSessionsFlag', TRUE);
                }

                # Sensitise/desensitise menu bar/toolbar items, depending on current conditions
                $axmud::CLIENT->desktopObj->restrictWidgets();
            });
            $subMenu_saveOptions->append($menuColumn_allSession_radio1);

            my $menuColumn_allSession_radio2 = Gtk3::RadioMenuItem->new_with_mnemonic(
                $menuColumn_allSession_radio1->get_group(),
                'Save in _all sessions',
            );
            $subMenu_saveOptions->append($menuColumn_allSession_radio2);

            $subMenu_saveOptions->append(Gtk3::SeparatorMenuItem->new());  # Separator

            my $menuItem_autoSaves_off = Gtk3::MenuItem->new('T_urn auto-saves off');
            $menuItem_autoSaves_off->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('autosave off', $mode);
            });
            $subMenu_saveOptions->append($menuItem_autoSaves_off);

            my $menuItem_autoSaves_on = Gtk3::MenuItem->new('Tu_rn auto-saves on');
            $menuItem_autoSaves_on->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('autosave on', $mode);
            });
            $subMenu_saveOptions->append($menuItem_autoSaves_on);

            $subMenu_saveOptions->append(Gtk3::SeparatorMenuItem->new());  # Separator

            my $menuItem_autoSaves_setTime = Gtk3::MenuItem->new('_Set auto-save time...');
            $menuItem_autoSaves_setTime->signal_connect('activate' => sub {

                my $number = $self->winObj->showEntryDialogue(
                    'Set auto-save time',
                    'Enter a time in seconds',
                );

                if ($number) {

                    # Set the auto-save time
                    $self->winObj->visibleSession->pseudoCmd('autosave ' . $number, $mode);
                }
            });
            $subMenu_saveOptions->append($menuItem_autoSaves_setTime);

        my $menuItem_saveOptions = Gtk3::MenuItem->new('Sa_ve options');
        $menuItem_saveOptions->set_submenu($subMenu_saveOptions);
        $menuColumn_file->append($menuItem_saveOptions);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'save_options', $menuItem_saveOptions);

        $menuColumn_file->append(Gtk3::SeparatorMenuItem->new());   # Separator

        my $menuItem_importFile = Gtk3::MenuItem->new('I_mport files...');
        $menuItem_importFile->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('importfiles', $mode);
        });
        $menuColumn_file->append($menuItem_importFile);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'import_files', $menuItem_importFile);

#        my $menuItem_exportAllFile = Gtk3::MenuItem->new('_Export all files...');
#        $menuItem_exportAllFile->signal_connect('activate' => sub {
#
#            $self->winObj->visibleSession->pseudoCmd('exportfiles', $mode);
#        });
#        $menuColumn_file->append($menuItem_exportAllFile);
#        # (Requires a visible session whose status is 'connected' or 'offline')
#        $self->ivAdd('menuItemHash', 'export_all_files', $menuItem_exportAllFile);

            # 'Export files' submenu
            my $subMenu_exportFile = Gtk3::Menu->new();

            my $menuItem_exportFile_world = Gtk3::MenuItem->new('_World files...');
            $menuItem_exportFile_world->signal_connect('activate' => sub {

                # Display a 'dialogue' window, so the user can choose a world profile
                my (
                    $choice,
                    @worldList,
                );

                # Get an ordered list of all world profiles
                @worldList = $self->getWorldList();

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

                    if ($choice) {

                        # Export the file
                        $self->winObj->visibleSession->pseudoCmd(
                            'exportfiles -w ' . $choice,
                            $mode,
                        );
                    }
                }
            });
            $subMenu_exportFile->append($menuItem_exportFile_world);

            $subMenu_exportFile->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $menuItem_exportFile_model = Gtk3::MenuItem->new('World _model file...');
            $menuItem_exportFile_model->signal_connect('activate' => sub {

                # Display a 'dialogue' window, so the user can choose a world profile
                my (
                    $choice,
                    @worldList,
                );

                # Get an ordered list of all world profiles
                @worldList = $self->getWorldList();

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

                    if ($choice) {

                        # Export the file
                        $self->winObj->visibleSession->pseudoCmd(
                            'exportfiles -m ' . $choice,
                            $mode,
                        );
                    }
                }
            });
            $subMenu_exportFile->append($menuItem_exportFile_model);

            my $menuItem_exportFile_tasks = Gtk3::MenuItem->new('_Tasks file');
            $menuItem_exportFile_tasks->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('exportfiles -t', $mode);
            });
            $subMenu_exportFile->append($menuItem_exportFile_tasks);

            my $menuItem_exportFile_scripts = Gtk3::MenuItem->new('_Scripts file');
            $menuItem_exportFile_scripts->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('exportfiles -s', $mode);
            });
            $subMenu_exportFile->append($menuItem_exportFile_scripts);

            my $menuItem_exportFile_contacts = Gtk3::MenuItem->new('_Contacts file');
            $menuItem_exportFile_contacts->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('exportfiles -n', $mode);
            });
            $subMenu_exportFile->append($menuItem_exportFile_contacts);

            my $menuItem_exportFile_dicts = Gtk3::MenuItem->new('_Dictionaries file');
            $menuItem_exportFile_dicts->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('exportfiles -y', $mode);
            });
            $subMenu_exportFile->append($menuItem_exportFile_dicts);

            my $menuItem_exportFile_toolbar = Gtk3::MenuItem->new('Tool_bar file');
            $menuItem_exportFile_toolbar->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('exportfiles -b', $mode);
            });
            $subMenu_exportFile->append($menuItem_exportFile_toolbar);

            my $menuItem_exportFile_userComm = Gtk3::MenuItem->new('_User commands file');
            $menuItem_exportFile_userComm->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('exportfiles -u', $mode);
            });
            $subMenu_exportFile->append($menuItem_exportFile_userComm);

            my $menuItem_exportFile_zonemaps = Gtk3::MenuItem->new('_Zonemaps file');
            $menuItem_exportFile_zonemaps->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('exportfiles -z', $mode);
            });
            $subMenu_exportFile->append($menuItem_exportFile_zonemaps);

            my $menuItem_exportFile_winmaps = Gtk3::MenuItem->new('W_inmaps file');
            $menuItem_exportFile_winmaps->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('exportfiles -p', $mode);
            });
            $subMenu_exportFile->append($menuItem_exportFile_winmaps);

            my $menuItem_exportFile_ttsObjs = Gtk3::MenuItem->new('Te_xt-to-speech file');
            $menuItem_exportFile_ttsObjs->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('exportfiles -x', $mode);
            });
            $subMenu_exportFile->append($menuItem_exportFile_ttsObjs);

        my $menuItem_exportFile = Gtk3::MenuItem->new('E_xport files');
        $menuItem_exportFile->set_submenu($subMenu_exportFile);
        $menuColumn_file->append($menuItem_exportFile);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'export_file', $menuItem_exportFile);

        $menuColumn_file->append(Gtk3::SeparatorMenuItem->new());   # Separator

        my $menuItem_importData = Gtk3::MenuItem->new('_Import data...');
        $menuItem_importData->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('importdata', $mode);
        });
        $menuColumn_file->append($menuItem_importData);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'import_data', $menuItem_importData);

            # 'Export data' submenu
            my $subMenu_exportData = Gtk3::Menu->new();

            my $menuItem_exportData_otherProf = Gtk3::MenuItem->new('_Non-world profiles...');
            $menuItem_exportData_otherProf->signal_connect('activate' => sub {

                # Display a 'dialogue' window, so the user can choose a non-world profile
                my (
                    $choice,
                    @otherProfList,
                );

                # Get an ordered list of all non-world profiles
                @otherProfList = $self->getOtherProfList();

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

                        \@otherProfList,
                    );

                    if ($choice) {

                        # Export the data
                        $self->winObj->visibleSession->pseudoCmd('exportdata -d ' . $choice, $mode);
                    }
                }
            });
            $subMenu_exportData->append($menuItem_exportData_otherProf);

            my $menuItem_exportData_singleCage = Gtk3::MenuItem->new('_Single cage...');
            $menuItem_exportData_singleCage->signal_connect('activate' => sub {

                # Display a 'dialogue' window, so the user can choose a cage
                my (
                    $choice,
                    @cageList,
                );

                # Get an ordered list of cages
                @cageList

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

                        \@cageList,
                    );

                    if ($choice) {

                        # Export the data
                        $self->winObj->visibleSession->pseudoCmd('exportdata -t ' . $choice, $mode);
                    }
                }
            });
            $subMenu_exportData->append($menuItem_exportData_singleCage);

            my $menuItem_exportData_profCages = Gtk3::MenuItem->new('_All cages in profile...');
            $menuItem_exportData_profCages->signal_connect('activate' => sub {

                # Display a 'dialogue' window, so the user can choose a profile
                my (
                    $choice,
                    @profList,
                );

                # Get an ordered list of profiles
                @profList

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

                        \@profList,
                    );

                    if ($choice) {

                        # Export the data
                        $self->winObj->visibleSession->pseudoCmd('exportdata -p ' . $choice, $mode);
                    }
                }
            });
            $subMenu_exportData->append($menuItem_exportData_profCages);

            my $menuItem_exportData_template = Gtk3::MenuItem->new('_Profile template...');
            $menuItem_exportData_template->signal_connect('activate' => sub {

                # Display a 'dialogue' window, so the user can choose a profile template
                my (
                    $choice,
                    @templList,
                );

                # Get an ordered list of all templates
                @templList = sort {lc($a) cmp lc($b)}

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

                        \@templList,
                    );

                    if ($choice) {

                        # Export the data
                        $self->winObj->visibleSession->pseudoCmd('exportdata -s ' . $choice, $mode);
                    }
                }
            });
            $subMenu_exportData->append($menuItem_exportData_template);

            $subMenu_exportData->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $menuItem_exportData_initialTask = Gtk3::MenuItem->new('(_Global) initial task...');
            $menuItem_exportData_initialTask->signal_connect('activate' => sub {

                # Display a 'dialogue' window, so the user can choose a (global) initial task
                my (
                    $choice,
                    @taskList,
                );

                # Get an ordered list of all (global) initial tasks
                @taskList = sort {lc($a) cmp lc($b)} ($axmud::CLIENT->ivKeys('initTaskHash'));

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

                        \@taskList,
                    );

                    if ($choice) {

                        # Export the data
                        $self->winObj->visibleSession->pseudoCmd('exportdata -i ' . $choice, $mode);
                    }
                }
            });
            $subMenu_exportData->append($menuItem_exportData_initialTask);

            my $menuItem_exportData_customTask = Gtk3::MenuItem->new('_Custom task...');
            $menuItem_exportData_customTask->signal_connect('activate' => sub {

                # Display a 'dialogue' window, so the user can choose a custom task
                my (
                    $choice,
                    @taskList,
                );

                # Get an ordered list of all custom task names
                @taskList = sort {lc($a) cmp lc($b)} ($axmud::CLIENT->ivKeys('customTaskHash'));

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

                        \@taskList,
                    );

                    if ($choice) {

                        # Export the data
                        $self->winObj->visibleSession->pseudoCmd('exportdata -c ' . $choice, $mode);
                    }
                }
            });
            $subMenu_exportData->append($menuItem_exportData_customTask);

            $subMenu_exportData->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $menuItem_exportData_dict = Gtk3::MenuItem->new('_Dictionary...');
            $menuItem_exportData_dict->signal_connect('activate' => sub {

                # Display a 'dialogue' window, so the user can choose a dictionary
                my (
                    $choice,
                    @dictList,
                );

                # Get an ordered list of all dictionaries, with the current dictionary at the top of
                #   the list

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

                        \@dictList,
                    );

                    if ($choice) {

                        # Export the data
                        $self->winObj->visibleSession->pseudoCmd('exportdata -y ' . $choice, $mode);
                    }
                }
            });
            $subMenu_exportData->append($menuItem_exportData_dict);

            my $menuItem_exportData_zonemap = Gtk3::MenuItem->new('_Zonemap...');
            $menuItem_exportData_zonemap->signal_connect('activate' => sub {

                # Display a 'dialogue' window, so the user can choose a zonemap
                my (
                    $choice,
                    @zonemapList,
                );

                @zonemapList = (sort {lc($a) cmp lc($b)} ($axmud::CLIENT->ivKeys('zonemapHash')));
                if (@zonemapList) {

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

                        \@zonemapList,
                    );

                    if ($choice) {

                        # Export the data
                        $self->winObj->visibleSession->pseudoCmd('exportdata -z ' . $choice, $mode);
                    }
                }
            });
            $subMenu_exportData->append($menuItem_exportData_zonemap);

            my $menuItem_exportData_winmap = Gtk3::MenuItem->new('_Winmap...');
            $menuItem_exportData_winmap->signal_connect('activate' => sub {

                # Display a 'dialogue' window, so the user can choose a winmap
                my (
                    $choice,
                    @winmapList,
                );

                @winmapList = (sort {lc($a) cmp lc($b)} ($axmud::CLIENT->ivKeys('winmapHash')));
                if (@winmapList) {

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

                        \@winmapList,
                    );

                    if ($choice) {

                        # Export the data
                        $self->winObj->visibleSession->pseudoCmd('exportdata -p ' . $choice, $mode);
                    }
                }
            });
            $subMenu_exportData->append($menuItem_exportData_winmap);

            my $menuItem_exportData_colScheme = Gtk3::MenuItem->new('C_olour scheme...');
            $menuItem_exportData_colScheme->signal_connect('activate' => sub {

                # Display a 'dialogue' window, so the user can choose a colour scheme
                my (
                    $choice,
                    @schemeList,
                );

                @schemeList = (
                    sort {lc($a) cmp lc($b)} ($axmud::CLIENT->ivKeys('colourSchemeHash'))

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

                        \@schemeList,
                    );

                    if ($choice) {

                        # Export the data
                        $self->winObj->visibleSession->pseudoCmd('exportdata -o ' . $choice, $mode);
                    }
                }
            });
            $subMenu_exportData->append($menuItem_exportData_colScheme);

            my $menuItem_exportData_ttsObj = Gtk3::MenuItem->new('_TTS object...');
            $menuItem_exportData_ttsObj->signal_connect('activate' => sub {

                # Display a 'dialogue' window, so the user can choose a TTS object
                my (
                    $choice,
                    @objList,
                );

                @objList = (sort {lc($a) cmp lc($b)} ($axmud::CLIENT->ivKeys('ttsObjHash')));
                if (@objList) {

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

                        \@objList,
                    );

                    if ($choice) {

                        # Export the data
                        $self->winObj->visibleSession->pseudoCmd('exportdata -x ' . $choice, $mode);
                    }
                }
            });
            $subMenu_exportData->append($menuItem_exportData_ttsObj);

        my $menuItem_exportData = Gtk3::MenuItem->new('Export _data');
        $menuItem_exportData->set_submenu($subMenu_exportData);
        $menuColumn_file->append($menuItem_exportData);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'export_data', $menuItem_exportData);

        $menuColumn_file->append(Gtk3::SeparatorMenuItem->new());   # Separator

            # 'Backup data' submenu
            my $subMenu_backupRestore = Gtk3::Menu->new();

            my $menuItem_backupData = Gtk3::MenuItem->new('_Backup all data files');
            $menuItem_backupData->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('backupdata', $mode);
            });
            $subMenu_backupRestore->append($menuItem_backupData);

            my $menuItem_restoreData = Gtk3::MenuItem->new('_Restore from backup...');
            $menuItem_restoreData->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('restoredata', $mode);
            });
            $subMenu_backupRestore->append($menuItem_restoreData);

        my $menuItem_backupRestore = Gtk3::MenuItem->new('_Backup data');
        $menuItem_backupRestore->set_submenu($subMenu_backupRestore);
        $menuColumn_file->append($menuItem_backupRestore);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'backup_restore_data', $menuItem_backupRestore);

        $menuColumn_file->append(Gtk3::SeparatorMenuItem->new());   # Separator

        my $menuItem_showFiles = Gtk3::ImageMenuItem->new('S_how file objects');
        my $menuImg_showFiles = Gtk3::Image->new_from_stock('gtk-dialog-info', 'menu');
        $menuItem_showFiles->set_image($menuImg_showFiles);
        $menuItem_showFiles->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('showfile', $mode);
        });
        $menuColumn_file->append($menuItem_showFiles);
        # (Requires a visible session)
        $self->ivAdd('menuItemHash', 'show_files', $menuItem_showFiles);

        my $menuItem_disableSaveWorld = Gtk3::ImageMenuItem->new('Disable _world save');
        my $menuImg_disableSaveWorld = Gtk3::Image->new_from_stock('gtk-dialog-warning', 'menu');
        $menuItem_disableSaveWorld->set_image($menuImg_disableSaveWorld);
        $menuItem_disableSaveWorld->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('disablesaveworld', $mode);
        });
        $menuColumn_file->append($menuItem_disableSaveWorld);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'disable_world_save', $menuItem_disableSaveWorld);

        my $menuItem_disableSaveLoad = Gtk3::ImageMenuItem->new('Disabl_e all saves/loads');
        my $menuImg_disableSaveLoad = Gtk3::Image->new_from_stock('gtk-dialog-warning', 'menu');
        $menuItem_disableSaveLoad->set_image($menuImg_disableSaveLoad);
        $menuItem_disableSaveLoad->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('disablesaveload', $mode);
        });
        $menuColumn_file->append($menuItem_disableSaveLoad);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'disable_save_load', $menuItem_disableSaveLoad);

        # Setup complete
        return $menuColumn_file;
    }

    sub drawEditColumn {

        # Called by $self->enableMenu
        # Sets up the menu's 'Edit' column
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments, or if the menu can't be created
        #   Otherwise returns the Gtk3::Menu created

        my ($self, $check) = @_;

        # Local variables
        my $mode;

        # Check for improper arguments
        if (defined $check) {

             return $axmud::CLIENT->writeImproper($self->_objClass . '->drawEditColumn', @_);
        }

        # Import IVs (for convenience)
        $mode = $self->winObj->pseudoCmdMode;

        # Set up column
        my $menuColumn_edit = Gtk3::Menu->new();
        if (! $menuColumn_edit) {

            return undef;
        }

        my $menuItem_quickPrefs = Gtk3::ImageMenuItem->new(
            '_Quick preferences...',
        );
        my $menuImg_quickPrefs = Gtk3::Image->new_from_stock('gtk-preferences', 'menu');
        $menuItem_quickPrefs->set_image($menuImg_quickPrefs);
        $menuItem_quickPrefs->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('editquick', $mode);
        });
        $menuColumn_edit->append($menuItem_quickPrefs);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'edit_quick_prefs', $menuItem_quickPrefs);

        my $menuItem_clientPrefs = Gtk3::ImageMenuItem->new(
            $axmud::SCRIPT . ' _preferences...',
        );
        my $menuImg_clientPrefs = Gtk3::Image->new_from_stock('gtk-preferences', 'menu');
        $menuItem_clientPrefs->set_image($menuImg_clientPrefs);
        $menuItem_clientPrefs->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('editclient', $mode);
        });
        $menuColumn_edit->append($menuItem_clientPrefs);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'edit_client_prefs', $menuItem_clientPrefs);

        my $menuItem_sessionPrefs = Gtk3::ImageMenuItem->new('_Session preferences...');
        my $menuImg_sessionPrefs = Gtk3::Image->new_from_stock('gtk-preferences', 'menu');
        $menuItem_sessionPrefs->set_image($menuImg_sessionPrefs);
        $menuItem_sessionPrefs->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('editsession', $mode);
        });
        $menuColumn_edit->append($menuItem_sessionPrefs);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'edit_session_prefs', $menuItem_sessionPrefs);

        $menuColumn_edit->append(Gtk3::SeparatorMenuItem->new());   # Separator

        my $menuItem_editWorld = Gtk3::ImageMenuItem->new('Edit current _world...');
        my $menuImg_editWorld = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
        $menuItem_editWorld->set_image($menuImg_editWorld);
        $menuItem_editWorld->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('editworld', $mode);
        });
        $menuColumn_edit->append($menuItem_editWorld);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'edit_current_world', $menuItem_editWorld);

        my $menuItem_editGuild = Gtk3::ImageMenuItem->new('Edit current _guild...');
        my $menuImg_editGuild = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
        $menuItem_editGuild->set_image($menuImg_editGuild);
        $menuItem_editGuild->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('editguild', $mode);
        });
        $menuColumn_edit->append($menuItem_editGuild);
        # Requires a current session whose status is 'connected' or 'offline' and whose
        #   ->currentGuild is defined
        $self->ivAdd('menuItemHash', 'edit_current_guild', $menuItem_editGuild);

        my $menuItem_editRace = Gtk3::ImageMenuItem->new('Edit current _race...');
        my $menuImg_editRace = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
        $menuItem_editRace->set_image($menuImg_editRace);
        $menuItem_editRace->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('editrace', $mode);
        });
        $menuColumn_edit->append($menuItem_editRace);
        # Requires a current session whose status is 'connected' or 'offline' and whose
        #   ->currentRace is defined
        $self->ivAdd('menuItemHash', 'edit_current_race', $menuItem_editRace);

        my $menuItem_editChar = Gtk3::ImageMenuItem->new('Edit current _character...');
        my $menuImg_editChar = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
        $menuItem_editChar->set_image($menuImg_editChar);
        $menuItem_editChar->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('editchar', $mode);
        });
        $menuColumn_edit->append($menuItem_editChar);
        # Requires a current session whose status is 'connected' or 'offline' and whose
        #   ->currentChar is defined
        $self->ivAdd('menuItemHash', 'edit_current_char', $menuItem_editChar);

        $menuColumn_edit->append(Gtk3::SeparatorMenuItem->new());   # Separator

        my $menuItem_locatorWiz = Gtk3::ImageMenuItem->new('Run Locator w_izard...');
        my $menuImg_locatorWiz = Gtk3::Image->new_from_stock('gtk-page-setup', 'menu');
        $menuItem_locatorWiz->set_image($menuImg_locatorWiz);
        $menuItem_locatorWiz->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('locatorwizard', $mode);
        });
        $menuColumn_edit->append($menuItem_locatorWiz);
        # (Requires a visible session whose status is 'connected' or 'offline'. A
        #   corresponding menu item also appears in $self->drawTasksColumn)
        $self->ivAdd('menuItemHash', 'run_locator_wiz', $menuItem_locatorWiz);

        my $menuItem_editWorldModel = Gtk3::ImageMenuItem->new('Edit world _model...');
        my $menuImg_editWorldModel = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
        $menuItem_editWorldModel->set_image($menuImg_editWorldModel);
        $menuItem_editWorldModel->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('editmodel', $mode);
        });
        $menuColumn_edit->append($menuItem_editWorldModel);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'edit_world_model', $menuItem_editWorldModel);

        my $menuItem_editDict = Gtk3::ImageMenuItem->new('Edit _dictionary...');
        my $menuImg_editDict = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
        $menuItem_editDict->set_image($menuImg_editDict);
        $menuItem_editDict->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('editdictionary', $mode);
        });
        $menuColumn_edit->append($menuItem_editDict);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'edit_dictionary', $menuItem_editDict);

        $menuColumn_edit->append(Gtk3::SeparatorMenuItem->new());   # Separator

            # 'Simulate' submenu
            my $subMenu_simulate = Gtk3::Menu->new();

            my $menuItem_simWorld = Gtk3::MenuItem->new('Simulate _world...');
            $menuItem_simWorld->signal_connect('activate' => sub {

                # Open a simulate world 'dialogue' window. The text entered is used in a
                #   ';simulateworld' command
                $self->winObj->visibleSession->pseudoCmd('simulateworld', $mode);
            });
            $subMenu_simulate->append($menuItem_simWorld);

            my $menuItem_simPrompt = Gtk3::MenuItem->new('Simulate _prompt...');
            $menuItem_simPrompt->signal_connect('activate' => sub {

                # Open a simulate prompt 'dialogue' window. The text entered is used in a
                #   ';simulateprompt' command
                $self->winObj->visibleSession->pseudoCmd('simulateprompt', $mode);
            });
            $subMenu_simulate->append($menuItem_simPrompt);

            my $menuItem_simCmd = Gtk3::MenuItem->new('Simulate _command...');
            $menuItem_simCmd->signal_connect('activate' => sub {

                # Prompt the user for a world command
                my $cmd = $self->winObj->showEntryDialogue(
                    'Simulate world command',
                    'Enter a world command (not actually sent to the world)',
                );

                if ($cmd) {

                    $self->winObj->visibleSession->pseudoCmd(
                        'simulatecommand <' . $cmd . '>',
                        $mode,
                    );
                }
            });
            $subMenu_simulate->append($menuItem_simCmd);

            my $menuItem_simHook = Gtk3::MenuItem->new('Simulate _hook event...');
            $menuItem_simHook->signal_connect('activate' => sub {

                my (
                    $interfaceModel, $choice, $number, $cancelFlag, $cmd,
                    @eventList, @hookDataList,
                );

                # Get the hook interface model, and from there, a list of hook events
                $interfaceModel = $axmud::CLIENT->ivShow('interfaceModelHash', 'hook');
                @eventList = sort {$a cmp $b} ($interfaceModel->ivKeys('hookEventHash'));

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

                        foreach my $item (@hookDataList) {

                            $cmd .= ' <' . $item . '>';
                        }

                        # ...and execute it
                        $self->winObj->visibleSession->pseudoCmd($cmd, $mode);
                    }
                }
            });
            $subMenu_simulate->append($menuItem_simHook);

        my $menuItem_simulate = Gtk3::MenuItem->new('Sim_ulate');
        $menuItem_simulate->set_submenu($subMenu_simulate);
        $menuColumn_edit->append($menuItem_simulate);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'simulate', $menuItem_simulate);

        my $menuItem_patternTest = Gtk3::MenuItem->new('_Test patterns...');
        $menuItem_patternTest->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('testpattern', $mode);
        });
        $menuColumn_edit->append($menuItem_patternTest);
        # (Desensitised only when the setup wizwin is open)
        $self->ivAdd('menuItemHash', 'test_pattern', $menuItem_patternTest);

        # Setup complete
        return $menuColumn_edit;
    }

    sub drawInterfacesColumn {

        # Called by $self->enableMenu
        # Sets up the menu's 'Interfaces' column
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments, or if the menu can't be created
        #   Otherwise returns the Gtk3::Menu created

        my ($self, $check) = @_;

        # Local variables
        my $mode;

        # Check for improper arguments
        if (defined $check) {

             return $axmud::CLIENT->writeImproper($self->_objClass . '->drawInterfacesColumn', @_);
        }

        # Import IVs (for convenience)
        $mode = $self->winObj->pseudoCmdMode;

        # Set up column
        my $menuColumn_interfaces = Gtk3::Menu->new();
        if (! $menuColumn_interfaces) {

            return undef;
        }

        my $menuItem_activeInterfaces = Gtk3::MenuItem->new('Acti_ve interfaces...');
        $menuItem_activeInterfaces->signal_connect('activate' => sub {

            # Open a session preference window on the notebook's second page, so the user can see
            #   the list of active interfaces immediately
            $self->winObj->visibleSession->pseudoCmd('editactiveinterface', $mode);
        });
        $menuColumn_interfaces->append($menuItem_activeInterfaces);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'active_interfaces', $menuItem_activeInterfaces);

        $menuColumn_interfaces->append(Gtk3::SeparatorMenuItem->new());   # Separator

            # 'Triggers' submenu
            my $subMenu_showTriggers = Gtk3::Menu->new();

            my $menuItem_worldTriggers = Gtk3::MenuItem->new('_World triggers...');
            $menuItem_worldTriggers->signal_connect('activate' => sub {

                # Open the cage window on the notebook's second page, so the user can see the list
                #   of triggers immediately
                $self->winObj->visibleSession->pseudoCmd('editcage -t', $mode);
            });
            $subMenu_showTriggers->append($menuItem_worldTriggers);

            my $menuItem_guildTriggers = Gtk3::MenuItem->new('_Guild triggers...');
            $menuItem_guildTriggers->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd(
                    'editcage trigger_guild_' . $self->winObj->visibleSession->currentGuild->name,
                    $mode,
                );
            });
            $subMenu_showTriggers->append($menuItem_guildTriggers);
            # (Requires a visible session whose status is 'connected' or 'offline', and a current
            #   guild)
            $self->ivAdd('menuItemHash', 'guild_triggers', $menuItem_guildTriggers);

            my $menuItem_raceTriggers = Gtk3::MenuItem->new('_Race triggers...');
            $menuItem_raceTriggers->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd(
                    'editcage trigger_race_' . $self->winObj->visibleSession->currentRace->name,
                    $mode,
                );
            });
            $subMenu_showTriggers->append($menuItem_raceTriggers);
            # (Requires a visible session whose status is 'connected' or 'offline', and a current
            #   race)
            $self->ivAdd('menuItemHash', 'race_triggers', $menuItem_raceTriggers);

            my $menuItem_charTriggers = Gtk3::MenuItem->new('_Character triggers...');
            $menuItem_charTriggers->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd(
                    'editcage trigger_char_' . $self->winObj->visibleSession->currentChar->name,
                    $mode,
                );
            });
            $subMenu_showTriggers->append($menuItem_charTriggers);
            # (Requires a visible session whose status is 'connected' or 'offline', and a current
            #   character)
            $self->ivAdd('menuItemHash', 'char_triggers', $menuItem_charTriggers);

        my $menuItem_showTriggers = Gtk3::MenuItem->new('_Triggers');
        $menuItem_showTriggers->set_submenu($subMenu_showTriggers);
        $menuColumn_interfaces->append($menuItem_showTriggers);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'show_triggers', $menuItem_showTriggers);

            # 'Aliases' submenu
            my $subMenu_showAliases = Gtk3::Menu->new();

            my $menuItem_worldAliases = Gtk3::MenuItem->new('World _aliases...');
            $menuItem_worldAliases->signal_connect('activate' => sub {

                # Open the cage window on the notebook's second page, so the user can see the list
                #   of aliases immediately
                $self->winObj->visibleSession->pseudoCmd('editcage -a', $mode);
            });
            $subMenu_showAliases->append($menuItem_worldAliases);

            my $menuItem_guildAliases = Gtk3::MenuItem->new('_Guild aliases...');
            $menuItem_guildAliases->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd(
                    'editcage alias_guild_' . $self->winObj->visibleSession->currentGuild->name,
                    $mode,
                );
            });
            $subMenu_showAliases->append($menuItem_guildAliases);
            # (Requires a visible session whose status is 'connected' or 'offline', and a current
            #   guild)
            $self->ivAdd('menuItemHash', 'guild_aliases', $menuItem_guildAliases);

            my $menuItem_raceAliases = Gtk3::MenuItem->new('_Race aliases...');
            $menuItem_raceAliases->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd(
                    'editcage alias_race_' . $self->winObj->visibleSession->currentRace->name,
                    $mode,
                );
            });
            $subMenu_showAliases->append($menuItem_raceAliases);
            # (Requires a visible session whose status is 'connected' or 'offline', and a current
            #   race)
            $self->ivAdd('menuItemHash', 'race_aliases', $menuItem_raceAliases);

            my $menuItem_charAliases = Gtk3::MenuItem->new('_Character aliases...');
            $menuItem_charAliases->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd(
                    'editcage alias_char_' . $self->winObj->visibleSession->currentChar->name,
                    $mode,
                );
            });
            $subMenu_showAliases->append($menuItem_charAliases);
            # (Requires a visible session whose status is 'connected' or 'offline', and a current
            #   character)
            $self->ivAdd('menuItemHash', 'char_aliases', $menuItem_charAliases);

        my $menuItem_showAliases = Gtk3::MenuItem->new('_Aliases');
        $menuItem_showAliases->set_submenu($subMenu_showAliases);
        $menuColumn_interfaces->append($menuItem_showAliases);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'show_aliases', $menuItem_showAliases);

            # 'Macros' submenu
            my $subMenu_showMacros = Gtk3::Menu->new();

            my $menuItem_worldMacros = Gtk3::MenuItem->new('_World macros...');
            $menuItem_worldMacros->signal_connect('activate' => sub {

                # Open the cage window on the notebook's second page, so the user can see the list
                #   of macros immediately
                $self->winObj->visibleSession->pseudoCmd('editcage -m', $mode);
            });
            $subMenu_showMacros->append($menuItem_worldMacros);

            my $menuItem_guildMacros = Gtk3::MenuItem->new('_Guild macros...');
            $menuItem_guildMacros->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd(
                    'editcage macro_guild_' . $self->winObj->visibleSession->currentGuild->name,
                    $mode,
                );
            });
            $subMenu_showMacros->append($menuItem_guildMacros);
            # (Requires a visible session whose status is 'connected' or 'offline', and a current
            #   guild)
            $self->ivAdd('menuItemHash', 'guild_macros', $menuItem_guildMacros);

            my $menuItem_raceMacros = Gtk3::MenuItem->new('_Race macros...');
            $menuItem_raceMacros->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd(
                    'editcage macro_race_' . $self->winObj->visibleSession->currentRace->name,
                    $mode,
                );
            });
            $subMenu_showMacros->append($menuItem_raceMacros);
            # (Requires a visible session whose status is 'connected' or 'offline', and a current
            #   race)
            $self->ivAdd('menuItemHash', 'race_macros', $menuItem_raceMacros);

            my $menuItem_charMacros = Gtk3::MenuItem->new('_Character macros...');
            $menuItem_charMacros->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd(
                    'editcage macro_char_' . $self->winObj->visibleSession->currentChar->name,
                    $mode,
                );
            });
            $subMenu_showMacros->append($menuItem_charMacros);
            # (Requires a visible session whose status is 'connected' or 'offline', and a current
            #   character)
            $self->ivAdd('menuItemHash', 'char_macros', $menuItem_charMacros);

        my $menuItem_showMacros = Gtk3::MenuItem->new('_Macros');
        $menuItem_showMacros->set_submenu($subMenu_showMacros);
        $menuColumn_interfaces->append($menuItem_showMacros);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'show_macros', $menuItem_showMacros);

            # 'Timers' submenu
            my $subMenu_showTimers = Gtk3::Menu->new();

            my $menuItem_worldTimers = Gtk3::MenuItem->new('_World timers...');
            $menuItem_worldTimers->signal_connect('activate' => sub {

                # Open the cage window on the notebook's second page, so the user can see the list
                #   of timers immediately
                $self->winObj->visibleSession->pseudoCmd('editcage -i', $mode);
            });
            $subMenu_showTimers->append($menuItem_worldTimers);

            my $menuItem_guildTimers = Gtk3::MenuItem->new('_Guild timers...');
            $menuItem_guildTimers->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd(
                    'editcage timer_guild_' . $self->winObj->visibleSession->currentGuild->name,
                    $mode,
                );
            });
            $subMenu_showTimers->append($menuItem_guildTimers);
            # (Requires a visible session whose status is 'connected' or 'offline', and a current
            #   guild)
            $self->ivAdd('menuItemHash', 'guild_timers', $menuItem_guildTimers);

            my $menuItem_raceTimers = Gtk3::MenuItem->new('_Race timers...');
            $menuItem_raceTimers->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd(
                    'editcage timer_race_' . $self->winObj->visibleSession->currentRace->name,
                    $mode,
                );
            });
            $subMenu_showTimers->append($menuItem_raceTimers);
            # (Requires a visible session whose status is 'connected' or 'offline', and a current
            #   race)
            $self->ivAdd('menuItemHash', 'race_timers', $menuItem_raceTimers);

            my $menuItem_charTimers = Gtk3::MenuItem->new('_Character timers...');
            $menuItem_charTimers->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd(
                    'editcage timer_char_' . $self->winObj->visibleSession->currentChar->name,
                    $mode,
                );
            });
            $subMenu_showTimers->append($menuItem_charTimers);
            # (Requires a visible session whose status is 'connected' or 'offline', and a current
            #   character)
            $self->ivAdd('menuItemHash', 'char_timers', $menuItem_charTimers);

        my $menuItem_showTimers = Gtk3::MenuItem->new('T_imers');
        $menuItem_showTimers->set_submenu($subMenu_showTimers);
        $menuColumn_interfaces->append($menuItem_showTimers);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'show_timers', $menuItem_showTimers);

            # 'Hooks' submenu
            my $subMenu_showHooks = Gtk3::Menu->new();

            my $menuItem_worldHooks = Gtk3::MenuItem->new('_World hooks...');
            $menuItem_worldHooks->signal_connect('activate' => sub {

                # Open the cage window on the notebook's second page, so the user can see the list
                #   of hooks immediately
                $self->winObj->visibleSession->pseudoCmd('editcage -h', $mode);
            });
            $subMenu_showHooks->append($menuItem_worldHooks);

            my $menuItem_guildHooks = Gtk3::MenuItem->new('_Guild hooks...');
            $menuItem_guildHooks->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd(
                    'editcage hook_guild_' . $self->winObj->visibleSession->currentGuild->name,
                    $mode,
                );
            });
            $subMenu_showHooks->append($menuItem_guildHooks);
            # (Requires a visible session whose status is 'connected' or 'offline', and a current
            #   guild)
            $self->ivAdd('menuItemHash', 'guild_hooks', $menuItem_guildHooks);

            my $menuItem_raceHooks = Gtk3::MenuItem->new('_Race hooks...');
            $menuItem_raceHooks->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd(
                    'editcage hook_race_' . $self->winObj->visibleSession->currentRace->name,
                    $mode,
                );
            });
            $subMenu_showHooks->append($menuItem_raceHooks);
            # (Requires a visible session whose status is 'connected' or 'offline', and a current
            #   race)
            $self->ivAdd('menuItemHash', 'race_hooks', $menuItem_raceHooks);

            my $menuItem_charHooks = Gtk3::MenuItem->new('_Character hooks...');
            $menuItem_charHooks->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd(
                    'editcage hook_char_' . $self->winObj->visibleSession->currentChar->name,
                    $mode,
                );
            });
            $subMenu_showHooks->append($menuItem_charHooks);
            # (Requires a visible session whose status is 'connected' or 'offline', and a current
            #   character)
            $self->ivAdd('menuItemHash', 'char_hooks', $menuItem_charHooks);

        my $menuItem_showHooks = Gtk3::MenuItem->new('_Hooks');
        $menuItem_showHooks->set_submenu($subMenu_showHooks);
        $menuColumn_interfaces->append($menuItem_showHooks);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'show_hooks', $menuItem_showHooks);

        $menuColumn_interfaces->append(Gtk3::SeparatorMenuItem->new());   # Separator

            # 'Commands' submenu
            my $subMenu_showCmds = Gtk3::Menu->new();

            my $menuItem_worldCmds = Gtk3::MenuItem->new('_World commands...');
            $menuItem_worldCmds->signal_connect('activate' => sub {

                # Open the cage window on the notebook's second page, so the user can see the list
                #   OF commands immediately
                $self->winObj->visibleSession->pseudoCmd('editcage -c', $mode);
            });
            $subMenu_showCmds->append($menuItem_worldCmds);

            my $menuItem_guildCmds = Gtk3::MenuItem->new('_Guild commands...');
            $menuItem_guildCmds->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd(
                    'editcage cmd_guild_' . $self->winObj->visibleSession->currentGuild->name,
                    $mode,
                );
            });
            $subMenu_showCmds->append($menuItem_guildCmds);
            # (Requires a visible session whose status is 'connected' or 'offline', and a current
            #   guild)
            $self->ivAdd('menuItemHash', 'guild_cmds', $menuItem_guildCmds);

            my $menuItem_raceCmds = Gtk3::MenuItem->new('_Race commands...');
            $menuItem_raceCmds->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd(
                    'editcage cmd_race_' . $self->winObj->visibleSession->currentRace->name,
                    $mode,
                );
            });
            $subMenu_showCmds->append($menuItem_raceCmds);
            # (Requires a visible session whose status is 'connected' or 'offline', and a current
            #   race)
            $self->ivAdd('menuItemHash', 'race_cmds', $menuItem_raceCmds);

            my $menuItem_charCmds = Gtk3::MenuItem->new('_Character commands...');
            $menuItem_charCmds->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd(
                    'editcage cmd_char_' . $self->winObj->visibleSession->currentChar->name,
                    $mode,
                );
            });
            $subMenu_showCmds->append($menuItem_charCmds);
            # (Requires a visible session whose status is 'connected' or 'offline', and a current
            #   character)
            $self->ivAdd('menuItemHash', 'char_cmds', $menuItem_charCmds);

        my $menuItem_showCmds = Gtk3::MenuItem->new('_Commands');
        $menuItem_showCmds->set_submenu($subMenu_showCmds);
        $menuColumn_interfaces->append($menuItem_showCmds);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'show_cmds', $menuItem_showCmds);

            # 'Routes' submenu
            my $subMenu_showRoutes = Gtk3::Menu->new();

            my $menuItem_worldRoutes = Gtk3::MenuItem->new('_World routes...');
            $menuItem_worldRoutes->signal_connect('activate' => sub {

                # Open the cage window on the notebook's second page, so the user can see the list
                #   OF routes immediately
                $self->winObj->visibleSession->pseudoCmd('editcage -r', $mode);
            });
            $subMenu_showRoutes->append($menuItem_worldRoutes);

            my $menuItem_guildRoutes = Gtk3::MenuItem->new('_Guild routes...');
            $menuItem_guildRoutes->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd(
                    'editcage route_guild_' . $self->winObj->visibleSession->currentGuild->name,
                    $mode,
                );
            });
            $subMenu_showRoutes->append($menuItem_guildRoutes);
            # (Requires a visible session whose status is 'connected' or 'offline', and a current
            #   guild)
            $self->ivAdd('menuItemHash', 'guild_routes', $menuItem_guildRoutes);

            my $menuItem_raceRoutes = Gtk3::MenuItem->new('_Race routes...');
            $menuItem_raceRoutes->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd(
                    'editcage route_race_' . $self->winObj->visibleSession->currentRace->name,
                    $mode,
                );
            });
            $subMenu_showRoutes->append($menuItem_raceRoutes);
            # (Requires a visible session whose status is 'connected' or 'offline', and a current
            #   race)
            $self->ivAdd('menuItemHash', 'race_routes', $menuItem_raceRoutes);

            my $menuItem_charRoutes = Gtk3::MenuItem->new('_Character routes...');
            $menuItem_charRoutes->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd(
                    'editcage route_char_' . $self->winObj->visibleSession->currentChar->name,
                    $mode,
                );
            });
            $subMenu_showRoutes->append($menuItem_charRoutes);
            # (Requires a visible session whose status is 'connected' or 'offline', and a current
            #   character)
            $self->ivAdd('menuItemHash', 'char_routes', $menuItem_charRoutes);

        my $menuItem_showRoutes = Gtk3::MenuItem->new('_Routes');
        $menuItem_showRoutes->set_submenu($subMenu_showRoutes);
        $menuColumn_interfaces->append($menuItem_showRoutes);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'show_routes', $menuItem_showRoutes);

        # Setup complete
        return $menuColumn_interfaces;
    }

    sub drawTasksColumn {

        # Called by $self->enableMenu
        # Sets up the menu's 'Tasks' column
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments, or if the menu can't be created
        #   Otherwise returns the Gtk3::Menu created

        my ($self, $check) = @_;

        # Local variables
        my $mode;

        # Check for improper arguments
        if (defined $check) {

             return $axmud::CLIENT->writeImproper($self->_objClass . '->drawTasksColumn', @_);
        }

        # Import IVs (for convenience)
        $mode = $self->winObj->pseudoCmdMode;

        # Set up column
        my $menuColumn_tasks = Gtk3::Menu->new();
        if (! $menuColumn_tasks) {

            return undef;
        }

        my $menuItem_freezeTasks = Gtk3::CheckMenuItem->new('_Freeze all tasks');
        $menuItem_freezeTasks->signal_connect('toggled' => sub {

            $self->winObj->visibleSession->pseudoCmd('freezetask', $mode);
        });
        $menuColumn_tasks->append($menuItem_freezeTasks);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'freeze_tasks', $menuItem_freezeTasks);

            # 'Start new task' submenu
            my $subMenu_startNewTask = Gtk3::Menu->new();

            my @taskList = (
                'channels', 'chat', 'compass', 'condition', 'divert', 'inventory', 'locator',
                'status', 'watch',
            );

            my @mnemonicList = (
                '_Channels task', 'C_hat task', 'C_ompass task', 'Con_dition task', '_Divert task',
                '_Inventory task', '_Locator task', '_Status task', '_Watch task',
            );

            foreach my $task (@taskList) {

                my $menuItem_startNewTask_task = Gtk3::MenuItem->new(shift @mnemonicList);
                $menuItem_startNewTask_task->signal_connect('activate' => sub {

                    $self->winObj->visibleSession->pseudoCmd(
                        'starttask ' . $task,
                        $mode,
                    );
                });
                $subMenu_startNewTask->append($menuItem_startNewTask_task);
                # (Requires a visible session whose status is 'connected' or 'offline'; in addition,
                #   some of these tasks must be unique)
                $self->ivAdd('menuItemHash', $task . '_task_start', $menuItem_startNewTask_task);
            }

        my $menuItem_startNewTask = Gtk3::MenuItem->new('Start _new task');
        $menuItem_startNewTask->set_submenu($subMenu_startNewTask);
        $menuColumn_tasks->append($menuItem_startNewTask);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'start_new_task', $menuItem_startNewTask);

        $menuColumn_tasks->append(Gtk3::SeparatorMenuItem->new());  # Separator

            # 'Channels task' submenu
            my $subMenu_channelsTask = Gtk3::Menu->new();

            my $menuItem_channelsTask_addPattern = Gtk3::MenuItem->new('Add _channel pattern...');
            $menuItem_channelsTask_addPattern->signal_connect('activate' => sub {

                my ($pattern, $channel);

                # Prompt the user for a pattern/channel
                ($pattern, $channel) = $self->winObj->showDoubleEntryDialogue(
                    'Add channel pattern',
                    'Enter a pattern (regex)',
                    'Enter a channel (1-16 chars)',
                );

                if (defined $pattern && defined $channel) {

                    $self->winObj->visibleSession->pseudoCmd(
                        'addchannelpattern <' . $channel . '> <' . $pattern . '>',
                        $mode,
                    );
                }
            });
            $subMenu_channelsTask->append($menuItem_channelsTask_addPattern);

            my $menuItem_channelsTask_addException = Gtk3::MenuItem->new(
                'Add _exception pattern...',
            );
            $menuItem_channelsTask_addException->signal_connect('activate' => sub {

                # Prompt the user for a pattern
                my $pattern = $self->winObj->showEntryDialogue(
                    'Add exception pattern',
                    'Enter a pattern (regex)',
                );

                if (defined $pattern) {

                    $self->winObj->visibleSession->pseudoCmd(
                        'addchannelpattern -e <' . $pattern . '>',
                        $mode,
                    );
                }
            });
            $subMenu_channelsTask->append($menuItem_channelsTask_addException);

            my $menuItem_channelsTask_listPattern = Gtk3::MenuItem->new('_List patterns');
            $menuItem_channelsTask_listPattern->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('listchannelpattern', $mode);
            });
            $subMenu_channelsTask->append($menuItem_channelsTask_listPattern);

            $subMenu_channelsTask->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $menuItem_channelsTask_emptyWindow = Gtk3::MenuItem->new('Empty Channels _window');
            $menuItem_channelsTask_emptyWindow->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('emptychannelswindow', $mode);
            });
            $subMenu_channelsTask->append($menuItem_channelsTask_emptyWindow);

            $subMenu_channelsTask->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $menuItem_channelsTask_editTask = Gtk3::ImageMenuItem->new('Edit current _task...');
            my $menuImg_channelsTask_editTask = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
            $menuItem_channelsTask_editTask->set_image($menuImg_channelsTask_editTask);
            $menuItem_channelsTask_editTask->signal_connect('activate' => sub {

                my $session = $self->winObj->visibleSession;

                # Open up a task 'edit' window to edit the task, with the 'main' window as the
                #   parent
                $self->winObj->createFreeWin(
                    'Games::Axmud::EditWin::Task',
                    $self->winObj,
                    $session,
                    'Edit ' . $session->channelsTask->prettyName . ' task',
                    $session->channelsTask,
                    FALSE,                          # Not temporary
                    # Config
                    'edit_flag' => FALSE,           # Some IVs for current tasks not editable
                );
            });
            $subMenu_channelsTask->append($menuItem_channelsTask_editTask);

        my $menuItem_channelsTask = Gtk3::MenuItem->new('_Channels task');
        $menuItem_channelsTask->set_submenu($subMenu_channelsTask);
        $menuColumn_tasks->append($menuItem_channelsTask);
        # (Requires a visible session whose status is 'connected' or 'offline' and is running a
        #   Channels task)
        $self->ivAdd('menuItemHash', 'channels_task', $menuItem_channelsTask);

            # 'Chat task' submenu
            my $subMenu_chatTask = Gtk3::Menu->new();

            my $menuItem_chatTask_listen = Gtk3::MenuItem->new('_Listen for incoming calls');
            $menuItem_chatTask_listen->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('chatlisten', $mode);
            });
            $subMenu_chatTask->append($menuItem_chatTask_listen);

            my $menuItem_chatTask_ignore = Gtk3::MenuItem->new('_Ignore incoming calls');
            $menuItem_chatTask_ignore->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('chatignore', $mode);
            });
            $subMenu_chatTask->append($menuItem_chatTask_ignore);

            $subMenu_chatTask->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $menuItem_chatTask_chatContact = Gtk3::MenuItem->new('_Chat with...');
            $menuItem_chatTask_chatContact->signal_connect('activate' => sub {

                my (
                    $choice,
                    @comboList,
                );

                # Get a sorted list of chat contact names
                @comboList = sort {lc($a) cmp lc($b)} ($axmud::CLIENT->ivKeys('chatContactHash'));
                if (! @comboList) {

lib/Games/Axmud/Strip.pm  view on Meta::CPAN


                    if ($choice) {

                        $self->session->pseudoCmd(
                            'chatcall ' . $choice,
                            $mode,
                        );
                    }
                }
            });
            $subMenu_chatTask->append($menuItem_chatTask_chatContact);

            my $menuItem_chatTask_chatMM = Gtk3::MenuItem->new('Chat using _MudMaster...');
            $menuItem_chatTask_chatMM->signal_connect('activate' => sub {

                my ($host, $port);

                # Prompt the user for a host and port
                ($host, $port) = $self->winObj->showDoubleEntryDialogue(
                    'Chat using MudMaster',
                    'Enter a DNS/IP address',
                    '(Optional) enter the port',
                );

lib/Games/Axmud/Strip.pm  view on Meta::CPAN


                    } else {

                        $self->winObj->visibleSession->pseudoCmd(
                            'chatmcall ' . $host . ' ' . $port,
                            $mode,
                        );
                    }
                }
            });
            $subMenu_chatTask->append($menuItem_chatTask_chatMM);

            my $menuItem_chatTask_chatZChat = Gtk3::MenuItem->new('Chat using _zChat...');
            $menuItem_chatTask_chatZChat->signal_connect('activate' => sub {

                my ($host, $port);

                # Prompt the user for an address and port
                ($host, $port) = $self->winObj->showDoubleEntryDialogue(
                    'Chat using zChat',
                    'Enter a DNS/IP address',
                    '(Optional) enter the port',
                );

lib/Games/Axmud/Strip.pm  view on Meta::CPAN


                    } else {

                        $self->winObj->visibleSession->pseudoCmd(
                            'chatzcall ' . $host . ' ' . $port,
                            $mode,
                        );
                    }
                }
            });
            $subMenu_chatTask->append($menuItem_chatTask_chatZChat);

            $subMenu_chatTask->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $menuItem_chatTask_allowSnoop = Gtk3::MenuItem->new('_Allow everyone to snoop');
            $menuItem_chatTask_allowSnoop->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('chatset -a', $mode);
            });
            $subMenu_chatTask->append($menuItem_chatTask_allowSnoop);

            my $menuItem_chatTask_forbidSnoop = Gtk3::MenuItem->new('_Forbid all snooping');
            $menuItem_chatTask_forbidSnoop->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('chatset -f', $mode);
            });
            $subMenu_chatTask->append($menuItem_chatTask_forbidSnoop);

            $subMenu_chatTask->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $menuItem_chatTask_hangUpAll = Gtk3::MenuItem->new('_Hang up on everyone');
            $menuItem_chatTask_hangUpAll->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('chathangup', $mode);
            });
            $subMenu_chatTask->append($menuItem_chatTask_hangUpAll);

            $subMenu_chatTask->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $menuItem_chatTask_editTask = Gtk3::ImageMenuItem->new('Edit lead chat _task...');
            my $menuImg_chatTask_editTask = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
            $menuItem_chatTask_editTask->set_image($menuImg_chatTask_editTask);
            $menuItem_chatTask_editTask->signal_connect('activate' => sub {

                my $session = $self->winObj->visibleSession;

                # Open up a task 'edit' window to edit the task, with the 'main' window as the
                #   parent
                $self->winObj->createFreeWin(
                    'Games::Axmud::EditWin::Task',
                    $self->winObj,
                    $session,
                    'Edit ' . $session->chatTask->prettyName . ' task',
                    $session->chatTask,
                    FALSE,                          # Not temporary
                    # Config
                    'edit_flag' => FALSE,           # Some IVs for current tasks not editable
                );
            });
            $subMenu_chatTask->append($menuItem_chatTask_editTask);
            # (Requires a visible session whose status is 'connected' or 'offline' and is running a
            #   Chat task)
            $self->ivAdd('menuItemHash', 'edit_chat_task', $menuItem_chatTask_editTask);

        my $menuItem_chatTask = Gtk3::MenuItem->new('C_hat task');
        $menuItem_chatTask->set_submenu($subMenu_chatTask);
        $menuColumn_tasks->append($menuItem_chatTask);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'chat_task', $menuItem_chatTask);

            # 'Compass' submenu
            my $subMenu_compassTask = Gtk3::Menu->new();

            my $menuItem_compassTask_enableKeypad
                = Gtk3::MenuItem->new('_Enable keypad world commands');
            $menuItem_compassTask_enableKeypad->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('compass on', $mode);
            });
            $subMenu_compassTask->append($menuItem_compassTask_enableKeypad);

            my $menuItem_compassTask_disableKeypad
                = Gtk3::MenuItem->new('_Disable keypad world commands');
            $menuItem_compassTask_disableKeypad->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('compass off', $mode);
            });
            $subMenu_compassTask->append($menuItem_compassTask_disableKeypad);

            $subMenu_compassTask->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $menuItem_compassTask_addPattern = Gtk3::MenuItem->new('_Customise key...');
            $menuItem_compassTask_addPattern->signal_connect('activate' => sub {

                my (
                    $cmd, $keycode,
                    @comboList,
                );

                @comboList = (
                    'kp_0',
                    'kp_5',

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

                            'compass ' . $keycode . ' ' . $cmd,
                            $mode,
                        );

                    } else {

                        $self->winObj->visibleSession->pseudoCmd('compass ' . $keycode, $mode);
                    }
                }
            });
            $subMenu_compassTask->append($menuItem_compassTask_addPattern);

            $subMenu_compassTask->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $menuItem_compassTask_editTask = Gtk3::ImageMenuItem->new('Edit current _task...');
            my $menuImg_compassTask_editTask = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
            $menuItem_compassTask_editTask->set_image($menuImg_compassTask_editTask);
            $menuItem_compassTask_editTask->signal_connect('activate' => sub {

                my $session = $self->winObj->visibleSession;

                # Open up a task 'edit' window to edit the task, with the 'main' window as the
                #   parent
                $self->winObj->createFreeWin(
                    'Games::Axmud::EditWin::Task',
                    $self->winObj,
                    $session,
                    'Edit ' . $session->compassTask->prettyName . ' task',
                    $session->compassTask,
                    FALSE,                          # Not temporary
                    # Config
                    'edit_flag' => FALSE,           # Some IVs for current tasks not editable
                );
            });
            $subMenu_compassTask->append($menuItem_compassTask_editTask);

        my $menuItem_compassTask = Gtk3::MenuItem->new('C_ompass task');
        $menuItem_compassTask->set_submenu($subMenu_compassTask);
        $menuColumn_tasks->append($menuItem_compassTask);
        # (Requires a visible session whose status is 'connected' or 'offline' and is running a
        #   Compass task)
        $self->ivAdd('menuItemHash', 'compass_task', $menuItem_compassTask);

            # 'Divert task' submenu
            my $subMenu_divertTask = Gtk3::Menu->new();

            my $menuItem_divertTask_addPattern = Gtk3::MenuItem->new('Add _channel pattern...');
            $menuItem_divertTask_addPattern->signal_connect('activate' => sub {

                my ($pattern, $channel);

                # Prompt the user for a pattern/channel
                ($pattern, $channel) = $self->winObj->showDoubleEntryDialogue(
                    'Add channel pattern',
                    'Enter a pattern (regex)',
                    'Enter a channel (1-16 chars)',
                );

                if (defined $pattern && defined $channel) {

                    $self->winObj->visibleSession->pseudoCmd(
                        'addchannelpattern <' . $channel . '> <' . $pattern . '>',
                        $mode,
                    );
                }
            });
            $subMenu_divertTask->append($menuItem_divertTask_addPattern);

            my $menuItem_divertTask_addException = Gtk3::MenuItem->new('Add _exception pattern...');
            $menuItem_divertTask_addException->signal_connect('activate' => sub {

                # Prompt the user for a pattern
                my $pattern = $self->winObj->showEntryDialogue(
                    'Add exception pattern',
                    'Enter a pattern (regex)',
                );

                if (defined $pattern) {

                    $self->winObj->visibleSession->pseudoCmd(
                        'addchannelpattern -e <' . $pattern . '>',
                        $mode,
                    );
                }
            });
            $subMenu_divertTask->append($menuItem_divertTask_addException);

            my $menuItem_divertTask_listPattern = Gtk3::MenuItem->new('_List patterns');
            $menuItem_divertTask_listPattern->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('listchannelpattern', $mode);
            });
            $subMenu_divertTask->append($menuItem_divertTask_listPattern);

            $subMenu_divertTask->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $menuItem_divertTask_emptyWindow = Gtk3::MenuItem->new('Empty divert _window');
            $menuItem_divertTask_emptyWindow->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('emptydivertwindow', $mode);
            });
            $subMenu_divertTask->append($menuItem_divertTask_emptyWindow);

            $subMenu_divertTask->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $menuItem_divertTask_editTask = Gtk3::ImageMenuItem->new('Edit current _task...');
            my $menuImg_divertTask_editTask = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
            $menuItem_divertTask_editTask->set_image($menuImg_divertTask_editTask);
            $menuItem_divertTask_editTask->signal_connect('activate' => sub {

                my $session = $self->winObj->visibleSession;

                # Open up a task 'edit' window to edit the task, with the 'main' window as the
                #   parent
                $self->winObj->createFreeWin(
                    'Games::Axmud::EditWin::Task',
                    $self->winObj,
                    $session,
                    'Edit ' . $session->divertTask->prettyName . ' task',
                    $session->divertTask,
                    FALSE,                          # Not temporary
                    # Config
                    'edit_flag' => FALSE,           # Some IVs for current tasks not editable
                );
            });
            $subMenu_divertTask->append($menuItem_divertTask_editTask);

        my $menuItem_divertTask = Gtk3::MenuItem->new('_Divert task');
        $menuItem_divertTask->set_submenu($subMenu_divertTask);
        $menuColumn_tasks->append($menuItem_divertTask);
        # (Requires a visible session whose status is 'connected' or 'offline' and is running a
        #   Divert task)
        $self->ivAdd('menuItemHash', 'divert_task', $menuItem_divertTask);

            # 'Inventory/Condition task' submenu
            my $subMenu_inventoryTask = Gtk3::Menu->new();

            my $menuItem_inventoryTask_activateTask = Gtk3::MenuItem->new('_Activate task');
            $menuItem_inventoryTask_activateTask->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('activateinventory', $mode);
            });
            $subMenu_inventoryTask->append($menuItem_inventoryTask_activateTask);

            my $menuItem_inventoryTask_disactivateTask = Gtk3::MenuItem->new('_Disactivate task');
            $menuItem_inventoryTask_disactivateTask->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('disactivateinventory', $mode);
            });
            $subMenu_inventoryTask->append($menuItem_inventoryTask_disactivateTask);

            $subMenu_inventoryTask->append(Gtk3::SeparatorMenuItem->new()); # Separator

            my $menuItem_inventoryTask_sellAll = Gtk3::MenuItem->new('_Sell all');
            $menuItem_inventoryTask_sellAll->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('sellall', $mode);
            });
            $subMenu_inventoryTask->append($menuItem_inventoryTask_sellAll);

            my $menuItem_inventoryTask_dropAll = Gtk3::MenuItem->new('D_rop all');
            $menuItem_inventoryTask_dropAll->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('dropall', $mode);
            });
            $subMenu_inventoryTask->append($menuItem_inventoryTask_dropAll);

            $subMenu_inventoryTask->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $menuItem_inventoryTask_editTask = Gtk3::ImageMenuItem->new(
                'Edit current _Inventory task...',
            );
            my $menuImg_inventoryTask_editTask = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
            $menuItem_inventoryTask_editTask->set_image($menuImg_inventoryTask_editTask);
            $menuItem_inventoryTask_editTask->signal_connect('activate' => sub {

                my $session = $self->winObj->visibleSession;

                # Open up a task 'edit' window to edit the task, with the 'main' window as the
                #   parent

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

                    'Games::Axmud::EditWin::Task',
                    $self->winObj,
                    $session,
                    'Edit ' . $session->inventoryTask->prettyName . ' task',
                    $session->inventoryTask,
                    FALSE,                          # Not temporary
                    # Config
                    'edit_flag' => FALSE,           # Some IVs for current tasks not editable
                );
            });
            $subMenu_inventoryTask->append($menuItem_inventoryTask_editTask);

            my $menuItem_conditionTask_editTask = Gtk3::ImageMenuItem->new(
                'Edit current _Condition task...',
            );
            my $menuImg_conditionTask_editTask = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
            $menuItem_conditionTask_editTask->set_image($menuImg_conditionTask_editTask);
            $menuItem_conditionTask_editTask->signal_connect('activate' => sub {

                my $session = $self->winObj->visibleSession;

                # Open up a task 'edit' window to edit the task, with the 'main' window as the
                #   parent

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

                    'Games::Axmud::EditWin::Task',
                    $self->winObj,
                    $session,
                    'Edit ' . $session->conditionTask->prettyName . ' task',
                    $session->conditionTask,
                    FALSE,                          # Not temporary
                    # Config
                    'edit_flag' => FALSE,           # Some IVs for current tasks not editable
                );
            });
            $subMenu_inventoryTask->append($menuItem_conditionTask_editTask);

        my $menuItem_inventoryTask = Gtk3::MenuItem->new('_Inventory/Condition tasks');
        $menuItem_inventoryTask->set_submenu($subMenu_inventoryTask);
        $menuColumn_tasks->append($menuItem_inventoryTask);
        # (Requires a visible session whose status is 'connected' or 'offline' and is running a
        #   Inventory task)
        $self->ivAdd('menuItemHash', 'inventory_task', $menuItem_inventoryTask);

            # 'Locator task' submenu
            my $subMenu_locatorTask = Gtk3::Menu->new();

            my $menuItem_locatorTask_resetTask = Gtk3::MenuItem->new('_Reset task');
            $menuItem_locatorTask_resetTask->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('resetlocatortask', $mode);
            });
            $subMenu_locatorTask->append($menuItem_locatorTask_resetTask);

            my $menuItem_locatorTask_toggleLocWin = Gtk3::MenuItem->new('Toggle task _window');
            $menuItem_locatorTask_toggleLocWin->signal_connect('activate' => sub {

                if ($self->winObj->visibleSession->locatorTask->winObj) {

                    $self->winObj->visibleSession->pseudoCmd('closetaskwindow locator', $mode);

                } else {

                    $self->winObj->visibleSession->pseudoCmd('opentaskwindow locator', $mode);
                }
            });
            $subMenu_locatorTask->append($menuItem_locatorTask_toggleLocWin);

            $subMenu_locatorTask->append(Gtk3::SeparatorMenuItem->new());   # Separator

            my $menuItem_locatorTask_toggleUnknown
                = Gtk3::MenuItem->new('T_oggle unknown word collection');
            $menuItem_locatorTask_toggleUnknown->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('collectunknownwords', $mode);
            });
            $subMenu_locatorTask->append($menuItem_locatorTask_toggleUnknown);

            my $menuItem_locatorTask_emptyUnknown
                = Gtk3::MenuItem->new('_Empty unknown word list');
            $menuItem_locatorTask_emptyUnknown->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('emptyunknownwords', $mode);
            });
            $subMenu_locatorTask->append($menuItem_locatorTask_emptyUnknown);

            my $menuItem_locatorTask_displayUnknown
                = Gtk3::MenuItem->new('_Display unknown word list');
            $menuItem_locatorTask_displayUnknown->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('listunknownwords', $mode);
            });
            $subMenu_locatorTask->append($menuItem_locatorTask_displayUnknown);

            $subMenu_locatorTask->append(Gtk3::SeparatorMenuItem->new());   # Separator

            my $menuItem_locatorWiz = Gtk3::ImageMenuItem->new('Run _Locator wizard...');
            my $menuImg_locatorWiz = Gtk3::Image->new_from_stock('gtk-page-setup', 'menu');
            $menuItem_locatorWiz->set_image($menuImg_locatorWiz);
            $menuItem_locatorWiz->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('locatorwizard', $mode);
            });
            $subMenu_locatorTask->append($menuItem_locatorWiz);
            # (Requires a visible session whose status is 'connected' or 'offline'. A
            #   corresponding menu item also appears in $self->drawEditColumn)
            $self->ivAdd('menuItemHash', 'run_locator_wiz_2', $menuItem_locatorWiz);

            $subMenu_locatorTask->append(Gtk3::SeparatorMenuItem->new());   # Separator

            my $menuItem_locatorTask_editTask = Gtk3::ImageMenuItem->new('Edit current _task...');
            my $menuImg_locatorTask_editTask = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
            $menuItem_locatorTask_editTask->set_image($menuImg_locatorTask_editTask);
            $menuItem_locatorTask_editTask->signal_connect('activate' => sub {

                my $session = $self->winObj->visibleSession;

                # Open up a task 'edit' window to edit the task, with the 'main' window as the
                #   parent
                $self->winObj->createFreeWin(
                    'Games::Axmud::EditWin::Task',
                    $self->winObj,
                    $session,
                    'Edit ' . $session->locatorTask->prettyName . ' task',
                    $session->locatorTask,
                    FALSE,                          # Not temporary
                    # Config
                    'edit_flag' => FALSE,           # Some IVs for current tasks not editable
                );
            });
            $subMenu_locatorTask->append($menuItem_locatorTask_editTask);

        my $menuItem_locatorTask = Gtk3::MenuItem->new('_Locator task');
        $menuItem_locatorTask->set_submenu($subMenu_locatorTask);
        $menuColumn_tasks->append($menuItem_locatorTask);
        # (Requires a visible session whose status is 'connected' or 'offline' and is running a
        #   Locator task)
        $self->ivAdd('menuItemHash', 'locator_task', $menuItem_locatorTask);

            # 'Status task' submenu
            my $subMenu_statusTask = Gtk3::Menu->new();

            my $menuItem_statusTask_activateTask = Gtk3::MenuItem->new('_Activate task');
            $menuItem_statusTask_activateTask->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('activatestatustask', $mode);
            });
            $subMenu_statusTask->append($menuItem_statusTask_activateTask);

            my $menuItem_statusTask_disactivateTask = Gtk3::MenuItem->new('_Disactivate task');
            $menuItem_statusTask_disactivateTask->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('disactivatestatustask', $mode);
            });
            $subMenu_statusTask->append($menuItem_statusTask_disactivateTask);

            my $menuItem_statusTask_resetCounters = Gtk3::MenuItem->new('_Reset all counters');
            $menuItem_statusTask_resetCounters->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('resetcounter', $mode);
            });
            $subMenu_statusTask->append($menuItem_statusTask_resetCounters);

            $subMenu_statusTask->append(Gtk3::SeparatorMenuItem->new());    # Separator

            # 'Gauges' submenu
            my $subMenu_gauges = Gtk3::Menu->new();

            my $menuItem_statusTask_toggleStatWin = Gtk3::MenuItem->new('Toggle task _window');
            $menuItem_statusTask_toggleStatWin->signal_connect('activate' => sub {

                if ($self->winObj->visibleSession->statusTask->winObj) {

                    $self->winObj->visibleSession->pseudoCmd('closetaskwindow status', $mode);

                } else {

                    $self->winObj->visibleSession->pseudoCmd('opentaskwindow status', $mode);
                }
            });
            $subMenu_gauges->append($menuItem_statusTask_toggleStatWin);

            my $menuItem_statusTask_showGauge = Gtk3::MenuItem->new('Toggle _gauges');
            $menuItem_statusTask_showGauge->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('showstatusgauge', $mode);
            });
            $subMenu_gauges->append($menuItem_statusTask_showGauge);

            my $menuItem_statusTask_showGaugeLabel = Gtk3::MenuItem->new('Toggle gauge _labels');
            $menuItem_statusTask_showGaugeLabel->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('showstatusgauge -l', $mode);
            });
            $subMenu_gauges->append($menuItem_statusTask_showGaugeLabel);

            my $menuItem_gauges = Gtk3::MenuItem->new('D_isplay');
            $menuItem_gauges->set_submenu($subMenu_gauges);
            $subMenu_statusTask->append($menuItem_gauges);

            $subMenu_statusTask->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $menuItem_statusTask_editTask = Gtk3::ImageMenuItem->new('Edit current _task...');
            my $menuImg_statusTask_editTask = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
            $menuItem_statusTask_editTask->set_image($menuImg_statusTask_editTask);
            $menuItem_statusTask_editTask->signal_connect('activate' => sub {

                my $session = $self->winObj->visibleSession;

                # Open up a task 'edit' window to edit the task, with the 'main' window as the
                #   parent
                $self->winObj->createFreeWin(
                    'Games::Axmud::EditWin::Task',
                    $self->winObj,
                    $session,
                    'Edit ' . $session->statusTask->prettyName . ' task',
                    $session->statusTask,
                    FALSE,                          # Not temporary
                    # Config
                    'edit_flag' => FALSE,           # Some IVs for current tasks not editable
                );
            });
            $subMenu_statusTask->append($menuItem_statusTask_editTask);

        my $menuItem_statusTask = Gtk3::MenuItem->new('_Status task');
        $menuItem_statusTask->set_submenu($subMenu_statusTask);
        $menuColumn_tasks->append($menuItem_statusTask);
        # (Requires a visible session whose status is 'connected' or 'offline' and is running a
        #   Status task)
        $self->ivAdd('menuItemHash', 'status_task', $menuItem_statusTask);

            # 'Watch' submenu
            my $subMenu_watchTask = Gtk3::Menu->new();

            my $menuItem_watchTask_emptyWindow = Gtk3::MenuItem->new('Empty watch _window');
            $menuItem_watchTask_emptyWindow->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('emptywatchwindow', $mode);
            });
            $subMenu_watchTask->append($menuItem_watchTask_emptyWindow);

            $subMenu_watchTask->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $menuItem_watchTask_editTask = Gtk3::ImageMenuItem->new('Edit current _task...');
            my $menuImg_watchTask_editTask = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
            $menuItem_watchTask_editTask->set_image($menuImg_watchTask_editTask);
            $menuItem_watchTask_editTask->signal_connect('activate' => sub {

                my $session = $self->winObj->visibleSession;

                # Open up a task 'edit' window to edit the task, with the 'main' window as the
                #   parent
                $self->winObj->createFreeWin(
                    'Games::Axmud::EditWin::Task',
                    $self->winObj,
                    $session,
                    'Edit ' . $session->watchTask->prettyName . ' task',
                    $session->watchTask,
                    FALSE,                          # Not temporary
                    # Config
                    'edit_flag' => FALSE,           # Some IVs for current tasks not editable
                );
            });
            $subMenu_watchTask->append($menuItem_watchTask_editTask);

        my $menuItem_watchTask = Gtk3::MenuItem->new('_Watch task');
        $menuItem_watchTask->set_submenu($subMenu_watchTask);
        $menuColumn_tasks->append($menuItem_watchTask);
        # (Requires a visible session whose status is 'connected' or 'offline' and is running a
        #   Watch task)
        $self->ivAdd('menuItemHash', 'watch_task', $menuItem_watchTask);

        # Setup complete
        return $menuColumn_tasks;
    }

    sub drawDisplayColumn {

        # Called by $self->enableMenu
        # Sets up the menu's 'Display' column
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments, or if the menu can't be created
        #   Otherwise returns the Gtk3::Menu created

        my ($self, $check) = @_;

        # Local variables
        my $mode;

        # Check for improper arguments
        if (defined $check) {

             return $axmud::CLIENT->writeImproper($self->_objClass . '->drawDisplayColumn', @_);
        }

        # Import IVs (for convenience)
        $mode = $self->winObj->pseudoCmdMode;

        # Set up column
        my $menuColumn_display = Gtk3::Menu->new();
        if (! $menuColumn_display) {

            return undef;
        }

        my $menuItem_openAutomapper = Gtk3::ImageMenuItem->new('Open _automapper');
        my $menuImg_openAutomapper = Gtk3::Image->new_from_stock('gtk-jump-to', 'menu');
        $menuItem_openAutomapper->set_image($menuImg_openAutomapper);
        $menuItem_openAutomapper->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('openautomapper', $mode);
        });
        $menuColumn_display->append($menuItem_openAutomapper);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'open_automapper', $menuItem_openAutomapper);

        my $menuItem_openViewer = Gtk3::ImageMenuItem->new('Open object _viewer');
        my $menuImg_openViewer = Gtk3::Image->new_from_stock('gtk-jump-to', 'menu');
        $menuItem_openViewer->set_image($menuImg_openViewer);
        $menuItem_openViewer->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('opendataviewer', $mode);
        });
        $menuColumn_display->append($menuItem_openViewer);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'open_object_viewer', $menuItem_openViewer);

        $menuColumn_display->append(Gtk3::SeparatorMenuItem->new());    # Separator

            # 'Current layer' submenu
            my $subMenu_currentLayer = Gtk3::Menu->new();

            my $menuItem_currentLayer_moveUp = Gtk3::MenuItem->new('Move _up');
            $menuItem_currentLayer_moveUp->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('layerup', $mode);
            });
            $subMenu_currentLayer->append($menuItem_currentLayer_moveUp);

            my $menuItem_currentLayer_moveDown = Gtk3::MenuItem->new('Move _down');
            $menuItem_currentLayer_moveDown->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('layerdown', $mode);
            });
            $subMenu_currentLayer->append($menuItem_currentLayer_moveDown);

            $subMenu_currentLayer->append(Gtk3::SeparatorMenuItem->new());  # Separator

            my $menuItem_currentLayer_moveTop = Gtk3::MenuItem->new('Move to _top');
            $menuItem_currentLayer_moveTop->signal_connect('activate' => sub {

                # Get the workspace grid object used by the visible session; can't rely on
                #   $self->workspaceGridObj because 'main' windows might appear on several
                #   workspaces
                my $gridObj
                    = $self->winObj->workspaceObj->findWorkspaceGrid($self->visibleSession);

                if ($gridObj) {

                    $self->winObj->visibleSession->pseudoCmd(
                        'setlayer ' . ($gridObj->maxLayers - 1),
                        $mode,
                    );
                }
            });
            $subMenu_currentLayer->append($menuItem_currentLayer_moveTop);

            my $menuItem_currentLayer_moveBottom = Gtk3::MenuItem->new('Move to _bottom');
            $menuItem_currentLayer_moveBottom->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('setlayer 0', $mode);
            });
            $subMenu_currentLayer->append($menuItem_currentLayer_moveBottom);

            $subMenu_currentLayer->append(Gtk3::SeparatorMenuItem->new());  # Separator

            my $menuItem_currentLayer_setLayer = Gtk3::MenuItem->new('_Set layer...');
            $menuItem_currentLayer_setLayer->signal_connect('activate' => sub {

                my ($gridObj, $result);

                $gridObj = $self->winObj->workspaceObj->findWorkspaceGrid($self->visibleSession);

                if ($gridObj) {

                    # Display a dialogue to choose the new layer
                    $result = $self->winObj->showEntryDialogue(

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

                        'Enter the new layer (in the range 0-' . ($gridObj->maxLayers - 1) . ')',
                    );

                    if ($result) {

                        # Set the layer
                        $self->winObj->visibleSession->pseudoCmd('setlayer ' . $result, $mode);
                    }
                }
            });
            $subMenu_currentLayer->append($menuItem_currentLayer_setLayer);

        my $menuItem_currentLayer = Gtk3::MenuItem->new('Current _layer');
        $menuItem_currentLayer->set_submenu($subMenu_currentLayer);
        $menuColumn_display->append($menuItem_currentLayer);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'current_layer', $menuItem_currentLayer);

            # 'Window storage' submenu
            my $subMenu_windowStorage = Gtk3::Menu->new();

            my $menuItem_autoStore
                = Gtk3::CheckMenuItem->new('_Automatically store sizes/positions');
            $menuItem_autoStore->signal_connect('toggled' => sub {

                $self->winObj->visibleSession->pseudoCmd('togglewindowstorage', $mode);
            });
            $subMenu_windowStorage->append($menuItem_autoStore);

            my $menuItem_storeCurrent = Gtk3::MenuItem->new('_Store current sizes/positions');
            $menuItem_storeCurrent->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('applywindowstorage', $mode);
            });
            $subMenu_windowStorage->append($menuItem_storeCurrent);

            $subMenu_windowStorage->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $menuItem_resetStorage = Gtk3::MenuItem->new('_Clear stored sizes/positions');
            $menuItem_resetStorage->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('clearwindowstorage', $mode);
            });
            $subMenu_windowStorage->append($menuItem_resetStorage);

        my $menuItem_windowStorage = Gtk3::MenuItem->new('\'Grid\' _window storage');
        $menuItem_windowStorage->set_submenu($subMenu_windowStorage);
        $menuColumn_display->append($menuItem_windowStorage);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'window_storage', $menuItem_windowStorage);

        $menuColumn_display->append(Gtk3::SeparatorMenuItem->new());    # Separator

        my $menuItem_testControls = Gtk3::MenuItem->new('_Test window controls');
        $menuItem_testControls->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('testwindowcontrols', $mode);
        });
        $menuColumn_display->append($menuItem_testControls);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'test_controls', $menuItem_testControls);

        my $menuItem_testPanels = Gtk3::MenuItem->new('T_est panels');
        $menuItem_testPanels->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('testpanel', $mode);
        });
        $menuColumn_display->append($menuItem_testPanels);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'test_panels', $menuItem_testPanels);

        # Setup complete
        return $menuColumn_display;
    }

    sub drawCommandsColumn {

        # Called by $self->enableMenu
        # Sets up the menu's 'Commands' column
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments, or if the menu can't be created
        #   Otherwise returns the Gtk3::Menu created

        my ($self, $check) = @_;

        # Local variables
        my $mode;

        # Check for improper arguments
        if (defined $check) {

             return $axmud::CLIENT->writeImproper($self->_objClass . '->drawCommandsColumn', @_);
        }

        # Import IVs (for convenience)
        $mode = $self->winObj->pseudoCmdMode;

        # Set up column
        my $menuColumn_commands = Gtk3::Menu->new();
        if (! $menuColumn_commands) {

            return undef;
        }

        my $menuItem_repeat = Gtk3::ImageMenuItem->new('_Repeat...');
        my $menuImg_repeat = Gtk3::Image->new_from_stock('gtk-redo', 'menu');
        $menuItem_repeat->set_image($menuImg_repeat);
        $menuItem_repeat->signal_connect('activate' => sub {

            # Display a 'dialogue' window so the user can choose the command to repeat, and how
            #   often
            my ($cmd, $number);

            # Display the dialogue
            ($cmd, $number) = $self->winObj->showDoubleEntryDialogue(

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

            if ($cmd && $number) {

                # Issue the command
                $self->winObj->visibleSession->pseudoCmd('repeat ' . $number . ' ' . $cmd, $mode);
            }
        });
        $menuColumn_commands->append($menuItem_repeat);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'repeat_cmd', $menuItem_repeat);

        my $menuItem_repeatSecond = Gtk3::ImageMenuItem->new('Repeat each _second...');
        my $menuImg_repeatSecond = Gtk3::Image->new_from_stock('gtk-redo', 'menu');
        $menuItem_repeatSecond->set_image($menuImg_repeatSecond);
        $menuItem_repeatSecond->signal_connect('activate' => sub {

            # Display a 'dialogue' window so the user can choose the command to repeat, and how
            #   often
            my ($cmd, $number);

            # Display the dialogue
            ($cmd, $number) = $self->winObj->showDoubleEntryDialogue(

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

                $self->winObj->visibleSession->pseudoCmd(
                    'intervalrepeat ' . $number . ' 1 ' . $cmd,
                    $mode,
                );
            }
        });
        $menuColumn_commands->append($menuItem_repeatSecond);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'repeat_second', $menuItem_repeatSecond);

        my $menuItem_repeatInterval = Gtk3::ImageMenuItem->new('Repeat at _intervals...');
        my $menuImg_repeatInterval = Gtk3::Image->new_from_stock('gtk-redo', 'menu');
        $menuItem_repeatInterval->set_image($menuImg_repeatInterval);
        $menuItem_repeatInterval->signal_connect('activate' => sub {

            # Display a 'dialogue' window so the user can choose the command to repeat, and how
            #   often
            my ($cmd, $number, $interval);

            # Display the dialogue
            ($cmd, $number) = $self->winObj->showDoubleEntryDialogue(

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

                        'intervalrepeat ' . $number . ' ' . $interval . ' ' . $cmd,
                        $mode,
                    );
                }
            }
        });
        $menuColumn_commands->append($menuItem_repeatInterval);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'repeat_interval', $menuItem_repeatInterval);

        $menuColumn_commands->append(Gtk3::SeparatorMenuItem->new());   # Separator

        my $menuItem_cancelRepeat = Gtk3::ImageMenuItem->new('_Cancel repeating commands');
        my $menuImg_cancelRepeat = Gtk3::Image->new_from_stock('gtk-cancel', 'menu');
        $menuItem_cancelRepeat->set_image($menuImg_cancelRepeat);
        $menuItem_cancelRepeat->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('stopcommand', $mode);
        });
        $menuColumn_commands->append($menuItem_cancelRepeat);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'cancel_repeat', $menuItem_cancelRepeat);

        # Setup complete
        return $menuColumn_commands;
    }

    sub drawRecordingsColumn {

        # Called by $self->enableMenu
        # Sets up the menu's 'Recordings' column
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments, or if the menu can't be created
        #   Otherwise returns the Gtk3::Menu created

        my ($self, $check) = @_;

        # Local variables
        my $mode;

        # Check for improper arguments
        if (defined $check) {

             return $axmud::CLIENT->writeImproper($self->_objClass . '->drawRecordingsColumn', @_);
        }

        # Import IVs (for convenience)
        $mode = $self->winObj->pseudoCmdMode;

        # Set up column
        my $menuColumn_recordings = Gtk3::Menu->new();
        if (! $menuColumn_recordings) {

            return undef;
        }

        my $menuItem_startStop = Gtk3::ImageMenuItem->new('_Start/stop recording');
        my $menuImg_startStop = Gtk3::Image->new_from_stock('gtk-media-record', 'menu');
        $menuItem_startStop->set_image($menuImg_startStop);
        $menuItem_startStop->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('record', $mode);
        });
        $menuColumn_recordings->append($menuItem_startStop);
        # (Requires a visible session whose status is 'connected' or 'offline', and
        #   GA::Session->recordingPausedFlag set to FALSE)
        $self->ivAdd('menuItemHash', 'start_stop_recording', $menuItem_startStop);

        my $menuItem_pauseResume = Gtk3::ImageMenuItem->new('_Pause/resume recording');
        my $menuImg_pauseResume = Gtk3::Image->new_from_stock('gtk-media-pause', 'menu');
        $menuItem_pauseResume->set_image($menuImg_pauseResume);
        $menuItem_pauseResume->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('pauserecording', $mode);
        });
        $menuColumn_recordings->append($menuItem_pauseResume);
        # (Requires a visible session whose status is 'connected' or 'offline', and
        #   GA::Session->recordingFlag set to TRUE)
        $self->ivAdd('menuItemHash', 'pause_recording', $menuItem_pauseResume);

        $menuColumn_recordings->append(Gtk3::SeparatorMenuItem->new()); # Separator

            # 'Add line' submenu
            my $subMenu_addLine = Gtk3::Menu->new();

            my $menuItem_addWorldCmd = Gtk3::MenuItem->new('Add _world command...');
            $menuItem_addWorldCmd->signal_connect('activate' => sub {

                # Display a 'dialogue' window, so the user can choose the command to add
                my $text = $self->winObj->showEntryDialogue(
                    'Recording',
                    'Enter a world command to add at this point in the recording',
                );

                if ($text) {

                    # Add the world command
                    $self->winObj->visibleSession->pseudoCmd(
                        'worldcommand <' . $text . '>',
                        $mode,
                    );
                }
            });
            $subMenu_addLine->append($menuItem_addWorldCmd);

            my $menuItem_addClientCmd = Gtk3::MenuItem->new('Add _client command...');
            $menuItem_addClientCmd->signal_connect('activate' => sub {

                # Display a 'dialogue' window, so the user can choose the command to add
                my $text = $self->winObj->showEntryDialogue(
                    'Recording',
                    'Enter a client command to add at this point in the recording',
                );

                if ($text) {

                    # Add the client command
                    $self->winObj->visibleSession->pseudoCmd(
                        'clientcommand <' . $text . '>',
                        $mode,
                    );
                }
            });
            $subMenu_addLine->append($menuItem_addClientCmd);

            my $menuItem_addComment = Gtk3::MenuItem->new('Add co_mment...');
            $menuItem_addComment->signal_connect('activate' => sub {

                # Display a 'dialogue' window, so the user can choose the comment to add
                my $text = $self->winObj->showEntryDialogue(
                    'Recording',
                    'Enter a comment to add at this point in the recording',
                );

                if ($text) {

                    # Add the comment
                    $self->winObj->visibleSession->pseudoCmd(
                        'comment <' . $text . '>',
                        $mode,
                    );
                }
            });
            $subMenu_addLine->append($menuItem_addComment);

        my $menuItem_addLine = Gtk3::MenuItem->new('Add _line');
        $menuItem_addLine->set_submenu($subMenu_addLine);
        $menuColumn_recordings->append($menuItem_addLine);
        # (Requires a visible session whose status is 'connected' or 'offline' and a visible session
        #   whose ->recordingFlag set to TRUE)
        $self->ivAdd('menuItemHash', 'recording_add_line', $menuItem_addLine);

            # 'Add break' submenu
            my $subMenu_addBreak = Gtk3::Menu->new();

            my $menuItem_ordinaryBreak = Gtk3::MenuItem->new('Add _ordinary break');
            $menuItem_ordinaryBreak->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('break', $mode);
            });
            $subMenu_addBreak->append($menuItem_ordinaryBreak);

            my $menuItem_triggerBreak = Gtk3::MenuItem->new('Add _trigger break...');
            $menuItem_triggerBreak->signal_connect('activate' => sub {

                # Display a 'dialogue' window, so the user can choose the trigger pattern to add
                my $text = $self->winObj->showEntryDialogue(
                    'Recording',
                    'Enter a trigger pattern to add at this point in the recording',
                );

                if ($text) {

                    # Add the trigger break
                    $self->winObj->visibleSession->pseudoCmd('break -t ' . $text, $mode);
                }
            });
            $subMenu_addBreak->append($menuItem_triggerBreak);

            my $menuItem_pauseBreak = Gtk3::MenuItem->new('Add _pause break...');
            $menuItem_pauseBreak->signal_connect('activate' => sub {

                # Display a 'dialogue' window, so the user can choose the pause interval to add
                my $text = $self->winObj->showEntryDialogue(
                    'Recording',
                    'Enter the length of the pause break to add at this point in the recording',
                );

                if ($text) {

                    # Add the pause break
                    $self->winObj->visibleSession->pseudoCmd('break -p ' . $text, $mode);
                }
            });
            $subMenu_addBreak->append($menuItem_pauseBreak);

            my $menuItem_locatorBreak = Gtk3::MenuItem->new('Add _Locator task break');
            $menuItem_locatorBreak->signal_connect('activate' => sub {

                $self->winObj->visibleSession->pseudoCmd('break -l', $mode);
            });
            $subMenu_addBreak->append($menuItem_locatorBreak);

        my $menuItem_addBreak = Gtk3::MenuItem->new('Add _break');
        $menuItem_addBreak->set_submenu($subMenu_addBreak);
        $menuColumn_recordings->append($menuItem_addBreak);
        # (Requires a visible session whose status is 'connected' or 'offline' and a visible session
        #   whose ->recordingFlag set to TRUE)
        $self->ivAdd('menuItemHash', 'recording_add_break', $menuItem_addBreak);

        $menuColumn_recordings->append(Gtk3::SeparatorMenuItem->new()); # Separator

        my $menuItem_insertPoint = Gtk3::MenuItem->new('Set _insertion point...');
        $menuItem_insertPoint->signal_connect('activate' => sub {

            # Display a 'dialogue' window, so the user can choose the insertion point
            my $text = $self->winObj->showEntryDialogue(
                'Recording',
                'Enter the line number at which to continue the recording',
            );

            if ($text) {

                # Set the insertion point
                $self->winObj->visibleSession->pseudoCmd('insertrecording ' . $text, $mode);
            }
        });
        $menuColumn_recordings->append($menuItem_insertPoint);
        # (Requires a visible session whose status is 'connected' or 'offline' and a visible session
        #   whose ->recordingFlag set to TRUE)
        $self->ivAdd('menuItemHash', 'recording_set_insertion', $menuItem_insertPoint);

        my $menuItem_cancelInsert = Gtk3::MenuItem->new('_Cancel insertion point');
        $menuItem_cancelInsert->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('insertrecording', $mode);
        });
        $menuColumn_recordings->append($menuItem_cancelInsert);
        # (Requires a visible session whose status is 'connected' or 'offline' and a visible session
        #   whose ->recordingFlag set to TRUE)
        $self->ivAdd('menuItemHash', 'recording_cancel_insertion', $menuItem_cancelInsert);

        $menuColumn_recordings->append(Gtk3::SeparatorMenuItem->new()); # Separator

        my $menuItem_deleteLine = Gtk3::MenuItem->new('_Delete line...');
        $menuItem_deleteLine->signal_connect('activate' => sub {

            # Display a 'dialogue' window, so the user can choose the line to delete
            my $text = $self->winObj->showEntryDialogue(
                'Recording',
                'Enter the number of the line to delete',
            );

            if ($text) {

                # Delete the line
                $self->winObj->visibleSession->pseudoCmd('deleterecording ' . $text, $mode);
            }
        });
        $menuColumn_recordings->append($menuItem_deleteLine);
        # (Requires a visible session whose status is 'connected' or 'offline' and a visible session
        #   whose ->recordingFlag set to TRUE)
        $self->ivAdd('menuItemHash', 'recording_delete_line', $menuItem_deleteLine);

        my $menuItem_deleteMulti = Gtk3::MenuItem->new('D_elete lines...');
        $menuItem_deleteMulti->signal_connect('activate' => sub {

            # Display a 'dialogue' window, so the user can choose the lines to delete
            my ($start, $stop) = $self->winObj->showDoubleEntryDialogue(
                'Recording',
                'Enter the number of the first line to be deleted',
                'Enter the number of the last line to be deleted',
            );

            if (defined $start && defined $stop) {

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

                    'deleterecording ' . $start . ' ' . $stop,
                    $mode,
                );
            }
        });
        $menuColumn_recordings->append($menuItem_deleteMulti);
        # (Requires a visible session whose status is 'connected' or 'offline' and a visible session
        #   whose ->recordingFlag set to TRUE)
        $self->ivAdd('menuItemHash', 'recording_delete_multi', $menuItem_deleteMulti);

        my $menuItem_deleteLast = Gtk3::MenuItem->new('Delete l_ast line');
        $menuItem_deleteLast->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('deleterecording', $mode);

        });
        $menuColumn_recordings->append($menuItem_deleteLast);
        # (Requires a visible session whose status is 'connected' or 'offline' and a visible session
        #   whose ->recordingFlag set to TRUE)
        $self->ivAdd('menuItemHash', 'recording_delete_last', $menuItem_deleteLast);

        $menuColumn_recordings->append(Gtk3::SeparatorMenuItem->new()); # Separator

        my $menuItem_showRecording = Gtk3::MenuItem->new('S_how recording');
        $menuItem_showRecording->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('listrecording', $mode);
        });
        $menuColumn_recordings->append($menuItem_showRecording);
        # (Requires a visible session whose status is 'connected' or 'offline' and a visible session
        #   whose ->recordingFlag set to TRUE or whose ->recordingList is not empty)
        $self->ivAdd('menuItemHash', 'show_recording', $menuItem_showRecording);

        my $menuItem_copyRecording = Gtk3::MenuItem->new('C_opy recording');
        $menuItem_copyRecording->signal_connect('activate' => sub {

            $self->winObj->visibleSession->pseudoCmd('copyrecording', $mode);
        });
        $menuColumn_recordings->append($menuItem_copyRecording);
        # (Requires a visible session whose status is 'connected' or 'offline' and a visible session
        #   whose ->recordingFlag set to TRUE or whose ->recordingList is not empty)
        $self->ivAdd('menuItemHash', 'copy_recording', $menuItem_copyRecording);

        # Setup complete
        return $menuColumn_recordings;
    }

    sub drawAxbasicColumn {

        # Called by $self->enableMenu
        # Sets up the menu's 'Axbasic' column
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments, or if the menu can't be created
        #   Otherwise returns the Gtk3::Menu created

        my ($self, $check) = @_;

        # Local variables
        my $mode;

        # Check for improper arguments
        if (defined $check) {

             return $axmud::CLIENT->writeImproper($self->_objClass . '->drawAxbasicColumn', @_);
        }

        # Import IVs (for convenience)
        $mode = $self->winObj->pseudoCmdMode;

        # Set up column
        my $menuColumn_basic = Gtk3::Menu->new();
        if (! $menuColumn_basic) {

            return undef;
        }

        my $menuItem_runScript = Gtk3::ImageMenuItem->new('_Run script...');
        my $menuImg_runScript = Gtk3::Image->new_from_stock('gtk-execute', 'menu');
        $menuItem_runScript->set_image($menuImg_runScript);
        $menuItem_runScript->signal_connect('activate' => sub {

            # Display a 'dialogue' window, so the user can choose the script to run
            my $text = $self->winObj->showEntryDialogue(
                'Run ' . $axmud::BASIC_NAME . ' script',
                'Enter the script to run (e.g. \'wumpus\')',
            );

            if ($text) {

                # Run the script
                $self->winObj->visibleSession->pseudoCmd('runscript ' . $text, $mode);
            }
        });
        $menuColumn_basic->append($menuItem_runScript);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'run_script', $menuItem_runScript);

        my $menuItem_runScriptTask = Gtk3::ImageMenuItem->new('Run script as _task...');
        my $menuImg_runScriptTask = Gtk3::Image->new_from_stock('gtk-execute', 'menu');
        $menuItem_runScriptTask->set_image($menuImg_runScriptTask);
        $menuItem_runScriptTask->signal_connect('activate' => sub {

            # Display a 'dialogue' window, so the user can choose the script to run
            my $text = $self->winObj->showEntryDialogue(
                'Run ' . $axmud::BASIC_NAME . ' script',
                'Enter the script to run as a task (e.g. \'wumpus\')',
            );

            if ($text) {

                # Run the script as a task
                $self->winObj->visibleSession->pseudoCmd('runscripttask ' . $text, $mode);
            }
        });
        $menuColumn_basic->append($menuItem_runScriptTask);
        # (Requires a visible session whose status is 'connected' or 'offline')
        $self->ivAdd('menuItemHash', 'run_script_task', $menuItem_runScriptTask);

        $menuColumn_basic->append(Gtk3::SeparatorMenuItem->new()); # Separator

        my $menuItem_checkScript = Gtk3::MenuItem->new('_Check script...');
        $menuItem_checkScript->signal_connect('activate' => sub {

            # Display a 'dialogue' window, so the user can choose the script to check
            my $text = $self->winObj->showEntryDialogue(
                'Check ' . $axmud::BASIC_NAME . ' script',
                'Enter the script to check (e.g. \'wumpus\')',
            );

            if ($text) {

                # Check the script
                $self->winObj->visibleSession->pseudoCmd('checkscript ' . $text, $mode);
            }
        });
        $menuColumn_basic->append($menuItem_checkScript);
        # (Requires a visible session)
        $self->ivAdd('menuItemHash', 'check_script', $menuItem_checkScript);

        my $menuItem_editScript = Gtk3::ImageMenuItem->new('_Edit script...');
        my $menuImg_editScript = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
        $menuItem_editScript->set_image($menuImg_editScript);
        $menuItem_editScript->signal_connect('activate' => sub {

            # Display a 'dialogue' window, so the user can choose the script to check
            my $text = $self->winObj->showEntryDialogue(
                'Edit ' . $axmud::BASIC_NAME . ' script',
                'Enter the script to edit (e.g. \'wumpus\')',
            );

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

        $menuColumn_basic->append($menuItem_editScript);
        # (Requires a visible session)
        $self->ivAdd('menuItemHash', 'edit_script', $menuItem_editScript);

        # Setup complete
        return $menuColumn_basic;
    }

    sub drawPluginsColumn {

        # Called by $self->enableMenu
        # Sets up the menu's 'Plugins' column
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments, or if the menu can't be created
        #   Otherwise returns the Gtk3::Menu created

        my ($self, $check) = @_;

        # Local variables
        my $mode;

        # Check for improper arguments
        if (defined $check) {

             return $axmud::CLIENT->writeImproper($self->_objClass . '->drawPluginsColumn', @_);
        }

        # Import IVs (for convenience)
        $mode = $self->winObj->pseudoCmdMode;

        # Set up column
        my $menuColumn_plugins = Gtk3::Menu->new();
        if (! $menuColumn_plugins) {

            return undef;
        }

        my $menuItem_loadPlugin = Gtk3::ImageMenuItem->new('_Load plugin...');
        my $menuImg_loadPlugin = Gtk3::Image->new_from_stock('gtk-open', 'menu');
        $menuItem_loadPlugin->set_image($menuImg_loadPlugin);
        $menuItem_loadPlugin->signal_connect('activate' => sub {

            # Load the plugin
            $self->winObj->visibleSession->pseudoCmd('loadplugin', $mode);
        });
        $menuColumn_plugins->append($menuItem_loadPlugin);
        # (Requires a visible session)
        $self->ivAdd('menuItemHash', 'load_plugin', $menuItem_loadPlugin);

        my $menuItem_showPlugins = Gtk3::MenuItem->new('_Show plugins...');
        $menuItem_showPlugins->signal_connect('activate' => sub {

            # Open the client preference window at the right page
            my $prefWin = $self->winObj->createFreeWin(
                'Games::Axmud::PrefWin::Client',
                $self->winObj,
                $self->winObj->visibleSession,
                'Client preferences',
            );

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

        $menuColumn_plugins->append($menuItem_showPlugins);
        # (Requires a visible session)
        $self->ivAdd('menuItemHash', 'show_plugin', $menuItem_showPlugins);

        # Setup complete
        return $menuColumn_plugins;
    }

    sub drawHelpColumn {

        # Called by $self->enableMenu
        # Sets up the menu's 'Help' column
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments, or if the menu can't be created
        #   Otherwise returns the Gtk3::Menu created

        my ($self, $check) = @_;

        # Local variables
        my $mode;

        # Check for improper arguments
        if (defined $check) {

             return $axmud::CLIENT->writeImproper($self->_objClass . '->drawHelpColumn', @_);
        }

        # Import IVs (for convenience)
        $mode = $self->winObj->pseudoCmdMode;

        # Set up column
        my $menuColumn_help = Gtk3::Menu->new();
        if (! $menuColumn_help) {

            return undef;
        }

        my $menuItem_help = Gtk3::ImageMenuItem->new('_Help...');
        my $menuImg_help = Gtk3::Image->new_from_stock('gtk-help', 'menu');
        $menuItem_help->set_image($menuImg_help);
        $menuItem_help->signal_connect('activate' => sub {

            # Check that the About window isn't already open
            if ($axmud::CLIENT->aboutWin) {

                # Only one About window can be open at a time
                $axmud::CLIENT->aboutWin->restoreFocus();
                # Open it at the right page

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

                if ($winObj) {

                    $axmud::CLIENT->set_aboutWin($winObj);
                }
            }
        });
        $menuColumn_help->append($menuItem_help);
        # (Desensitised only when the setup wizwin is open)
        $self->ivAdd('menuItemHash', 'help', $menuItem_help);

        $menuColumn_help->append(Gtk3::SeparatorMenuItem->new());   # Separator

        my $menuItem_about = Gtk3::ImageMenuItem->new('_About...');
        my $menuImg_about = Gtk3::Image->new_from_stock('gtk-about', 'menu');
        $menuItem_about->set_image($menuImg_about);
        $menuItem_about->signal_connect('activate' => sub {

            # Check that the About window isn't already open
            if ($axmud::CLIENT->aboutWin) {

                # Window already open; draw attention to the fact by 'present'ing it
                $axmud::CLIENT->aboutWin->restoreFocus();
                # Open it at the right page

lib/Games/Axmud/Strip.pm  view on Meta::CPAN


                    # Only one About window can be open at a time
                    $axmud::CLIENT->set_aboutWin($winObj);
                }
            }
        });
        $menuColumn_help->append($menuItem_about);
        # (Desensitised only when the setup wizwin is open)
        $self->ivAdd('menuItemHash', 'about', $menuItem_about);

        my $menuItem_credits = Gtk3::MenuItem->new('_Credits...');
        $menuItem_credits->signal_connect('activate' => sub {

            # Check that the About window isn't already open
            if ($axmud::CLIENT->aboutWin) {

                # Window already open; draw attention to the fact by 'present'ing it
                $axmud::CLIENT->aboutWin->restoreFocus();
                # Open it at the right page
                $axmud::CLIENT->aboutWin->notebook->set_current_page(1);

lib/Games/Axmud/Strip.pm  view on Meta::CPAN


                    # Only one About window can be open at a time
                    $axmud::CLIENT->set_aboutWin($winObj);
                }
            }
        });
        $menuColumn_help->append($menuItem_credits);
        # (Desensitised only when the setup wizwin is open)
        $self->ivAdd('menuItemHash', 'credits', $menuItem_credits);

        my $menuItem_license = Gtk3::MenuItem->new('_Licenses...');
        $menuItem_license->signal_connect('activate' => sub {

            # Check that the About window isn't already open
            if ($axmud::CLIENT->aboutWin) {

                # Window already open; draw attention to the fact by 'present'ing it
                $axmud::CLIENT->aboutWin->restoreFocus();
                # Open it at the right page
                $axmud::CLIENT->aboutWin->notebook->set_current_page(3);

lib/Games/Axmud/Strip.pm  view on Meta::CPAN


                    # Only one About window can be open at a time
                    $axmud::CLIENT->set_aboutWin($winObj);
                }
            }
        });
        $menuColumn_help->append($menuItem_license);
        # (Desensitised only when the setup wizwin is open)
        $self->ivAdd('menuItemHash', 'license', $menuItem_license);

        $menuColumn_help->append(Gtk3::SeparatorMenuItem->new());   # Separator

        my $menuItem_website = Gtk3::MenuItem->new($axmud::SCRIPT . ' _website...');
        $menuItem_website->signal_connect('activate' => sub {

            $axmud::CLIENT->openURL($axmud::URL);
        });
        $menuColumn_help->append($menuItem_website);
        # (Requires GA::Client->browserCmd)
        $self->ivAdd('menuItemHash', 'go_website', $menuItem_website);

        # Setup complete
        return $menuColumn_help;
    }

    sub addPluginWidgets {

        # Called by GA::Client->addPluginMenus to add a sub-menu in the 'plugins' column, for the
        #   benefit of a loaded plugin
        # Also called by $self->objEnable to add plugin sub-menus for 'internal' windows that are
        #   created after the plugins are loaded
        #
        # Expected arguments
        #   $plugin     - The plugin name
        #
        # Return values
        #   'undef' on improper arguments
        #   Otherwise, returns the sub-menu to which the plugin's code can add new menu items

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

        # Check for improper arguments
        if (! defined $plugin || defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->addPluginWidgets', @_);
        }

        # Create a sub-menu for this plugin. If this is the first plugin to add menu items, add a
        #   separator
        if (! $self->pluginHash) {

            $self->pluginMenu->append(Gtk3::SeparatorMenuItem->new());
        }

        # Add a sub-menu
        my $subMenu = Gtk3::Menu->new();

        my $menuItem = Gtk3::MenuItem->new('_' . $plugin . ' plugin');
        $menuItem->set_submenu($subMenu);
        $self->pluginMenu->append($menuItem);

        # Update IVs
        $self->ivAdd('pluginHash', $plugin, $subMenu);
        $self->ivAdd('pluginMenuItemHash', $plugin, $menuItem);

        return $subMenu;
    }

    sub sensitiseWidgets {

        # Can be called by anything, but usually called by GA::Win::Internal->restrictMenuBars
        # Given a list of Gtk3 widgets (all of them menu bar items), sets them as sensitive
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Optional arguments
        #   @widgetList - A list of widget names, matching keys in $self->menuItemHash
        #                   (e.g. 'move_up_level')
        #
        # Return values

lib/Games/Axmud/Strip.pm  view on Meta::CPAN


                $widget->set_sensitive(TRUE);
            }
        }

        return 1;
    }

    sub desensitiseWidgets {

        # Can be called by anything, but usually called by GA::Win::Internal->restrictMenuBars
        # Given a list of Gtk3 widgets (all of them menu bar items), sets them as insensitive
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Optional arguments
        #   @widgetList - A list of widget names, matching keys in $self->menuItemHash
        #                   (e.g. 'move_up_level')
        #
        # Return values

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

            my $widget = $self->ivShow('menuItemHash', $widgetName);
            if ($widget) {

                $widget->set_sensitive(FALSE);
            }
        }

        return 1;
    }

    # Menu bar support functions

    sub promptUser {

        # Called by most menu items in $self->drawWorldColumn
        # Before doing an action that will lead to the current connection being closed (e.g. 'Stop
        #   client', which runs the ';stopclient' command), prompt the user for confirmation
        # We don't want the user to lose their connection after accidentally clicking on a menu
        #   item; at the same time, we usually don't ask for confirmation when the user types the
        #   equivalent client command, because they are much less likely to make a mistake while
        #   typing, than while clicking

lib/Games/Axmud/Strip.pm  view on Meta::CPAN


    ##################
    # Accessors - get

    sub menuBar
        { $_[0]->{menuBar} }

    sub menuItemHash
        { my $self = shift; return %{$self->{menuItemHash}}; }

    sub pluginMenu
        { $_[0]->{pluginMenu} }
    sub pluginHash
        { my $self = shift; return %{$self->{pluginHash}}; }
    sub pluginMenuItemHash
        { my $self = shift; return %{$self->{pluginMenuItemHash}}; }

    sub saveAllSessionsFlag
        { $_[0]->{saveAllSessionsFlag} }
}

{ package Games::Axmud::Strip::Toolbar;

    use strict;
    use warnings;
#   use diagnostics;

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

            #   parent window, set to FALSE if any number of instances can be added
            jealousyFlag                => TRUE,
            # Flag set to TRUE if this strip object can be added when $axmud::BLIND_MODE_FLAG is
            #   TRUE, FALSE if it can't be added (because it's not useful for visually-impaired
            #   users)
            blindFlag                   => FALSE,
            # Flag set to TRUE if the main container widget, stored in $self->packingBox, should be
            #   allowed to accept the focus, FALSE if not. The restriction is applied during the
            #   call to GA::Win::Internal->drawWidgets and ->addStripObj. Even if FALSE, widgets in
            #   the container widget can be set to accept the focus (e.g. the Gtk3::Entry in
            #   GA::Strip::MenuBar)
            allowFocusFlag              => FALSE,

            # Initialisation settings stored as a hash (see the comments above)
            initHash                    => \%modHash,
            # Reference to a function to call when some widget is used. This IV is set only when
            #   required by this type of strip object. It can be set by a call to
            #   $self->set_func() or by some setting in $self->initHash, which is applied in the
            #   call to $self->objEnable(). To obtain a reference to an OOP method, you can use the
            #   generic object function Games::Axmud->getMethodRef()
            funcRef                     => undef,

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

            #   parent window, set to FALSE if any number of instances can be added
            jealousyFlag                => TRUE,
            # Flag set to TRUE if this strip object can be added when $axmud::BLIND_MODE_FLAG is
            #   TRUE, FALSE if it can't be added (because it's not useful for visually-impaired
            #   users)
            blindFlag                   => TRUE,
            # Flag set to TRUE if the main container widget, stored in $self->packingBox, should be
            #   allowed to accept the focus, FALSE if not. The restriction is applied during the
            #   call to GA::Win::Internal->drawWidgets and ->addStripObj. Even if FALSE, widgets in
            #   the container widget can be set to accept the focus (e.g. the Gtk3::Entry in
            #   GA::Strip::MenuBar)
            allowFocusFlag              => FALSE,

            # Initialisation settings stored as a hash (see the comments above)
            initHash                    => \%modHash,
            # Reference to a function to call when some widget is used. This IV is set only when
            #   required by this type of strip object. It can be set by a call to
            #   $self->set_func() or by some setting in $self->initHash, which is applied in the
            #   call to $self->objEnable(). To obtain a reference to an OOP method, you can use the
            #   generic object function Games::Axmud->getMethodRef()
            funcRef                     => undef,

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

            #   parent window, set to FALSE if any number of instances can be added
            jealousyFlag                => TRUE,
            # Flag set to TRUE if this strip object can be added when $axmud::BLIND_MODE_FLAG is
            #   TRUE, FALSE if it can't be added (because it's not useful for visually-impaired
            #   users)
            blindFlag                   => FALSE,
            # Flag set to TRUE if the main container widget, stored in $self->packingBox, should be
            #   allowed to accept the focus, FALSE if not. The restriction is applied during the
            #   call to GA::Win::Internal->drawWidgets and ->addStripObj. Even if FALSE, widgets in
            #   the container widget can be set to accept the focus (e.g. the Gtk3::Entry in
            #   GA::Strip::MenuBar)
            allowFocusFlag              => FALSE,

            # Initialisation settings stored as a hash (see the comments above)
            initHash                    => \%modHash,
            # Reference to a function to call when some widget is used. This IV is set only when
            #   required by this type of strip object. It can be set by a call to
            #   $self->set_func() or by some setting in $self->initHash, which is applied in the
            #   call to $self->objEnable(). To obtain a reference to an OOP method, you can use the
            #   generic object function Games::Axmud->getMethodRef()
            funcRef                     => undef,

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

            #   parent window, set to FALSE if any number of instances can be added
            jealousyFlag                => TRUE,
            # Flag set to TRUE if this strip object can be added when $axmud::BLIND_MODE_FLAG is
            #   TRUE, FALSE if it can't be added (because it's not useful for visually-impaired
            #   users)
            blindFlag                   => FALSE,
            # Flag set to TRUE if the main container widget, stored in $self->packingBox, should be
            #   allowed to accept the focus, FALSE if not. The restriction is applied during the
            #   call to GA::Win::Internal->drawWidgets and ->addStripObj. Even if FALSE, widgets in
            #   the container widget can be set to accept the focus (e.g. the Gtk3::Entry in
            #   GA::Strip::MenuBar)
            allowFocusFlag              => FALSE,

            # Initialisation settings stored as a hash (see the comments above)
            initHash                    => \%modHash,
            # Reference to a function to call when some widget is used. This IV is set only when
            #   required by this type of strip object. It can be set by a call to
            #   $self->set_func() or by some setting in $self->initHash, which is applied in the
            #   call to $self->objEnable(). To obtain a reference to an OOP method, you can use the
            #   generic object function Games::Axmud->getMethodRef()
            funcRef                     => undef,

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

            #   parent window, set to FALSE if any number of instances can be added
            jealousyFlag                => TRUE,
            # Flag set to TRUE if this strip object can be added when $axmud::BLIND_MODE_FLAG is
            #   TRUE, FALSE if it can't be added (because it's not useful for visually-impaired
            #   users)
            blindFlag                   => TRUE,
            # Flag set to TRUE if the main container widget, stored in $self->packingBox, should be
            #   allowed to accept the focus, FALSE if not. The restriction is applied during the
            #   call to GA::Win::Internal->drawWidgets and ->addStripObj. Even if FALSE, widgets in
            #   the container widget can be set to accept the focus (e.g. the Gtk3::Entry in
            #   GA::Strip::MenuBar)
            allowFocusFlag              => FALSE,

            # Initialisation settings stored as a hash (see the comments above)
            initHash                    => \%modHash,
            # Reference to a function to call when some widget is used. This IV is set only when
            #   required by this type of strip object. It can be set by a call to
            #   $self->set_func() or by some setting in $self->initHash, which is applied in the
            #   call to $self->objEnable(). To obtain a reference to an OOP method, you can use the
            #   generic object function Games::Axmud->getMethodRef()
            funcRef                     => undef,

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

        if ($self->entry) {

            $self->winObj->winShowAll($self->_objClass . '->obscureEntry');
        }

        return 1;
    }

    sub commandeerEntry {

        # Called by GA::Obj::TextView->setButtonPressEvent and ->createPopupMenu
        # When an MXP <SEND>..</SEND> construction (or any other code) wants to insert a command
        #   into the client's command line (instead of sending it to the world directly), this
        #   function is called
        # The command is copied into the entry box (but only if the calling session is this window's
        #   visible session, which it almost certainly is)
        #
        # Expected arguments
        #   $session        - The calling GA::Session
        #   $cmd            - The command to display in the entry box
        #

lib/Games/Axmud/Strip.pm  view on Meta::CPAN

            #   parent window, set to FALSE if any number of instances can be added
            jealousyFlag                => TRUE,
            # Flag set to TRUE if this strip object can be added when $axmud::BLIND_MODE_FLAG is
            #   TRUE, FALSE if it can't be added (because it's not useful for visually-impaired
            #   users)
            blindFlag                   => FALSE,
            # Flag set to TRUE if the main container widget, stored in $self->packingBox, should be
            #   allowed to accept the focus, FALSE if not. The restriction is applied during the
            #   call to GA::Win::Internal->drawWidgets and ->addStripObj. Even if FALSE, widgets in
            #   the container widget can be set to accept the focus (e.g. the Gtk3::Entry in
            #   GA::Strip::MenuBar)
            allowFocusFlag              => FALSE,

            # Initialisation settings stored as a hash (see the comments above)
            initHash                    => \%modHash,
            # Reference to a function to call when some widget is used. This IV is set only when
            #   required by this type of strip object. It can be set by a call to
            #   $self->set_func() or by some setting in $self->initHash, which is applied in the
            #   call to $self->objEnable(). To obtain a reference to an OOP method, you can use the
            #   generic object function Games::Axmud->getMethodRef()
            funcRef                     => undef,

lib/Games/Axmud/Win/Internal.pm  view on Meta::CPAN

                $winzoneObj->left,
                $winzoneObj->right,
                $winzoneObj->top,
                $winzoneObj->bottom,
                $winzoneObj->objName,
                $winzoneObj->initHash,
            );
        }

        # Sensitise/desensitise widgets according to current conditions
        $self->restrictMenuBars();
        $self->restrictToolbars();

        return 1;
    }

    sub redrawWidgets {

        # Can be called by anything
        # Resets the Gtk3::Window by re-packing the strip objects in $self->stripList
        # When called by $self->addStripObj, the new strip object will be packed for the first time.

lib/Games/Axmud/Win/Internal.pm  view on Meta::CPAN

                        $stripObj->packingBox,
                        $stripObj->expandFlag,
                        $stripObj->fillFlag,
                        $spacing,
                    );
                }
            }
        }

        # Sensitise/desensitise widgets according to current conditions
        $self->restrictMenuBars();
        $self->restrictToolbars();

        # Any Gtk3::TextViews will now be using the colours of the most recently-created
        #   Gtk3::TextView, not the colours that we want them to use. Update colours for all pane
        #   objects (GA::Table::Pane) before the forthcoming call to ->winShowAll
        $self->updateColourScheme(undef, TRUE);

        # Make everything visible
        $self->winShowAll($self->_objClass . '->redrawWidgets');
        $axmud::CLIENT->desktopObj->updateWidgets($self->_objClass . '->redrawWidgets');

lib/Games/Axmud/Win/Internal.pm  view on Meta::CPAN


        # Update all 'internal' windows
        foreach my $winObj ($axmud::CLIENT->desktopObj->listGridWins()) {

            if (
                $winObj->winType eq 'main'
                || $winObj->winType eq 'protocol'
                || $winObj->winType eq 'custom'
            ) {
                # Sensitise/desensitise menu items in 'internal' windows, as appropriate
                $winObj->restrictMenuBars();
                $winObj->restrictToolbars();
                # Update the gauge box, if visible
                $winObj->updateGauges();

                # Sensitise or desensitise widgets, as appropriate
                $winObj->setWidgetsIfSession();
                # Update widgets, as appropriate
                $winObj->setWidgetsChangeSession();

                # Make any changes visible

lib/Games/Axmud/Win/Internal.pm  view on Meta::CPAN

        }

        if ($self->enabledFlag && $self->winType ne 'main' && $self->winWidget eq $self->winBox) {

            $self->winWidget->set_title($text);
        }

        return 1;
    }

    sub restrictMenuBars {

        # Called by GA::Obj::Desktop->restrictWidgets
        # Sensitise or desensitise the menu bar in this 'internal' window, depending on current
        #   conditions. (Don't do anything if this window doesn't use a strip object for a menu bar)
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments or if this window doesn't use a strip object for a menu

lib/Games/Axmud/Win/Internal.pm  view on Meta::CPAN


        # Local variables
        my (
            $stripObj, $openFlag, $setupFlag,
            @list, @sensitiseList, @desensitiseList,
        );

        # Check for improper arguments
        if (defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->restrictMenuBars', @_);
        }

        # Get the strip object
        $stripObj = $self->ivShow('firstStripHash', 'Games::Axmud::Strip::MenuBar');
        if (! $stripObj) {

            # Nothing to sensitise/desensitise
            return undef;
        }

        # Test whether this is a 'main' window with a visible session whose status is 'connected' or
        #   'offline' (for the sake of efficiency)
        if (
            $self->visibleSession

lib/Games/Axmud/Win/Internal.pm  view on Meta::CPAN

                    # 'Edit' column
                    'test_pattern',
                    # 'Help' column
                    'help', 'about', 'credits', 'license',
                );

                last OUTER;
            }
        }

        # Menu bar items that require a 'main' window with a visible session
        @list = (
            # 'World' column
            'reconnect', 'reconnect_offline',
            'xconnect', 'xconnect_offline',
            'quit_all',
            'exit_all',
            'stop_session',
            # 'File' column
            'test_file',
            'show_files', 'show_file_meta',

lib/Games/Axmud/Win/Internal.pm  view on Meta::CPAN

            # 'Plugins' column
            'load_plugin', 'show_plugin',
        );

        if (! $setupFlag && $self->visibleSession) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu bar items that require a 'main' window with a visible session whose status is
        #   'connected' or 'offline'
        @list = (
            # 'World' column
            'login',
            'quit', 'qquit',
            'exit', 'xxit',
            # 'File' column
            'load_all', 'load_file',
            'save_all', 'save', 'save_options',
            'import_files',

lib/Games/Axmud/Win/Internal.pm  view on Meta::CPAN

            # 'Axbasic' column
            'run_script', 'run_script_task',
        );

        if (! $setupFlag && $openFlag) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu bar items that require a 'main' window with a visible session whose status is
        #   'connected' or 'offline' and whose ->currentGuild is defined
        @list = (
            # 'Edit' column
            'edit_current_guild',
            # 'Interfaces' column
            'guild_triggers', 'guild_aliases', 'guild_macros', 'guild_timers', 'guild_hooks',
                'guild_cmds', 'guild_routes',
        );

        if (! $setupFlag && $openFlag && $self->visibleSession->currentGuild) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu bar items that require a 'main' window with a visible session whose status is
        #   'connected' or 'offline' and whose ->currentRace is defined
        @list = (
            # 'Edit' column
            'edit_current_race',
            # 'Interfaces' column
            'race_triggers', 'race_aliases', 'race_macros', 'race_timers', 'race_hooks',
                'race_cmds', 'race_routes',
        );

        if (! $setupFlag && $openFlag && $self->visibleSession->currentRace) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu bar items that require a 'main' window with a visible session whose status is
        #   'connected' or 'offline' and whose ->currentChar is defined
        @list = (
            # 'Edit' column
            'edit_current_char',
            # 'Interfaces' column
            'char_triggers', 'char_aliases', 'char_macros', 'char_timers', 'char_hooks',
                'char_cmds', 'char_routes',
        );

        if (! $setupFlag && $openFlag && $self->visibleSession->currentChar) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu bar items that require a 'main' window with a visible session whose status is
        #   'connected' or 'offline' and $stripObj->saveAllSessionsFlag set to FALSE
        @list = (
            # 'File' column
            'save_file',
        );

        if (! $setupFlag && $openFlag && ! $stripObj->saveAllSessionsFlag) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu bar items that require a 'main' window with a visible session whose status is
        #   'connected' or 'offline' and whose ->recordingPausedFlag is FALSE
        @list = (
            # 'Recordings' column
            'start_stop_recording',
        );

        if (! $setupFlag && $openFlag && ! $self->visibleSession->recordingPausedFlag) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu bar items that require a 'main' window with a visible session whose status is
        #   'connected' or 'offline' and whose ->recordingFlag is TRUE
        @list = (
            # 'Recordings' column
            'pause_recording',
        );

        if (! $setupFlag && $openFlag && $self->visibleSession->recordingFlag) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu bar items that require a 'main' window with a visible session whose status is
        #   'connected' or 'offline' and a Chat task
        @list = (
            # 'Tasks' column
            'edit_chat_task',
        );

        if (! $setupFlag && $openFlag && $self->visibleSession->chatTask) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu bar items that require a 'main' window with a visible session whose status is
        #   'connected' or 'offline' and a Channels task
        @list = (
            # 'Tasks' column
            'channels_task',
        );

        if (! $setupFlag && $openFlag && $self->visibleSession->channelsTask) {

            push (@sensitiseList, @list);
            push (@desensitiseList, 'channels_task_start');

        } else {

            push (@sensitiseList, 'channels_task_start');
            push (@desensitiseList, @list);
        }

        # Menu bar items that require a 'main' window with a visible session whose status is
        #   'connected' or 'offline' and a Compass task
        @list = (
            # 'Tasks' column
            'compass_task',
        );

        if (! $setupFlag && $openFlag && $self->visibleSession->compassTask) {

            push (@sensitiseList, @list);
            push (@desensitiseList, 'compass_task_start');

        } else {

            push (@sensitiseList, 'compass_task_start');
            push (@desensitiseList, @list);
        }

        # Menu bar items that require a 'main' window with a visible session whose status is
        #   'connected' or 'offline' and NO Condition task
        @list = (
            # 'Tasks' column
            'condition_task_start',
        );

        if (! $setupFlag && $openFlag && ! defined $self->visibleSession->conditionTask) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu bar items that require a 'main' window with a visible session whose status is
        #   'connected' or 'offline' and a Divert task
        @list = (
            # 'Tasks' column
            'divert_task',
        );

        if (! $setupFlag && $openFlag && $self->visibleSession->divertTask) {

            push (@sensitiseList, @list);
            push (@desensitiseList, 'divert_task_start');

        } else {

            push (@sensitiseList, 'divert_task_start');
            push (@desensitiseList, @list);
        }

        # Menu bar items that require a 'main' window with a visible session whose status is
        #   'connected' or 'offline' and an Inventory task
        @list = (
            # 'Tasks' column
            'inventory_task',
        );

        if (! $setupFlag && $openFlag && $self->visibleSession->inventoryTask) {

            push (@sensitiseList, @list);
            push (@desensitiseList, 'inventory_task_start');

        } else {

            push (@sensitiseList, 'inventory_task_start');
            push (@desensitiseList, @list);
        }

        # Menu bar items that require a 'main' window with a visible session whose status is
        #   'connected' or 'offline' and a Locator task
        @list = (
            # 'Tasks' column
            'locator_task',
        );

        if (! $setupFlag && $openFlag && $self->visibleSession->locatorTask) {

            push (@sensitiseList, @list);
            push (@desensitiseList, 'locator_task_start');

        } else {

            push (@sensitiseList, 'locator_task_start');
            push (@desensitiseList, @list);
        }

        # Menu bar items that require a 'main' window with a visible session whose status is
        #   'connected' or 'offline' and a Status task
        @list = (
            # 'Tasks' column
            'status_task',
        );

        if (! $setupFlag && $openFlag && $self->visibleSession->statusTask) {

            push (@sensitiseList, @list);
            push (@desensitiseList, 'status_task_start');

        } else {

            push (@sensitiseList, 'status_task_start');
            push (@desensitiseList, @list);
        }

        # Menu bar items that require a 'main' window with a visible session whose status is
        #   'connected' or 'offline' and a Watch task
        @list = (
            # 'Tasks' column
            'watch_task',
        );

        if (! $setupFlag && $openFlag && $self->visibleSession->watchTask) {

            push (@sensitiseList, @list);
            push (@desensitiseList, 'watch_task_start');

        } else {

            push (@sensitiseList, 'watch_task_start');
            push (@desensitiseList, @list);
        }

        # Menu bar items that require a require a 'main' window with a visible session whose status
        #   is 'connected' or 'offline' and GA::Session->recordingFlag
        @list = (
            # 'Recordings' column
            'pause_resume_recording',
            'recording_add_line', 'recording_add_break',
            'recording_set_insertion', 'recording_cancel_insertion',
            'recording_delete_line', 'recording_delete_multi', 'recording_delete_last',
        );

        if (! $setupFlag && $openFlag && $self->visibleSession->recordingFlag) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu bar items that require a require a 'main' window with a visible session whose status
        #   is 'connected' or 'offline', and either GA::Session->recordingFlag or ->recordingList
        @list = (
            # 'Recordings' column
            'show_recording', 'copy_recording',
        );

        if (
            ! $setupFlag
            && $openFlag
            && ($self->visibleSession->recordingFlag || $self->visibleSession->recordingList)
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu bar items that require GA::Client->browserCmd
        @list = (
            # 'Help' column
            'go_website',
        );

        if (! $setupFlag && $axmud::CLIENT->browserCmd) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Sensitise/desensitise menu bar items
        $stripObj->sensitiseWidgets(@sensitiseList);
        $stripObj->desensitiseWidgets(@desensitiseList);

        # All menu items added by plugins require a 'main' window with a visible session, and the
        #   plugin itself must be must be enabled
        foreach my $plugin ($stripObj->ivKeys('pluginMenuItemHash')) {

            my ($widget, $pluginObj);

            $widget = $stripObj->ivShow('pluginMenuItemHash', $plugin);
            $pluginObj = $axmud::CLIENT->ivShow('pluginHash', $plugin);

            if (! $setupFlag && $self->visibleSession && $pluginObj->enabledFlag) {
                $widget->set_sensitive(TRUE);
            } else {
                $widget->set_sensitive(FALSE);
            }
        }

        return 1;

lib/Games/Axmud/Win/Internal.pm  view on Meta::CPAN

        foreach my $otherStripObj (
            sort {$a->number <=> $b->number} ($self->ivValues('stripHash'))
        ) {
            if ($otherStripObj ne $stripObj) {

                $otherStripObj->notify_addStripObj($stripObj);
            }
        }

        # Sensitise/desensitise widgets according to current conditions
        $self->restrictMenuBars();
        $self->restrictToolbars();

        # Make everything visible
        $self->winShowAll($self->_objClass . '->addStripObj');
        $axmud::CLIENT->desktopObj->updateWidgets($self->_objClass . '->addStripObj');

        # Adding/removing widgets upsets the position of the scrollbar in each tab's textview.
        #   Make sure all the textviews are scrolled to the bottom
        $self->rescrollTextViews();

lib/Games/Axmud/Win/Internal.pm  view on Meta::CPAN

        foreach my $otherStripObj (
            sort {$a->number <=> $b->number} ($self->ivValues('stripHash'))
        ) {
            if ($otherStripObj ne $stripObj) {

                $otherStripObj->notify_removeStripObj($stripObj);
            }
        }

        # Sensitise/desensitise widgets according to current conditions
        $self->restrictMenuBars();
        $self->restrictToolbars();

        # Make everything visible
        $self->winShowAll($self->_objClass . '->removeStripObj');
        $axmud::CLIENT->desktopObj->updateWidgets($self->_objClass . '->removeStripObj');

        # Hack to resolve a Gtk3 issue, in which a white area appears at the bottom of textviews
        #   when the gauge strip object is removed (and possibly in similar situations)
        foreach my $tableObj ($self->tableStripObj->ivValues('tableObjHash')) {

lib/Games/Axmud/Win/Internal.pm  view on Meta::CPAN


        return 1;
    }

    sub addStrip {

        # Convenient shortcut to $self->addStripObj, which expects a package name like
        #   GA::Strip::GaugeBox as an argument
        #
        # This function accepts a string, which can be any of the following (case-insensitive):
        #   'menu' / 'menubar' / 'menu_bar'                 - adds a GA::Strip::MenuBar
        #   'tool' / 'toolbar' / 'tool_bar'                 - adds a GA::Strip::Toolbar
        #   'gauge' / 'gaugebox' / 'gauge_box'              - adds a GA::Strip::GaugeBox
        #   'entry'                                         - adds a GA::Strip::Entry
        #   'connect' / 'info' / 'connectinfo' / 'connect_info'
        #                                                   - adds a GA::Strip::ConnectInfo
        #
        # The string can also be a part of the package name itself. For example, if you create your
        #   own GA::Strip::MyObject (inheriting from GA::Strip::Custom), then this function expects
        #   the string 'MyObject' (case-sensitive)
        # NB This function is not able to check that the package actually exists, although Axmud's

lib/Games/Axmud/Win/Internal.pm  view on Meta::CPAN

            return $self->addStripObj($packageName, $index);
        }
    }

    sub removeStrip {

        # Convenient shortcut to $self->removeStripObj, which expects a package name like
        #   GA::Strip::GaugeBox as an argument
        #
        # This function accepts a string, which can be any of the following (case-insensitive):
        #   'menu' / 'menubar' / 'menu_bar'                 - adds a GA::Strip::MenuBar
        #   'tool' / 'toolbar' / 'tool_bar'                 - adds a GA::Strip::Toolbar
        #   'gauge' / 'gaugebox' / 'gauge_box'              - adds a GA::Strip::GaugeBox
        #   'entry'                                         - adds a GA::Strip::Entry
        #   'connect' / 'info' / 'connectinfo' / 'connect_info'
        #                                                   - adds a GA::Strip::ConnectInfo
        #
        # The string can also be a part of the package name itself. For example, if you create your
        #   own GA::Strip::MyObject (inheriting from GA::Strip::Custom), then this function expects
        #   the string 'MyObject' (case-sensitive)
        #

lib/Games/Axmud/Win/Internal.pm  view on Meta::CPAN

        ) {
            return undef
        }

        # Remove the Gtk3 widget that contains the whole strip
        $axmud::CLIENT->desktopObj->removeWidget($self->packingBox, $stripObj->packingBox);
        # Update IVs
        $stripObj->set_visibleFlag(FALSE);

        # Sensitise/desensitise widgets according to current conditions
        $self->restrictMenuBars();
        $self->restrictToolbars();

        # Make everything visible
        $self->winShowAll($self->_objClass . '->hideStripObj');
        $axmud::CLIENT->desktopObj->updateWidgets($self->_objClass . '->hideStripObj');

        # Hack to resolve a Gtk3 issue, in which a white area appears at the bottom of textviews
        #   when the gauge strip object is removed (and possibly in similar situations)
        foreach my $tableObj ($self->tableStripObj->ivValues('tableObjHash')) {

lib/Games/Axmud/Win/Internal.pm  view on Meta::CPAN


        if ($posn != 0) {

            $self->packingBox->reorder_child($stripObj->packingBox, $posn);
        }

        # Update IVs
        $stripObj->set_visibleFlag(TRUE);

        # Sensitise/desensitise widgets according to current conditions
        $self->restrictMenuBars();
        $self->restrictToolbars();

        # Make everything visible
        $self->winShowAll($self->_objClass . '->revealStripObj');
        $axmud::CLIENT->desktopObj->updateWidgets($self->_objClass . '->revealStripObj');

        # Adding/removing widgets upsets the position of the scrollbar in each tab's textview.
        #   Make sure all the textviews are scrolled to the bottom
        $self->rescrollTextViews();

lib/Games/Axmud/Win/Internal.pm  view on Meta::CPAN

            $stripObj->fillFlag,
            $spacing,
        );

        if ($posn != 0) {

            $self->packingBox->reorder_child($stripObj->packingBox, $posn);
        }

        # Sensitise/desensitise widgets according to current conditions
        $self->restrictMenuBars();
        $self->restrictToolbars();

        # Make everything visible
        $self->winShowAll($self->_objClass . '->replaceStripObj');
        $axmud::CLIENT->desktopObj->updateWidgets($self->_objClass . '->replaceStripObj');

        # Redraw any visible gauges, otherwise the gauge box will be visible, but the gauges
        #   themselves will have disappeared
        $gaugeStripObj = $self->ivShow('firstStripHash', 'Games::Axmud::Strip::GaugeBox');
        if ($gaugeStripObj && $gaugeStripObj->visibleFlag) {

lib/Games/Axmud/Win/Internal.pm  view on Meta::CPAN


        return 1;
    }

    sub getStrip {

        # Convenient method for getting the blessed reference of the earliest-created instance of a
        #   type of strip object
        #
        # This function accepts a string, which can be any of the following (case-insensitive):
        #   'menu' / 'menubar' / 'menu_bar'                 - converts to GA::Strip::MenuBar
        #   'tool' / 'toolbar' / 'tool_bar'                 - converts to GA::Strip::Toolbar
        #   'table'                                         - converts to GA::Strip::Table
        #   'gauge' / 'gaugebox' / 'gauge_box'              - converts to GA::Strip::GaugeBox
        #   'search' / 'searchbox' / 'search_box'           - converts to GA::Strip::SearchBox
        #   'entry'                                         - converts to GA::Strip::Entry
        #   'connect' / 'info' / 'connectinfo' / 'connect_info'
        #                                                   - converts to GA::Strip::ConnectInfo
        #
        # The string can also be a part of the package name itself. For example, if you create your
        #   own GA::Strip::MyObject (inheriting from GA::Strip::Custom), then this function expects

lib/Games/Axmud/Win/Internal.pm  view on Meta::CPAN

        }

        # Return the earliest-created instance of that strip object (return 'undef' if none exists)
        return $self->ivShow('firstStripHash', $packageName);
    }

    sub convertPackageName {

        # Called by $self->addStrip, ->getStrip and $self->removeStrip
        # Converts a simple string (e.g. 'menu' into the package name of a strip object (e.g.
        #   'Games::Axmud::Strip::MenuBar'
        #
        # This function accepts a string, which can be any of the following (case-insensitive):
        #   'menu' / 'menubar' / 'menu_bar'                 - converts to GA::Strip::MenuBar
        #   'tool' / 'toolbar' / 'tool_bar'                 - converts to GA::Strip::Toolbar
        #   'table'                                         - converts to GA::Strip::Table
        #   'gauge' / 'gaugebox' / 'gauge_box'              - converts to GA::Strip::GaugeBox
        #   'search' / 'searchbox' / 'search_box'           - converts to GA::Strip::SearchBox
        #   'entry'                                         - converts to GA::Strip::Entry
        #   'connect' / 'info' / 'connectinfo' / 'connect_info'
        #                                                   - converts to GA::Strip::ConnectInfo
        #
        # The string can also be a part of the package name itself. For example, if you create your
        #   own GA::Strip::MyObject (inheriting from GA::Strip::Custom), then this function expects

lib/Games/Axmud/Win/Internal.pm  view on Meta::CPAN


        # Check for improper arguments
        if (! defined $string || defined $check) {

             return $axmud::CLIENT->writeImproper($self->_objClass . '->convertPackageName', @_);
        }

        if (
            lc($string) eq 'menu' || lc($string) eq 'menubar' || lc($string) eq 'menu_bar'
        ) {
            $packageName = 'Games::Axmud::Strip::MenuBar';

        } elsif (
            lc($string) eq 'tool' || lc($string) eq 'toolbar' || lc($string) eq 'tool_bar'
        ) {
            $packageName = 'Games::Axmud::Strip::Toolbar';

        } elsif (
            lc($string) eq 'gauge' || lc($string) eq 'gaugebox' || lc($string) eq 'gauge_box'
        ) {
            $packageName = 'Games::Axmud::Strip::GaugeBox';

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

            # Hash in the form
            #   toolbarRoomFlagHash{room_flag} = undef
            toolbarRoomFlagHash         => {},
            # When a colour button in the quick painting button set it toggled, the corresponding
            #   room flag is stored here
            # When this IV is defined, clicking a room toggles the room flag in that room. If
            #   multiple rooms are selected, and one of the selected rooms was the clicked one,
            #   the room flag is toggled in all of them
            toolbarQuickPaintColour     => undef,

            # Menu bar/toolbar items which will be sensitised or desensitised, depending on the
            #   context. Hash in the form
            #       $menuToolItemHash{'item_name'} = Gtk3_widget
            # ...where:
            #   'item_name' is a descriptive scalar, e.g. 'move_up_level'
            #   'Gtk3_widget' is the Gtk3::MenuItem or toolbar widget, typically Gtk3::ToolButton or
            #       Gtk3::RadioToolButton
            # NB Entries in this hash continue to exist, after the widgets are no longer visible.
            #   Doesn't matter, because there are a limited number of 'item_name' scalars, and so
            #   a limited size to the hash (and referencing no-longer visible widgets, for example
            #   to sensitise/desensitise them, doesn't have any ill effects)
            menuToolItemHash            => {},

            # A horizontal pane, dividing the treeview on the left from everything else on the right
            hPaned                      => undef,

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

            ],
            # A subset of these magnifications, used as menu items
            constShortMagnifyList       => [
                0.5, 0.8, 1, 1.2, 1.5, 1.75, 2
            ],
            # When some menu items are selected (e.g. View > Room filters > Release markers filter),
            #   a call is made to this session's GA::Obj::WorldModel, which in turn calls every
            #   Automapper window using the model, in order to update its menu. When this happens,
            #   the following flag is set to TRUE, so that updating the menu item doesn't cause
            #   further calls to GA::Obj::WorldModel
            ignoreMenuUpdateFlag        => FALSE,

            # IVs used during a drag operation
            # Flag set to TRUE during drag mode (set from the menu or the toolbar). Normally, it's
            #   necessary to hold down the Alt-Gr key to drag canvas objects; when drag mode is on,
            #   clicks on canvas objects are treated as the start of a drag, rather than a
            #   select/unselect operation)
            # NB During a drag operation initiated with the Alt-Gr key, ->dragModeFlag's value
            #   doesn't change
            dragModeFlag                => FALSE,
            # Flag set to TRUE when a dragging operation starts

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        }

        # Create a packing box
        my $packingBox = Gtk3::VBox->new(FALSE, 0);
        $self->winBox->add($packingBox);
        $packingBox->set_border_width(0);
        # Update IVs immediately
        $self->ivPoke('packingBox', $packingBox);

        # Create a menu (if allowed)
        if ($self->worldModelObj->showMenuBarFlag) {

            $menuBar = $self->enableMenu();
            if ($menuBar) {

                # Pack the widget
                $packingBox->pack_start($menuBar, FALSE, FALSE, 0);
            }
        }

        # Create toolbar(s) at the top of the window (if allowed)
        if ($self->worldModelObj->showToolbarFlag) {

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


        return 1;
    }

    sub redrawWidgets {

        # Can be called by any function
        # Redraws some or all of the menu bar, toolbar(s), treeview and canvas
        # The widgets redrawn are specified by the calling function, but are not redrawn if the
        #   right flags aren't set (e.g. the menu bar isn't redrawn if
        #   GA::Obj::WorldModel->showMenuBarFlag isn't set)
        #
        # Expected arguments
        #   @widgetList - A list of widget names. One or all of the following strings, in any order:
        #                   'menu_bar', 'toolbar', 'treeview', 'canvas'
        #
        # Return values
        #   'undef' on improper arguments or if any of the widgets in @widgetList are unrecognised
        #   1 otherwise

        my ($self, @widgetList) = @_;

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

                );
            }

            if ($self->canvasFrame) {

                $axmud::CLIENT->desktopObj->removeWidget($self->packingBox, $self->canvasFrame);
            }
        }

        # Redraw the menu bar, if specified (and if allowed)
        if ($self->worldModelObj->showMenuBarFlag) {

            if ($widgetHash{'menu_bar'}) {

                $self->resetMenuBarIVs();

                my $menuBar = $self->enableMenu();
                if ($menuBar) {

                    # Pack the new widget
                    $self->packingBox->pack_start($menuBar,FALSE,FALSE,0);

                } else {

                    # After the error, stop trying to draw menu bars
                    $self->worldModelObj->set_showMenuBarFlag(FALSE);
                }

            # Otherwise, repack the old menu bar
            } elsif ($self->menuBar) {

                $self->packingBox->pack_start($self->menuBar,FALSE,FALSE,0);
            }
        }

        # Redraw the toolbar(s), if specified (and if allowed)

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


                } else {

                    # Pack the frame directly into the packing box
                    $self->packingBox->pack_start($self->canvasFrame, TRUE, TRUE, 0);
                }
            }
        }

        # Now, for each widget that is no longer drawn, set default IVs
        if (! $self->worldModelObj->showMenuBarFlag) {

            $self->resetMenuBarIVs();
        }

        if (! $self->worldModelObj->showToolbarFlag) {

            $self->resetToolbarIVs();
        }

        if (! $self->worldModelObj->showTreeViewFlag || ! $self->worldModelObj->showCanvasFlag) {

            $self->ivUndef('hPaned');

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


               $self->hideTooltips();
            }
        });

        return 1;
    }

    # Other functions

    sub resetMenuBarIVs {

        # Called by $self->redrawWidgets at certain points, to reset the IVs storing details about
        #   the menu bar back to their defaults
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments
        #   1 otherwise

        my ($self, $check) = @_;

        # Check for improper arguments
        if (defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->resetMenuBarIVs', @_);
        }

        $self->ivUndef('menuBar');
        $self->ivEmpty('menuToolItemHash');

        return 1;
    }

    sub resetToolbarIVs {

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        $self->ivUndef('canvasHAdjustment');
        $self->ivUndef('canvasVAdjustment');

        $self->ivUndef('canvasTooltipObj');
        $self->ivUndef('canvasTooltipObjType');
        $self->ivUndef('canvasTooltipFlag');

        return 1;
    }

    # Menu widget methods

    sub enableMenu {

        # Called by $self->drawWidgets
        # Sets up the Automapper window's Gtk3::MenuBar widget
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments or if the widget can't be created
        #   Otherwise returns the Gtk3::MenuBar created

        my ($self, $check) = @_;

        # Check for improper arguments
        if (defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->enableMenu', @_);
        }

        # Create the menu bar
        my $menuBar = Gtk3::MenuBar->new();
        if (! $menuBar) {

            return undef;
        }

        # 'File' column
        my $column_file = $self->enableFileColumn();
        my $item_file = Gtk3::MenuItem->new('_File');
        $item_file->set_submenu($column_file);
        $menuBar->append($item_file);

        # 'Edit' column
        my $column_edit = $self->enableEditColumn();
        my $item_edit = Gtk3::MenuItem->new('_Edit');
        $item_edit->set_submenu($column_edit);
        $menuBar->append($item_edit);

        # 'View' column
        my $column_view = $self->enableViewColumn();
        my $item_view = Gtk3::MenuItem->new('_View');
        $item_view->set_submenu($column_view);
        $menuBar->append($item_view);

        # 'Mode' column
        my $column_mode = $self->enableModeColumn();
        my $item_mode = Gtk3::MenuItem->new('_Mode');
        $item_mode->set_submenu($column_mode);
        $menuBar->append($item_mode);

        # 'Regions' column
        my $column_regions = $self->enableRegionsColumn();
        my $item_regions = Gtk3::MenuItem->new('_Regions');
        $item_regions->set_submenu($column_regions);
        $menuBar->append($item_regions);

        # 'Rooms' column
        my $column_rooms = $self->enableRoomsColumn();
        my $item_rooms = Gtk3::MenuItem->new('R_ooms');
        $item_rooms->set_submenu($column_rooms);
        $menuBar->append($item_rooms);

        # 'Exits' column
        my $column_exits = $self->enableExitsColumn();
        my $item_exits = Gtk3::MenuItem->new('E_xits');
        $item_exits->set_submenu($column_exits);
        $menuBar->append($item_exits);

        # 'Labels' column
        my $column_labels = $self->enableLabelsColumn();
        my $item_labels = Gtk3::MenuItem->new('_Labels');
        $item_labels->set_submenu($column_labels);
        $menuBar->append($item_labels);

        # Store the widget
        $self->ivPoke('menuBar', $menuBar);

        # Sensitise/desensitise menu bar/toolbar items, depending on current conditions
        $self->restrictWidgets();

        # Setup complete
        return $menuBar;
    }

    sub enableFileColumn {

        # Called by $self->enableMenu
        # Sets up the 'File' column of the Automapper window's menu bar
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments or if the widget can't be created
        #   Otherwise returns the Gtk3::Menu created

        my ($self, $check) = @_;

        # Check for improper arguments
        if (defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->enableFileColumn', @_);
        }

        # Set up column
        my $column_file = Gtk3::Menu->new();
        if (! $column_file) {

            return undef;
        }

        my $item_loadModel = Gtk3::MenuItem->new('_Load world model');
        $item_loadModel->signal_connect('activate' => sub {

            # $self->winReset will be called by $self->set_worldModelObj when the ';load' command
            #   has finished its work
            # NB Force pseudo command mode 'win_error' in this menu column (success system messages
            #   in the 'main' window; errors/improper arguments messages shown in a 'dialogue'
            #   window)
            $self->session->pseudoCmd('load -m', 'win_error');
        });
        $column_file->append($item_loadModel);

        my $item_loadAll = Gtk3::ImageMenuItem->new('L_oad all files');
        $item_loadAll->signal_connect('activate' => sub {

            # The ';load' command will  $self->winReset when finished

            $self->session->pseudoCmd('load', 'win_error');
        });
        my $img_loadAll = Gtk3::Image->new_from_stock('gtk-open', 'menu');
        $item_loadAll->set_image($img_loadAll);
        $column_file->append($item_loadAll);

        $column_file->append(Gtk3::SeparatorMenuItem->new());   # Separator

        my $item_saveModel = Gtk3::MenuItem->new('_Save world model');
        $item_saveModel->signal_connect('activate' => sub {

            # Do a forced save. The ';save' command sets $self->freeClickMode back to 'default'
            $self->session->pseudoCmd('save -m -f', 'win_error');
        });
        $column_file->append($item_saveModel);

        my $item_saveAll = Gtk3::ImageMenuItem->new('S_ave all files');
        $item_saveAll->signal_connect('activate' => sub {

            # Do a forced save. The ';save' command sets $self->freeClickMode back to 'default'
            $self->session->pseudoCmd('save -f', 'win_error');
        });
        my $img_saveAll = Gtk3::Image->new_from_stock('gtk-save', 'menu');
        $item_saveAll->set_image($img_saveAll);
        $column_file->append($item_saveAll);

        $column_file->append(Gtk3::SeparatorMenuItem->new());   # Separator

        my $item_importModel = Gtk3::MenuItem->new('_Import/load world model...');
        $item_importModel->signal_connect('activate' => sub {

            $self->importModelCallback();
        });
        $column_file->append($item_importModel);

        my $item_exportModel = Gtk3::MenuItem->new('Save/_export world model...');
        $item_exportModel->signal_connect('activate' => sub {

            $self->exportModelCallback();
        });
        $column_file->append($item_exportModel);

        $column_file->append(Gtk3::SeparatorMenuItem->new());   # Separator

        my $item_mergeModel = Gtk3::MenuItem->new('_Merge world models...');
        $item_mergeModel->signal_connect('activate' => sub {

            $self->session->pseudoCmd('mergemodel')
        });
        $column_file->append($item_mergeModel);

        $column_file->append(Gtk3::SeparatorMenuItem->new());   # Separator

        my $item_closeWindow = Gtk3::ImageMenuItem->new('_Close window');
        $item_closeWindow->signal_connect('activate' => sub {

            $self->winDestroy();
        });
        my $img_closeWindow = Gtk3::Image->new_from_stock('gtk-quit', 'menu');
        $item_closeWindow->set_image($img_closeWindow);
        $column_file->append($item_closeWindow);

        # Setup complete
        return $column_file;
    }

    sub enableEditColumn {

        # Called by $self->enableMenu
        # Sets up the 'Edit' column of the Automapper window's menu bar
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments or if the widget can't be created
        #   Otherwise returns the Gtk3::Menu created

        my ($self, $check) = @_;

        # Local variables
        my $winObj;

        # Check for improper arguments
        if (defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->enableEditColumn', @_);
        }

        # Set up column
        my $column_edit = Gtk3::Menu->new();
        if (! $column_edit) {

            return undef;
        }

            # 'Select' submenu
            my $subMenu_select = Gtk3::Menu->new();

                # 'Select rooms' sub-submenu
                my $subSubMenu_selectRooms = Gtk3::Menu->new();

                my $item_selectNoTitle = Gtk3::MenuItem->new('Rooms with no _titles');
                $item_selectNoTitle->signal_connect('activate' => sub {

                    $self->selectRoomCallback('no_title');
                });
                $subSubMenu_selectRooms->append($item_selectNoTitle);

                my $item_selectNoDescrip = Gtk3::MenuItem->new('Rooms with no _descriptions');
                $item_selectNoDescrip->signal_connect('activate' => sub {

                    $self->selectRoomCallback('no_descrip');
                });
                $subSubMenu_selectRooms->append($item_selectNoDescrip);

                my $item_selectNoTitleDescrip = Gtk3::MenuItem->new('Rooms with _neither');
                $item_selectNoTitleDescrip->signal_connect('activate' => sub {

                    $self->selectRoomCallback('no_title_descrip');
                });
                $subSubMenu_selectRooms->append($item_selectNoTitleDescrip);

                my $item_selectTitleDescrip = Gtk3::MenuItem->new('Rooms with _both');
                $item_selectTitleDescrip->signal_connect('activate' => sub {

                    $self->selectRoomCallback('title_descrip');
                });
                $subSubMenu_selectRooms->append($item_selectTitleDescrip);

                $subSubMenu_selectRooms->append(Gtk3::SeparatorMenuItem->new());   # Separator

                my $item_selectNoVisitChar = Gtk3::MenuItem->new('Rooms not visited by _character');
                $item_selectNoVisitChar->signal_connect('activate' => sub {

                    $self->selectRoomCallback('no_visit_char');
                });
                $subSubMenu_selectRooms->append($item_selectNoVisitChar);

                my $item_selectNoVisitAllChar = Gtk3::MenuItem->new('Rooms not visited by _anyone');
                $item_selectNoVisitAllChar->signal_connect('activate' => sub {

                    $self->selectRoomCallback('no_visit_all');
                });
                $subSubMenu_selectRooms->append($item_selectNoVisitAllChar);

                my $item_selectVisitChar = Gtk3::MenuItem->new('Rooms visited by c_haracter');
                $item_selectVisitChar->signal_connect('activate' => sub {

                    $self->selectRoomCallback('visit_char');
                });
                $subSubMenu_selectRooms->append($item_selectVisitChar);

                my $item_selectVisitAllChar = Gtk3::MenuItem->new('Rooms visited by an_yone');
                $item_selectVisitAllChar->signal_connect('activate' => sub {

                    $self->selectRoomCallback('visit_all');
                });
                $subSubMenu_selectRooms->append($item_selectVisitAllChar);

                $subSubMenu_selectRooms->append(Gtk3::SeparatorMenuItem->new());   # Separator

                my $item_selectCheckable = Gtk3::MenuItem->new('Rooms with checkable d_irections');
                $item_selectCheckable->signal_connect('activate' => sub {

                    $self->selectRoomCallback('checkable');
                });
                $subSubMenu_selectRooms->append($item_selectCheckable);

            my $item_selectRooms = Gtk3::MenuItem->new('Select _rooms');
            $item_selectRooms->set_submenu($subSubMenu_selectRooms);
            $subMenu_select->append($item_selectRooms);

                # 'Select exits' sub-submenu
                my $subSubMenu_selectExits = Gtk3::Menu->new();

                my $item_selectInRooms = Gtk3::MenuItem->new('Exits in selected _rooms');
                $item_selectInRooms->signal_connect('activate' => sub {

                    $self->selectExitTypeCallback('in_rooms');
                });
                $subSubMenu_selectExits->append($item_selectInRooms);

                $subSubMenu_selectExits->append(Gtk3::SeparatorMenuItem->new());    # Separator

                my $item_selectUnallocated = Gtk3::MenuItem->new('_Unallocated exits');
                $item_selectUnallocated->signal_connect('activate' => sub {

                    $self->selectExitTypeCallback('unallocated');
                });
                $subSubMenu_selectExits->append($item_selectUnallocated);

                my $item_selectUnallocatable = Gtk3::MenuItem->new('U_nallocatable exits');
                $item_selectUnallocatable->signal_connect('activate' => sub {

                    $self->selectExitTypeCallback('unallocatable');
                });
                $subSubMenu_selectExits->append($item_selectUnallocatable);

                my $item_selectUncertain = Gtk3::MenuItem->new('Un_certain exits');
                $item_selectUncertain->signal_connect('activate' => sub {

                    $self->selectExitTypeCallback('uncertain');
                });
                $subSubMenu_selectExits->append($item_selectUncertain);

                my $item_selectIncomplete = Gtk3::MenuItem->new('_Incomplete exits');
                $item_selectIncomplete->signal_connect('activate' => sub {

                    $self->selectExitTypeCallback('incomplete');
                });
                $subSubMenu_selectExits->append($item_selectIncomplete);

                my $item_selectAllAbove = Gtk3::MenuItem->new('_All of the above');
                $item_selectAllAbove->signal_connect('activate' => sub {

                    $self->selectExitTypeCallback('all_above');
                });
                $subSubMenu_selectExits->append($item_selectAllAbove);

                $subSubMenu_selectExits->append(Gtk3::SeparatorMenuItem->new());    # Separator

                my $item_selectImpassable = Gtk3::MenuItem->new('I_mpassable exits');
                $item_selectImpassable->signal_connect('activate' => sub {

                    $self->selectExitTypeCallback('impass');
                });
                $subSubMenu_selectExits->append($item_selectImpassable);

                my $item_selectMystery = Gtk3::MenuItem->new('M_ystery exits');
                $item_selectMystery->signal_connect('activate' => sub {

                    $self->selectExitTypeCallback('mystery');
                });
                $subSubMenu_selectExits->append($item_selectMystery);

                $subSubMenu_selectExits->append(Gtk3::SeparatorMenuItem->new());    # Separator

                my $item_selectNonSuper = Gtk3::MenuItem->new('R_egion exits');
                $item_selectNonSuper->signal_connect('activate' => sub {

                    $self->selectExitTypeCallback('region');
                });
                $subSubMenu_selectExits->append($item_selectNonSuper);

                my $item_selectSuper = Gtk3::MenuItem->new('_Super-region exits');
                $item_selectSuper->signal_connect('activate' => sub {

                    $self->selectExitTypeCallback('super');
                });
                $subSubMenu_selectExits->append($item_selectSuper);

            my $item_selectExits = Gtk3::MenuItem->new('Select _exits');
            $item_selectExits->set_submenu($subSubMenu_selectExits);
            $subMenu_select->append($item_selectExits);

            $subMenu_select->append(Gtk3::SeparatorMenuItem->new());   # Separator

                # 'Select in region' sub-submenu
                my $subSubMenu_selectRegion = Gtk3::Menu->new();

                my $item_selectRegionRoom = Gtk3::MenuItem->new('Every _room');
                $item_selectRegionRoom->signal_connect('activate' => sub {

                    $self->selectInRegionCallback('room');
                });
                $subSubMenu_selectRegion->append($item_selectRegionRoom);

                my $item_selectRegionExit = Gtk3::MenuItem->new('Every _exit');
                $item_selectRegionExit->signal_connect('activate' => sub {

                    $self->selectInRegionCallback('exit');
                });
                $subSubMenu_selectRegion->append($item_selectRegionExit);

                my $item_selectRegionRoomTag = Gtk3::MenuItem->new('Every room _tag');
                $item_selectRegionRoomTag->signal_connect('activate' => sub {

                    $self->selectInRegionCallback('room_tag');
                });
                $subSubMenu_selectRegion->append($item_selectRegionRoomTag);

                my $item_selectRegionRoomGuild = Gtk3::MenuItem->new('Every room _guild');
                $item_selectRegionRoomGuild->signal_connect('activate' => sub {

                    $self->selectInRegionCallback('room_guild');
                });
                $subSubMenu_selectRegion->append($item_selectRegionRoomGuild);

                my $item_selectRegionLabel = Gtk3::MenuItem->new('Every _label');
                $item_selectRegionLabel->signal_connect('activate' => sub {

                    $self->selectInRegionCallback('label');
                });
                $subSubMenu_selectRegion->append($item_selectRegionLabel);

                $subSubMenu_selectRegion->append(Gtk3::SeparatorMenuItem->new());   # Separator

                my $item_selectRegionAbove = Gtk3::MenuItem->new('_All of the above');
                $item_selectRegionAbove->signal_connect('activate' => sub {

                    $self->selectInRegionCallback();
                });
                $subSubMenu_selectRegion->append($item_selectRegionAbove);

            my $item_selectRegion = Gtk3::MenuItem->new('Select in re_gion');
            $item_selectRegion->set_submenu($subSubMenu_selectRegion);
            $subMenu_select->append($item_selectRegion);

                # 'Select in map' sub-submenu
                my $subSubMenu_selectMap = Gtk3::Menu->new();

                my $item_selectMapRoom = Gtk3::MenuItem->new('Every _room');
                $item_selectMapRoom->signal_connect('activate' => sub {

                    $self->selectInMapCallback('room');
                });
                $subSubMenu_selectMap->append($item_selectMapRoom);

                my $item_selectMapExit = Gtk3::MenuItem->new('Every _exit');
                $item_selectMapExit->signal_connect('activate' => sub {

                    $self->selectInMapCallback('exit');
                });
                $subSubMenu_selectMap->append($item_selectMapExit);

                my $item_selectMapRoomTag = Gtk3::MenuItem->new('Every room _tag');
                $item_selectMapRoomTag->signal_connect('activate' => sub {

                    $self->selectInMapCallback('room_tag');
                });
                $subSubMenu_selectMap->append($item_selectMapRoomTag);

                my $item_selectMapRoomGuild = Gtk3::MenuItem->new('Every room _guild');
                $item_selectMapRoomGuild->signal_connect('activate' => sub {

                    $self->selectInMapCallback('room_guild');
                });
                $subSubMenu_selectMap->append($item_selectMapRoomGuild);

                my $item_selectMapLabel = Gtk3::MenuItem->new('Every _label');
                $item_selectMapLabel->signal_connect('activate' => sub {

                    $self->selectInMapCallback('label');
                });
                $subSubMenu_selectMap->append($item_selectMapLabel);

                $subSubMenu_selectMap->append(Gtk3::SeparatorMenuItem->new());   # Separator

                my $item_selectMapAbove = Gtk3::MenuItem->new('_All of the above');
                $item_selectMapAbove->signal_connect('activate' => sub {

                    $self->selectInMapCallback();
                });
                $subSubMenu_selectMap->append($item_selectMapAbove);

            my $item_selectMap = Gtk3::MenuItem->new('Select in _map');
            $item_selectMap->set_submenu($subSubMenu_selectMap);
            $subMenu_select->append($item_selectMap);

        my $item_select = Gtk3::MenuItem->new('_Select');
        $item_select->set_submenu($subMenu_select);
        $column_edit->append($item_select);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'select', $item_select);

            # 'Selected items' submenu
            my $subMenu_selectedObjs = Gtk3::Menu->new();

            my $item_identifyRoom = Gtk3::MenuItem->new('Identify _room(s)');
            $item_identifyRoom->signal_connect('activate' => sub {

                $self->identifyRoomsCallback();
            });
            $subMenu_selectedObjs->append($item_identifyRoom);
            # (Requires $self->currentRegionmap and EITHER $self->selectedRoom or
            #   $self->selectedRoomHash or $self->mapObj->currentRoom)
            $self->ivAdd('menuToolItemHash', 'identify_room', $item_identifyRoom);

            my $item_identifyExit = Gtk3::MenuItem->new('Identify _exit(s)');
            $item_identifyExit->signal_connect('activate' => sub {

                $self->identifyExitsCallback();
            });
            $subMenu_selectedObjs->append($item_identifyExit);
            # (Requires $self->currentRegionmap & either $self->selectedExit or
            #   $self->selectedExitHash)
            $self->ivAdd('menuToolItemHash', 'identify_exit', $item_identifyExit);

        my $item_selectedObjs = Gtk3::MenuItem->new('_Identify selected items');
        $item_selectedObjs->set_submenu($subMenu_selectedObjs);
        $column_edit->append($item_selectedObjs);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'selected_objs', $item_selectedObjs);

        my $item_unselectAll = Gtk3::MenuItem->new('_Unselect all');
        $item_unselectAll->signal_connect('activate' => sub {

            $self->setSelectedObj();
        });
        $column_edit->append($item_unselectAll);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'unselect_all', $item_unselectAll);

        $column_edit->append(Gtk3::SeparatorMenuItem->new());   # Separator

            # 'Search' submenu
            my $subMenu_search = Gtk3::Menu->new();

            my $item_searchModel = Gtk3::MenuItem->new('Search world _model...');
            $item_searchModel->signal_connect('activate' => sub {

                # Open a 'pref' window to conduct the search
                $self->createFreeWin(
                    'Games::Axmud::PrefWin::Search',
                    $self,
                    $self->session,
                    'World model search',
                );
            });
            $subMenu_search->append($item_searchModel);

            $subMenu_search->append(Gtk3::SeparatorMenuItem->new());   # Separator

            my $item_findRoom = Gtk3::MenuItem->new('Find _room...');
            $item_findRoom->signal_connect('activate' => sub {

                $self->findRoomCallback();
            });
            $subMenu_search->append($item_findRoom);

            my $item_findExit = Gtk3::MenuItem->new('Find _exit...');
            $item_findExit->signal_connect('activate' => sub {

                $self->findExitCallback();
            });
            $subMenu_search->append($item_findExit);

        my $item_search = Gtk3::ImageMenuItem->new('S_earch');
        my $img_search = Gtk3::Image->new_from_stock('gtk-find', 'menu');
        $item_search->set_image($img_search);
        $item_search->set_submenu($subMenu_search);
        $column_edit->append($item_search);

            # 'Generate reports' submenu
            my $subMenu_reports = Gtk3::Menu->new();

            my $item_showSummary = Gtk3::MenuItem->new('_Show general report');
            $item_showSummary->signal_connect('activate' => sub {

                # (Don't use $self->pseudoCmdMode - we want to see the footer messages)
                $self->session->pseudoCmd('modelreport', 'show_all');
            });
            $subMenu_reports->append($item_showSummary);

            my $item_showCurrentRegion = Gtk3::MenuItem->new('S_how current region');
            $item_showCurrentRegion->signal_connect('activate' => sub {

                $self->session->pseudoCmd(
                    'modelreport -r <' . $self->currentRegionmap->name . '>',
                    'show_all',
                );
            });
            $subMenu_reports->append($item_showCurrentRegion);
            # (Requires $self->currentRegionmap)
            $self->ivAdd('menuToolItemHash', 'report_region', $item_showCurrentRegion);

            $subMenu_reports->append(Gtk3::SeparatorMenuItem->new());  # Separator

                # 'Character visits' sub-submenu
                my $subSubMenu_visits = Gtk3::Menu->new();

                my $item_visits1 = Gtk3::MenuItem->new('_All regions/characters');
                $item_visits1->signal_connect('activate' => sub {

                    $self->session->pseudoCmd('modelreport -v', 'show_all');
                });
                $subSubMenu_visits->append($item_visits1);

                my $item_visits2 = Gtk3::MenuItem->new('Current _region');
                $item_visits2->signal_connect('activate' => sub {

                    $self->session->pseudoCmd(
                        'modelreport -v -r <' . $self->currentRegionmap->name . '>',
                        'show_all',
                    );
                });
                $subSubMenu_visits->append($item_visits2);
                # (Requires $self->currentRegionmap)
                $self->ivAdd('menuToolItemHash', 'report_visits_2', $item_visits2);

                my $item_visits3 = Gtk3::MenuItem->new('Current _character');
                $item_visits3->signal_connect('activate' => sub {

                    $self->session->pseudoCmd(
                        'modelreport -v -c <' . $self->session->currentChar->name . '>',
                        'show_all',
                    );
                });
                $subSubMenu_visits->append($item_visits3);
                # (Requires current character profile)
                $self->ivAdd('menuToolItemHash', 'report_visits_3', $item_visits3);

                my $item_visits4 = Gtk3::MenuItem->new('C_urrent region/character');
                $item_visits4->signal_connect('activate' => sub {

                    $self->session->pseudoCmd(
                        'modelreport -v -r <' . $self->currentRegionmap->name . '>' . ' -c <'
                        . $self->session->currentChar->name . '>',
                        'show_all',
                    );
                });
                $subSubMenu_visits->append($item_visits4);
                # (Requires $self->currentRegionmap and current character profile)
                $self->ivAdd('menuToolItemHash', 'report_visits_4', $item_visits4);

            my $item_visits = Gtk3::MenuItem->new('_Character visits');
            $item_visits->set_submenu($subSubMenu_visits);
            $subMenu_reports->append($item_visits);

                # 'Room guilds' sub-submenu
                my $subSubMenu_guilds = Gtk3::Menu->new();

                my $item_guilds1 = Gtk3::MenuItem->new('_All regions/guilds');
                $item_guilds1->signal_connect('activate' => sub {

                    $self->session->pseudoCmd('modelreport -g', 'show_all');
                });
                $subSubMenu_guilds->append($item_guilds1);

                my $item_guilds2 = Gtk3::MenuItem->new('Current _region');
                $item_guilds2->signal_connect('activate' => sub {

                    $self->session->pseudoCmd(
                        'modelreport -g -r <' . $self->currentRegionmap->name . '>',
                        'show_all',
                    );
                });
                $subSubMenu_guilds->append($item_guilds2);
                # (Requires $self->currentRegionmap)
                $self->ivAdd('menuToolItemHash', 'report_guilds_2', $item_guilds2);

                my $item_guilds3 = Gtk3::MenuItem->new('Current _guild');
                $item_guilds3->signal_connect('activate' => sub {

                    $self->session->pseudoCmd(
                        'modelreport -g -n <' . $self->session->currentGuild->name . '>',
                        'show_all',
                    );
                });
                $subSubMenu_guilds->append($item_guilds3);
                # (Requires current guild profile)
                $self->ivAdd('menuToolItemHash', 'report_guilds_3', $item_guilds3);

                my $item_guilds4 = Gtk3::MenuItem->new('C_urrent region/guild');
                $item_guilds4->signal_connect('activate' => sub {

                    $self->session->pseudoCmd(
                        'modelreport -g -r <' . $self->currentRegionmap->name . '>' . ' -n <'
                        . $self->session->currentGuild->name . '>',
                        'show_all',
                    );
                });
                $subSubMenu_guilds->append($item_guilds4);
                # (Requires $self->currentRegionmap and current guild profile)
                $self->ivAdd('menuToolItemHash', 'report_guilds_4', $item_guilds4);

            my $item_guilds = Gtk3::MenuItem->new('Room _guilds');
            $item_guilds->set_submenu($subSubMenu_guilds);
            $subMenu_reports->append($item_guilds);

                # 'Room flags' sub-submenu
                my $subSubMenu_roomFlags = Gtk3::Menu->new();

                my $item_roomFlags1 = Gtk3::MenuItem->new('_All regions/flags');
                $item_roomFlags1->signal_connect('activate' => sub {

                    $self->session->pseudoCmd('modelreport -f', 'show_all');
                });
                $subSubMenu_roomFlags->append($item_roomFlags1);

                my $item_roomFlags2 = Gtk3::MenuItem->new('Current _region');
                $item_roomFlags2->signal_connect('activate' => sub {

                    $self->session->pseudoCmd(
                        'modelreport -f -r <' . $self->currentRegionmap->name . '>',
                        'show_all',
                    );
                });
                $subSubMenu_roomFlags->append($item_roomFlags2);
                # (Requires $self->currentRegionmap)
                $self->ivAdd('menuToolItemHash', 'report_flags_2', $item_roomFlags2);

                my $item_roomFlags3 = Gtk3::MenuItem->new('_Specify flag...');
                $item_roomFlags3->signal_connect('activate' => sub {

                    my (
                        $choice,
                        @list,
                    );

                    @list = $self->worldModelObj->roomFlagOrderedList;

                    $choice = $self->showComboDialogue(

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

                    );

                    if ($choice) {

                        $self->session->pseudoCmd(
                            'modelreport -f -l <' . $choice . '>',
                            'show_all',
                        );
                    }
                });
                $subSubMenu_roomFlags->append($item_roomFlags3);

                my $item_roomFlags4 = Gtk3::MenuItem->new('C_urrent region/specify flag...');
                $item_roomFlags4->signal_connect('activate' => sub {

                    my (
                        $choice,
                        @list,
                    );

                    @list = $self->worldModelObj->roomFlagOrderedList;

                    $choice = $self->showComboDialogue(

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


                    if ($choice) {

                        $self->session->pseudoCmd(
                            'modelreport -f -r <' . $self->currentRegionmap->name . '>' . ' -l <'
                            . $choice . '>',
                            'show_all',
                        );
                    }
                });
                $subSubMenu_roomFlags->append($item_roomFlags4);
                # (Requires $self->currentRegionmap)
                $self->ivAdd('menuToolItemHash', 'report_flags_4', $item_roomFlags4);

            my $item_roomFlags = Gtk3::MenuItem->new('Room _flags');
            $item_roomFlags->set_submenu($subSubMenu_roomFlags);
            $subMenu_reports->append($item_roomFlags);

                 # 'Rooms' sub-submenu
                my $subSubMenu_rooms = Gtk3::Menu->new();

                my $item_rooms1 = Gtk3::MenuItem->new('_All regions');
                $item_rooms1->signal_connect('activate' => sub {

                    $self->session->pseudoCmd('modelreport -m', 'show_all');
                });
                $subSubMenu_rooms->append($item_rooms1);

                my $item_rooms2 = Gtk3::MenuItem->new('_Current region');
                $item_rooms2->signal_connect('activate' => sub {

                    $self->session->pseudoCmd(
                        'modelreport -m -r <' . $self->currentRegionmap->name . '>',
                        'show_all',
                    );
                });
                $subSubMenu_rooms->append($item_rooms2);
                # (Requires $self->currentRegionmap)
                $self->ivAdd('menuToolItemHash', 'report_rooms_2', $item_rooms2);

            my $item_rooms = Gtk3::MenuItem->new('_Rooms');
            $item_rooms->set_submenu($subSubMenu_rooms);
            $subMenu_reports->append($item_rooms);

                 # 'Exits' sub-submenu
                my $subSubMenu_exits = Gtk3::Menu->new();

                my $item_exits1 = Gtk3::MenuItem->new('_All regions');
                $item_exits1->signal_connect('activate' => sub {

                    $self->session->pseudoCmd('modelreport -x', 'show_all');
                });
                $subSubMenu_exits->append($item_exits1);

                my $item_exits2 = Gtk3::MenuItem->new('_Current region');
                $item_exits2->signal_connect('activate' => sub {

                    $self->session->pseudoCmd(
                        'modelreport -x -r <' . $self->currentRegionmap->name . '>',
                        'show_all',
                    );
                });
                $subSubMenu_exits->append($item_exits2);
                # (Requires $self->currentRegionmap)
                $self->ivAdd('menuToolItemHash', 'report_exits_2', $item_exits2);

            my $item_exits = Gtk3::MenuItem->new('_Exits');
            $item_exits->set_submenu($subSubMenu_exits);
            $subMenu_reports->append($item_exits);

                # 'Checked directions' sub-submenu
                my $subSubMenu_checked = Gtk3::Menu->new();

                my $item_checked1 = Gtk3::MenuItem->new('_All regions');
                $item_checked1->signal_connect('activate' => sub {

                    $self->session->pseudoCmd('modelreport -h', 'show_all');
                });
                $subSubMenu_checked->append($item_checked1);

                my $item_checked2 = Gtk3::MenuItem->new('_Current region');
                $item_checked2->signal_connect('activate' => sub {

                    $self->session->pseudoCmd(
                        'modelreport -h -r <' . $self->currentRegionmap->name . '>',
                        'show_all',
                    );
                });
                $subSubMenu_checked->append($item_checked2);
                # (Requires $self->currentRegionmap)
                $self->ivAdd('menuToolItemHash', 'report_checked_2', $item_checked2);

            my $item_checked = Gtk3::MenuItem->new('Checked _directions');
            $item_checked->set_submenu($subSubMenu_checked);
            $subMenu_reports->append($item_checked);

        my $item_reports = Gtk3::MenuItem->new('_Generate reports');
        $item_reports->set_submenu($subMenu_reports);
        $column_edit->append($item_reports);

        $column_edit->append(Gtk3::SeparatorMenuItem->new());   # Separator

            # 'Reset' sub-submenu
            my $subMenu_reset = Gtk3::Menu->new();

            my $item_resetRoomData = Gtk3::MenuItem->new('Reset _room data...');
            $item_resetRoomData->signal_connect('activate' => sub {

                $self->resetRoomDataCallback();
            });
            $subMenu_reset->append($item_resetRoomData);

            my $item_resetCharVisits = Gtk3::MenuItem->new('Reset _visits by character...');
            $item_resetCharVisits->signal_connect('activate' => sub {

                $self->resetVisitsCallback();
            });
            $subMenu_reset->append($item_resetCharVisits);

        my $item_reset = Gtk3::MenuItem->new('_Reset');
        $item_reset->set_submenu($subMenu_reset);
        $column_edit->append($item_reset);

        $column_edit->append(Gtk3::SeparatorMenuItem->new());   # Separator

        my $item_editDict = Gtk3::ImageMenuItem->new('Edit current _dictionary...');
        my $img_editDict = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
        $item_editDict->set_image($img_editDict);
        $item_editDict->signal_connect('activate' => sub {

            # Open an 'edit' window for the current dictionary
            $self->createFreeWin(
                'Games::Axmud::EditWin::Dict',
                $self,
                $self->session,
                'Edit dictionary \'' . $self->session->currentDict->name . '\'',
                $self->session->currentDict,
                FALSE,          # Not temporary
            );
        });
        $column_edit->append($item_editDict);

        my $item_addWords = Gtk3::MenuItem->new('Add dictionary _words...');
        $item_addWords->signal_connect('activate' => sub {

            $self->createFreeWin(
                'Games::Axmud::OtherWin::QuickWord',
                $self,
                $self->session,
                'Quick word adder',
            );
        });
        $column_edit->append($item_addWords);

        my $item_updateModel = Gtk3::MenuItem->new('U_pdate model words');
        $item_updateModel->signal_connect('activate' => sub {

            # Use pseudo-command mode 'win_error' - show success messages in the 'main' window,
            #   error messages in 'dialogue' window
            $self->session->pseudoCmd('updatemodel -t', 'win_error');
        });
        $column_edit->append($item_updateModel);

        $column_edit->append(Gtk3::SeparatorMenuItem->new());   # Separator

        my $item_setupWizard = Gtk3::ImageMenuItem->new('Run _Locator wizard...');
        my $img_setupWizard = Gtk3::Image->new_from_stock('gtk-page-setup', 'menu');
        $item_setupWizard->set_image($img_setupWizard);
        $item_setupWizard->signal_connect('activate' => sub {

            if ($self->session->wizWin) {

                # Some kind of 'wiz' window is already open
                $self->session->wizWin->restoreFocus();

            } else {

                # Open the Locator wizard window
                $self->session->pseudoCmd('locatorwizard', $self->pseudoCmdMode);
            }
        });
        $column_edit->append($item_setupWizard);

        my $item_editModel = Gtk3::ImageMenuItem->new('Edit world _model...');
        my $img_editModel = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
        $item_editModel->set_image($img_editModel);
        $item_editModel->signal_connect('activate' => sub {

            # Open an 'edit' window for the world model
            $self->createFreeWin(
                'Games::Axmud::EditWin::WorldModel',
                $self,
                $self->session,
                'Edit world model',

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


    sub enableViewColumn {

        # Sets up the 'View' column of the Automapper window's menu bar
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments or if the widget can't be created
        #   Otherwise returns the Gtk3::Menu created

        my ($self, $check) = @_;

        # Local variables
        my (
            $item_group,
            @magList, @shortMagList, @initList, @interiorList,
            %interiorHash,
        );

        # Check for improper arguments
        if (defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->enableViewColumn', @_);
        }

        # Set up column
        my $column_view = Gtk3::Menu->new();
        if (! $column_view) {

            return undef;
        }

            # 'Window components' submenu
            my $subMenu_winComponents = Gtk3::Menu->new();

            my $item_showMenuBar = Gtk3::CheckMenuItem->new('Show menu_bar');
            $item_showMenuBar->set_active($self->worldModelObj->showMenuBarFlag);
            $item_showMenuBar->signal_connect('toggled' => sub {

                $self->worldModelObj->toggleWinComponents(
                    'showMenuBarFlag',
                    $item_showMenuBar->get_active(),
                );
            });
            $subMenu_winComponents->append($item_showMenuBar);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'show_menu_bar', $item_showMenuBar);

            my $item_showToolbar = Gtk3::CheckMenuItem->new('Show _toolbar');
            $item_showToolbar->set_active($self->worldModelObj->showToolbarFlag);
            $item_showToolbar->signal_connect('toggled' => sub {

                $self->worldModelObj->toggleWinComponents(
                    'showToolbarFlag',
                    $item_showToolbar->get_active(),
                );
            });
            $subMenu_winComponents->append($item_showToolbar);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'show_toolbar', $item_showToolbar);

            my $item_showTreeView = Gtk3::CheckMenuItem->new('Show _regions');
            $item_showTreeView->set_active($self->worldModelObj->showTreeViewFlag);
            $item_showTreeView->signal_connect('toggled' => sub {

                $self->worldModelObj->toggleWinComponents(
                    'showTreeViewFlag',
                    $item_showTreeView->get_active(),
                );
            });
            $subMenu_winComponents->append($item_showTreeView);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'show_treeview', $item_showTreeView);

            my $item_showCanvas = Gtk3::CheckMenuItem->new('Show _map');
            $item_showCanvas->set_active($self->worldModelObj->showCanvasFlag);
            $item_showCanvas->signal_connect('toggled' => sub {

                $self->worldModelObj->toggleWinComponents(
                    'showCanvasFlag',
                    $item_showCanvas->get_active(),
                );
            });
            $subMenu_winComponents->append($item_showCanvas);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'show_canvas', $item_showCanvas);

            $subMenu_winComponents->append(Gtk3::SeparatorMenuItem->new());  # Separator

            my $item_redrawWindow = Gtk3::MenuItem->new('Re_draw window');
            $item_redrawWindow->signal_connect('activate' => sub {

                $self->redrawWidgets('menu_bar', 'toolbar', 'treeview', 'canvas');
            });
            $subMenu_winComponents->append($item_redrawWindow);

        my $item_windowComponents = Gtk3::MenuItem->new('_Window components');
        $item_windowComponents->set_submenu($subMenu_winComponents);
        $column_view->append($item_windowComponents);

            # 'Current room' submenu
            my $subMenu_currentRoom = Gtk3::Menu->new();

            my $item_radio1 = Gtk3::RadioMenuItem->new_with_mnemonic(undef, 'Draw _normal room');
            $item_radio1->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag && $item_radio1->get_active()) {

                    $self->worldModelObj->switchMode(
                        'currentRoomMode',
                        'single',           # New value of ->currentRoomMode
                        FALSE,              # No call to ->redrawRegions; current room is redrawn
                        'normal_current_mode',
                    );
                }
            });
            my $item_group0 = $item_radio1->get_group();
            $subMenu_currentRoom->append($item_radio1);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'normal_current_mode', $item_radio1);

            my $item_radio2 = Gtk3::RadioMenuItem->new_with_mnemonic(
                $item_group0,
                'Draw _emphasised room',
            );
            if ($self->worldModelObj->currentRoomMode eq 'double') {

                $item_radio2->set_active(TRUE);
            }
            $item_radio2->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag && $item_radio2->get_active()) {

                    $self->worldModelObj->switchMode(
                        'currentRoomMode',
                        'double',           # New value of ->currentRoomMode
                        FALSE,              # No call to ->redrawRegions; current room is redrawn
                        'empahsise_current_room',
                    );
                }
            });
            $subMenu_currentRoom->append($item_radio2);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'empahsise_current_room', $item_radio2);

            my $item_radio3 = Gtk3::RadioMenuItem->new_with_mnemonic(
                $item_group0,
                'Draw _filled-in room',
            );
            if ($self->worldModelObj->currentRoomMode eq 'interior') {

                $item_radio3->set_active(TRUE);
            }
            $item_radio3->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag && $item_radio3->get_active()) {

                    $self->worldModelObj->switchMode(
                        'currentRoomMode',
                        'interior',         # New value of ->currentRoomMode
                        FALSE,              # No call to ->redrawRegions; current room is redrawn
                        'fill_in_current_room',
                    );
                }
            });
            $subMenu_currentRoom->append($item_radio3);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'fill_in_current_room', $item_radio3);

        my $item_currentRoom = Gtk3::MenuItem->new('_Draw current room');
        $item_currentRoom->set_submenu($subMenu_currentRoom);
        $column_view->append($item_currentRoom);

            # 'Room filters' submenu
            my $subMenu_roomFilters = Gtk3::Menu->new();

            my $item_releaseAllFilters = Gtk3::CheckMenuItem->new('_Release all filters');
            $item_releaseAllFilters->set_active($self->worldModelObj->allRoomFiltersFlag);
            $item_releaseAllFilters->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'allRoomFiltersFlag',
                        $item_releaseAllFilters->get_active(),
                        TRUE,      # Do call $self->redrawRegions
                        'release_all_filters',
                        'icon_release_all_filters',
                    );
                }
            });
            $subMenu_roomFilters->append($item_releaseAllFilters);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'release_all_filters', $item_releaseAllFilters);

            $subMenu_roomFilters->append(Gtk3::SeparatorMenuItem->new()); # Separator

            my @shortcutList = $axmud::CLIENT->constRoomFilterKeyList;
            foreach my $filter ($axmud::CLIENT->constRoomFilterList) {

                my $shortcut = shift @shortcutList;

                my $menuItem = Gtk3::CheckMenuItem->new('Release ' . $shortcut . ' filter');
                $menuItem->set_active($self->worldModelObj->ivShow('roomFilterApplyHash', $filter));
                $menuItem->signal_connect('toggled' => sub {

                    if (! $self->ignoreMenuUpdateFlag) {

                        $self->worldModelObj->toggleFilter(
                            $filter,
                            $menuItem->get_active(),
                        );
                    }
                });
                $subMenu_roomFilters->append($menuItem);
                # (Never desensitised)
                $self->ivAdd('menuToolItemHash', $filter . '_filter', $menuItem);
            }

        my $item_roomFilters = Gtk3::MenuItem->new('Room _filters');
        $item_roomFilters->set_submenu($subMenu_roomFilters);
        $column_view->append($item_roomFilters);

            # 'Room interiors' submenu
            my $subMenu_roomInteriors = Gtk3::Menu->new();

            @initList = (
                'none' => '_Don\'t draw counts',
                'shadow_count' => 'Draw _unallocated/shadow exits',
                'region_count' => 'Draw re_gion/super region exits',
                'checked_count' => 'Draw _checked/checkable directions',
                'room_content' => 'Draw _room contents',
                'hidden_count' => 'Draw _hidden contents',
                'temp_count' => 'Draw _temporary contents',
                'word_count' => 'Draw r_ecognised words',

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


            } until (! @initList);

            for (my $count = 0; $count < (scalar @interiorList); $count++) {

                my ($icon, $mode);

                $mode = $interiorList[$count];

                # (For $count = 0, $item_group is 'undef')
                my $item_radio = Gtk3::RadioMenuItem->new_with_mnemonic(
                    $item_group,
                    $interiorHash{$mode},
                );
                if ($self->worldModelObj->roomInteriorMode eq $mode) {

                    $item_radio->set_active(TRUE);
                }

                $item_radio->signal_connect('toggled' => sub {

                    if (! $self->ignoreMenuUpdateFlag && $item_radio->get_active()) {

                        $self->worldModelObj->switchRoomInteriorMode($mode);
                    }
                });
                $item_group = $item_radio->get_group();
                $subMenu_roomInteriors->append($item_radio);
                # (Never desensitised)
                $self->ivAdd('menuToolItemHash', 'interior_mode_' . $mode, $item_radio);
            }

            $subMenu_roomInteriors->append(Gtk3::SeparatorMenuItem->new()); # Separator

            my $item_changeCharDrawn = Gtk3::MenuItem->new('Ch_ange character drawn...');
            $item_changeCharDrawn->signal_connect('activate' => sub {

                # (Callback func has no dependencies)
                $self->changeCharDrawnCallback();
            });
            $subMenu_roomInteriors->append($item_changeCharDrawn);

        my $item_roomInteriors = Gtk3::MenuItem->new('R_oom interiors');
        $item_roomInteriors->set_submenu($subMenu_roomInteriors);
        $column_view->append($item_roomInteriors);

            # 'All exits' submenu
            my $subMenu_allExits = Gtk3::Menu->new();

            my $item_radio11 = Gtk3::RadioMenuItem->new_with_mnemonic(
                undef,
                '_Use region exit settings',
            );
            $item_radio11->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag && $item_radio11->get_active()) {

                    $self->worldModelObj->switchMode(
                        'drawExitMode',
                        'ask_regionmap',    # New value of ->drawExitMode
                        TRUE,               # Do call $self->redrawRegions
                        'draw_defer_exits',
                        'icon_draw_defer_exits',
                    );
                }
            });
            my $item_group1 = $item_radio11->get_group();
            $subMenu_allExits->append($item_radio11);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'draw_defer_exits', $item_radio11);

            my $item_radio12 = Gtk3::RadioMenuItem->new_with_mnemonic(
                $item_group1,
                'Draw _no exits',
            );
            if ($self->worldModelObj->drawExitMode eq 'no_exit') {

                $item_radio12->set_active(TRUE);
            }
            $item_radio12->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag && $item_radio12->get_active()) {

                    $self->worldModelObj->switchMode(
                        'drawExitMode',
                        'no_exit',          # New value of ->drawExitMode
                        TRUE,               # Do call $self->redrawRegions
                        'draw_no_exits',
                        'icon_draw_no_exits',
                    );
                }
            });
            $subMenu_allExits->append($item_radio12);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'draw_no_exits', $item_radio12);

            my $item_radio13 = Gtk3::RadioMenuItem->new_with_mnemonic(
                $item_group1,
                'Draw _simple exits',
            );
            if ($self->worldModelObj->drawExitMode eq 'simple_exit') {

                $item_radio13->set_active(TRUE);
            }
            $item_radio13->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag && $item_radio13->get_active()) {

                    $self->worldModelObj->switchMode(
                        'drawExitMode',
                        'simple_exit',      # New value of ->drawExitMode
                        TRUE,               # Do call $self->redrawRegions
                        'draw_simple_exits',
                        'icon_draw_simple_exits',
                    );
                }
            });
            $subMenu_allExits->append($item_radio13);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'draw_simple_exits', $item_radio13);

            my $item_radio14 = Gtk3::RadioMenuItem->new_with_mnemonic(
                $item_group1,
                'Draw _complex exits',
            );
            if ($self->worldModelObj->drawExitMode eq 'complex_exit') {

                $item_radio14->set_active(TRUE);
            }
            $item_radio14->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag && $item_radio14->get_active()) {

                    $self->worldModelObj->switchMode(
                        'drawExitMode',
                        'complex_exit',     # New value of ->drawExitMode
                        TRUE,               # Do call $self->redrawRegions
                        'draw_complex_exits',
                        'icon_draw_complex_exits',
                    );
                }
            });
            $subMenu_allExits->append($item_radio14);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'draw_complex_exits', $item_radio14);

            $subMenu_allExits->append(Gtk3::SeparatorMenuItem->new()); # Separator

            my $item_obscuredExits = Gtk3::CheckMenuItem->new('_Obscure unimportant exits');
            $item_obscuredExits->set_active($self->worldModelObj->obscuredExitFlag);
            $item_obscuredExits->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'obscuredExitFlag',
                        $item_obscuredExits->get_active(),
                        TRUE,      # Do call $self->redrawRegions
                        'obscured_exits',
                        'icon_obscured_exits',
                    );
                }
            });
            $subMenu_allExits->append($item_obscuredExits);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'obscured_exits', $item_obscuredExits);

            my $item_autoRedraw = Gtk3::CheckMenuItem->new('_Auto-redraw obscured exits');
            $item_autoRedraw->set_active($self->worldModelObj->obscuredExitRedrawFlag);
            $item_autoRedraw->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'obscuredExitRedrawFlag',
                        $item_autoRedraw->get_active(),
                        TRUE,      # Do call $self->redrawRegions
                        'auto_redraw_obscured',
                        'icon_auto_redraw_obscured',
                    );
                }
            });
            $subMenu_allExits->append($item_autoRedraw);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'auto_redraw_obscured', $item_autoRedraw);

            my $item_obscuredExitRadius = Gtk3::MenuItem->new('Set obscure _radius...');
            $item_obscuredExitRadius->signal_connect('activate' => sub {

                $self->obscuredRadiusCallback();
            });
            $subMenu_allExits->append($item_obscuredExitRadius);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'obscured_exit_radius', $item_obscuredExitRadius);

            $subMenu_allExits->append(Gtk3::SeparatorMenuItem->new()); # Separator

            my $item_drawOrnaments = Gtk3::CheckMenuItem->new('Draw exit orna_ments');
            $item_drawOrnaments->set_active($self->worldModelObj->drawOrnamentsFlag);
            $item_drawOrnaments->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'drawOrnamentsFlag',
                        $item_drawOrnaments->get_active(),
                        TRUE,      # Do call $self->redrawRegions
                        'draw_ornaments',
                        'icon_draw_ornaments',
                    );
                }
            });
            $subMenu_allExits->append($item_drawOrnaments);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'draw_ornaments', $item_drawOrnaments);

        my $item_allExits = Gtk3::MenuItem->new('Exits (_all regions)');
        $item_allExits->set_submenu($subMenu_allExits);
        $column_view->append($item_allExits);

            # 'Region exits' submenu
            my $subMenu_regionExits = Gtk3::Menu->new();

            my $item_radio21 = Gtk3::RadioMenuItem->new_with_mnemonic(undef, 'Draw _no exits');
            $item_radio21->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag && $item_radio21->get_active()) {

                    $self->worldModelObj->switchRegionDrawExitMode(
                        $self->currentRegionmap,
                        'no_exit',
                    );
                }
            });
            my $item_group2 = $item_radio21->get_group();
            $subMenu_regionExits->append($item_radio21);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'region_draw_no_exits', $item_radio21);

            my $item_radio22 = Gtk3::RadioMenuItem->new_with_mnemonic(
                $item_group2,
                'Draw _simple exits',
            );
            if ($self->currentRegionmap && $self->currentRegionmap->drawExitMode eq 'simple_exit') {

                $item_radio22->set_active(TRUE);
            }
            $item_radio22->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag && $item_radio22->get_active()) {

                    $self->worldModelObj->switchRegionDrawExitMode(
                        $self->currentRegionmap,
                        'simple_exit',
                    );
                }
            });
            $subMenu_regionExits->append($item_radio22);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'region_draw_simple_exits', $item_radio22);

            my $item_radio23 = Gtk3::RadioMenuItem->new_with_mnemonic(
                $item_group2,
                'Draw _complex exits',
            );
            if (
                $self->currentRegionmap
                && $self->currentRegionmap->drawExitMode eq 'complex_exit'
            ) {
                $item_radio23->set_active(TRUE);
            }
            $item_radio23->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag && $item_radio23->get_active()) {

                    $self->worldModelObj->switchRegionDrawExitMode(
                        $self->currentRegionmap,
                        'complex_exit',
                    );
                }
            });
            $subMenu_regionExits->append($item_radio23);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'region_draw_complex_exits', $item_radio23);

            $subMenu_regionExits->append(Gtk3::SeparatorMenuItem->new());   # Separator

            my $item_obscuredExitsRegion = Gtk3::CheckMenuItem->new('_Obscure unimportant exits');
            if ($self->currentRegionmap) {

                $item_obscuredExitsRegion->set_active($self->currentRegionmap->obscuredExitFlag);
            }
            $item_obscuredExitsRegion->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleObscuredExitFlag($self->currentRegionmap);
                }
            });
            $subMenu_regionExits->append($item_obscuredExitsRegion);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'obscured_exits_region', $item_obscuredExitsRegion);

            my $item_autoRedrawRegion = Gtk3::CheckMenuItem->new('_Auto-redraw obscured exits');
            if ($self->currentRegionmap) {

                $item_autoRedrawRegion->set_active($self->currentRegionmap->obscuredExitRedrawFlag);
            }
            $item_autoRedrawRegion->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleObscuredExitRedrawFlag($self->currentRegionmap);
                }
            });
            $subMenu_regionExits->append($item_autoRedrawRegion);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'auto_redraw_obscured_region', $item_autoRedrawRegion);

            my $item_obscuredExitRadiusRegion = Gtk3::MenuItem->new('Set obscure _radius...');
            $item_obscuredExitRadiusRegion->signal_connect('activate' => sub {

                $self->obscuredRadiusCallback($self->currentRegionmap);
            });
            $subMenu_regionExits->append($item_obscuredExitRadiusRegion);
            # (Never desensitised)
            $self->ivAdd(
                'menuToolItemHash',
                'obscured_exit_radius_region',
                $item_obscuredExitRadiusRegion,
            );

            $subMenu_regionExits->append(Gtk3::SeparatorMenuItem->new());   # Separator

            my $item_drawOrnamentsRegion = Gtk3::CheckMenuItem->new('Draw exit orna_ments');
            if ($self->currentRegionmap) {

                $item_drawOrnamentsRegion->set_active($self->currentRegionmap->drawOrnamentsFlag);
            }
            $item_drawOrnamentsRegion->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleDrawOrnamentsFlag($self->currentRegionmap);
                }
            });
            $subMenu_regionExits->append($item_drawOrnamentsRegion);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'draw_ornaments_region', $item_drawOrnamentsRegion);

        my $item_regionExits = Gtk3::MenuItem->new('Exits (_current region)');
        $item_regionExits->set_submenu($subMenu_regionExits);
        $column_view->append($item_regionExits);
        # (Requires $self->currentRegionmap and $self->worldModelObj->drawExitMode is
        #   'ask_regionmap')
        $self->ivAdd('menuToolItemHash', 'draw_region_exits', $item_regionExits);

        $column_view->append(Gtk3::SeparatorMenuItem->new());   # Separator

        my $item_zoomIn = Gtk3::ImageMenuItem->new('Zoom i_n');
        my $img_zoomIn = Gtk3::Image->new_from_stock('gtk-zoom-in', 'menu');
        $item_zoomIn->set_image($img_zoomIn);
        $item_zoomIn->signal_connect('activate' => sub {

            $self->zoomCallback('in');
        });
        $column_view->append($item_zoomIn);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'zoom_in', $item_zoomIn);

        my $item_zoomOut = Gtk3::ImageMenuItem->new('Zoom _out');
        my $img_zoomOut = Gtk3::Image->new_from_stock('gtk-zoom-out', 'menu');
        $item_zoomOut->set_image($img_zoomOut);
        $item_zoomOut->signal_connect('activate' => sub {

            $self->zoomCallback('out');
        });
        $column_view->append($item_zoomOut);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'zoom_out', $item_zoomOut);

            # 'Zoom' submenu
            my $subMenu_zoom = Gtk3::Menu->new();

            # Import the list of magnifications
            @magList = $self->constMagnifyList;
            # Use a subset of magnifications from $self->constMagnifyList (and in reverse order to
            #   that found in $self->constMagnifyList)
            @shortMagList = reverse $self->constShortMagnifyList;

            foreach my $mag (@shortMagList) {

                my $menuItem = Gtk3::MenuItem->new('Zoom ' . $mag * 100 . '%');
                $menuItem->signal_connect('activate' => sub {

                    # No argument causes the called function to prompt the user
                    $self->zoomCallback($mag);
                });
                $subMenu_zoom->append($menuItem);
            }

            $subMenu_zoom->append(Gtk3::SeparatorMenuItem->new());  # Separator

            my $item_zoomMax = Gtk3::MenuItem->new('Zoom _in max');
            $item_zoomMax->signal_connect('activate' => sub {

                $self->zoomCallback($magList[-1]);
            });
            $subMenu_zoom->append($item_zoomMax);

            my $item_zoomMin = Gtk3::MenuItem->new('Zoom _out max');
            $item_zoomMin->signal_connect('activate' => sub {

                $self->zoomCallback($magList[0]);
            });
            $subMenu_zoom->append($item_zoomMin);

            $subMenu_zoom->append(Gtk3::SeparatorMenuItem->new());  # Separator

            my $item_zoomPrompt = Gtk3::MenuItem->new('O_ther...');
            $item_zoomPrompt->signal_connect('activate' => sub {

                # No argument causes the called function to prompt the user
                $self->zoomCallback();
            });
            $subMenu_zoom->append($item_zoomPrompt);

        my $item_zoom = Gtk3::ImageMenuItem->new('_Zoom');
        my $img_zoom = Gtk3::Image->new_from_stock('gtk-zoom-fit', 'menu');
        $item_zoom->set_image($img_zoom);
        $item_zoom->set_submenu($subMenu_zoom);
        $column_view->append($item_zoom);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'zoom_sub', $item_zoom);

        $column_view->append(Gtk3::SeparatorMenuItem->new());   # Separator

            # 'Level' submenu
            my $subMenu_level = Gtk3::Menu->new();

            my $item_moveUpLevel = Gtk3::MenuItem->new('Move _up level');
            $item_moveUpLevel->signal_connect('activate' => sub {

                $self->setCurrentLevel($self->currentRegionmap->currentLevel + 1);

                # Sensitise/desensitise menu bar/toolbar items, depending on current conditions
                $self->restrictWidgets();
            });
            $subMenu_level->append($item_moveUpLevel);
            # (Requires $self->currentRegionmap)
            $self->ivAdd('menuToolItemHash', 'move_up_level', $item_moveUpLevel);

            my $item_moveDownLevel = Gtk3::MenuItem->new('Move _down level');
            $item_moveDownLevel->signal_connect('activate' => sub {

                $self->setCurrentLevel($self->currentRegionmap->currentLevel - 1);

                # Sensitise/desensitise menu bar/toolbar items, depending on current conditions
                $self->restrictWidgets();
            });
            $subMenu_level->append($item_moveDownLevel);
            # (Requires $self->currentRegionmap)
            $self->ivAdd('menuToolItemHash', 'move_down_level', $item_moveDownLevel);

            $subMenu_level->append(Gtk3::SeparatorMenuItem->new()); # Separator

            my $item_changeLevel = Gtk3::MenuItem->new('_Change level...');
            $item_changeLevel->signal_connect('activate' => sub {

                $self->changeLevelCallback();
            });
            $subMenu_level->append($item_changeLevel);

        my $item_level = Gtk3::MenuItem->new('_Level');
        $item_level->set_submenu($subMenu_level);
        $column_view->append($item_level);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'level_sub', $item_level);

        $column_view->append(Gtk3::SeparatorMenuItem->new());   # Separator

            # 'Centre map' submenu
            my $subMenu_centreMap = Gtk3::Menu->new();

            my $item_centreMap_currentRoom = Gtk3::MenuItem->new('_Current room');
            $item_centreMap_currentRoom->signal_connect('activate' => sub {

                $self->centreMapOverRoom($self->mapObj->currentRoom);
            });
            $subMenu_centreMap->append($item_centreMap_currentRoom);
            # (Requires $self->currentRegionmap & $self->mapObj->currentRoom)
            $self->ivAdd(
                'menuToolItemHash',
                'centre_map_current_room',
                $item_centreMap_currentRoom,
            );

            my $item_centreMap_selectRoom = Gtk3::MenuItem->new('_Selected room');
            $item_centreMap_selectRoom->signal_connect('activate' => sub {

                $self->centreMapOverRoom($self->selectedRoom);
            });
            $subMenu_centreMap->append($item_centreMap_selectRoom);
            # (Requires $self->currentRegionmap & $self->selectedRoom)
            $self->ivAdd(
                'menuToolItemHash',
                'centre_map_select_room',
                $item_centreMap_selectRoom,
            );

            my $item_centreMap_lastKnownRoom = Gtk3::MenuItem->new('_Last known room');
            $item_centreMap_lastKnownRoom->signal_connect('activate' => sub {

                $self->centreMapOverRoom($self->mapObj->lastKnownRoom);
            });
            $subMenu_centreMap->append($item_centreMap_lastKnownRoom);
            # (Requires $self->currentRegionmap & $self->mapObj->lastknownRoom)
            $self->ivAdd(
                'menuToolItemHash',
                'centre_map_last_known_room',
                $item_centreMap_lastKnownRoom,
            );

            $subMenu_centreMap->append(Gtk3::SeparatorMenuItem->new()); # Separator

            my $item_centreMap_middleGrid = Gtk3::MenuItem->new('_Middle of grid');
            $item_centreMap_middleGrid->signal_connect('activate' => sub {

                $self->setMapPosn(0.5, 0.5);
            });
            $subMenu_centreMap->append($item_centreMap_middleGrid);
            # (Requires $self->currentRegionmap)
            $self->ivAdd('menuToolItemHash', 'centre_map_middle_grid', $item_centreMap_middleGrid);

        my $item_centreMap = Gtk3::MenuItem->new('Centre _map');
        $item_centreMap->set_submenu($subMenu_centreMap);
        $column_view->append($item_centreMap);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'centre_map_sub', $item_centreMap);

        my $item_repositionAllMaps = Gtk3::MenuItem->new('_Reposition all maps');
        $item_repositionAllMaps->signal_connect('activate' => sub {

            $self->worldModelObj->repositionMaps();
        });
        $column_view->append($item_repositionAllMaps);

            # 'Tracking' submenu
            my $subMenu_tracking = Gtk3::Menu->new();

            my $item_trackCurrentRoom = Gtk3::CheckMenuItem->new('_Track current room');
            $item_trackCurrentRoom->set_active($self->worldModelObj->trackPosnFlag);
            $item_trackCurrentRoom->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'trackPosnFlag',
                        $item_trackCurrentRoom->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'track_current_room',
                        'icon_track_current_room',
                    );
                }
            });
            $subMenu_tracking->append($item_trackCurrentRoom);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'track_current_room', $item_trackCurrentRoom);

            $subMenu_tracking->append(Gtk3::SeparatorMenuItem->new());  # Separator

            my $item_radio31 = Gtk3::RadioMenuItem->new_with_mnemonic(undef, '_Always track');
            if (
                $self->worldModelObj->trackingSensitivity != 0.33
                && $self->worldModelObj->trackingSensitivity != 0.66
                && $self->worldModelObj->trackingSensitivity != 1
            ) {
                # Only the sensitivity values 0, 0.33, 0.66 and 1 are curently allowed; act as
                #   though the IV was set to 0
                $item_radio31->set_active(TRUE);
            }
            $item_radio31->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag && $item_radio31->get_active()) {

                    $self->worldModelObj->setTrackingSensitivity(0);
                }
            });
            my $item_group3 = $item_radio31->get_group();
            $subMenu_tracking->append($item_radio31);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'track_always', $item_radio31);

            my $item_radio32 = Gtk3::RadioMenuItem->new_with_mnemonic(
                $item_group3,
                'Track near _centre',
            );
            if ($self->worldModelObj->trackingSensitivity == 0.33) {

                $item_radio32->set_active(TRUE);
            }
            $item_radio32->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag && $item_radio32->get_active()) {

                    $self->worldModelObj->setTrackingSensitivity(0.33);
                }
            });
            $subMenu_tracking->append($item_radio32);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'track_near_centre', $item_radio32);

            my $item_radio33 = Gtk3::RadioMenuItem->new_with_mnemonic(
                $item_group3,
                'Track near _edge',
            );
            if ($self->worldModelObj->trackingSensitivity == 0.66) {

                $item_radio33->set_active(TRUE);
            }
            $item_radio33->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag && $item_radio33->get_active()) {

                    $self->worldModelObj->setTrackingSensitivity(0.66);
                }
            });
            $subMenu_tracking->append($item_radio33);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'track_near_edge', $item_radio33);

            my $item_radio34 = Gtk3::RadioMenuItem->new_with_mnemonic(
                $item_group3,
                'Track if not _visible',
            );
            if ($self->worldModelObj->trackingSensitivity == 1) {

                $item_radio34->set_active(TRUE);
            }
            $item_radio34->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag && $item_radio34->get_active()) {

                    $self->worldModelObj->setTrackingSensitivity(1);
                }
            });
            $subMenu_tracking->append($item_radio34);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'track_not_visible', $item_radio34);

        my $item_tracking = Gtk3::MenuItem->new('_Tracking');
        $item_tracking->set_submenu($subMenu_tracking);
        $column_view->append($item_tracking);

        # Setup complete
        return $column_view;
    }

    sub enableModeColumn {

        # Called by $self->enableMenu
        # Sets up the 'Mode' column of the Automapper window's menu bar
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments or if the widget can't be created
        #   Otherwise returns the Gtk3::Menu created

        my ($self, $check) = @_;

        # Check for improper arguments
        if (defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->enableModeColumn', @_);
        }

        # Set up column
        my $column_mode = Gtk3::Menu->new();
        if (! $column_mode) {

            return undef;
        }

        # (Save each radio menu item in a hash IV, so that when $self->setMode is called, the radio
        #   group can be toggled)
        my $item_radio1 = Gtk3::RadioMenuItem->new_with_mnemonic(undef, '_Wait mode');
        $item_radio1->signal_connect('toggled' => sub {

            # (To stop the equivalent toolbar icon from being toggled by the call to ->setMode,
            #   make use of $self->ignoreMenuUpdateFlag)
            if ($item_radio1->get_active && ! $self->ignoreMenuUpdateFlag) {

                $self->setMode('wait');
            }
        });
        my $item_group = $item_radio1->get_group();
        $column_mode->append($item_radio1);
        # (Never desensitised)
        $self->ivAdd('menuToolItemHash', 'set_wait_mode', $item_radio1);

        my $item_radio2 = Gtk3::RadioMenuItem->new_with_mnemonic($item_group, '_Follow mode');
        $item_radio2->signal_connect('toggled' => sub {

            if ($item_radio2->get_active && ! $self->ignoreMenuUpdateFlag) {

                $self->setMode('follow');
            }
        });
        $column_mode->append($item_radio2);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'set_follow_mode', $item_radio2);

        my $item_radio3 = Gtk3::RadioMenuItem->new_with_mnemonic($item_group, '_Update mode');
        $item_radio3->signal_connect('toggled' => sub {

            if ($item_radio3->get_active && ! $self->ignoreMenuUpdateFlag) {

                $self->setMode('update');
            }
        });
        $column_mode->append($item_radio3);
        # (Requires $self->currentRegionmap, GA::Obj::WorldModel->disableUpdateModeFlag set to
        #   FALSE and a session not in 'connect offline' mode
        $self->ivAdd('menuToolItemHash', 'set_update_mode', $item_radio3);

        $column_mode->append(Gtk3::SeparatorMenuItem->new());   # Separator

        my $item_dragMode = Gtk3::CheckMenuItem->new('_Drag mode');
        $item_dragMode->set_active($self->dragModeFlag);
        $item_dragMode->signal_connect('toggled' => sub {

            if ($item_dragMode->get_active()) {
                $self->ivPoke('dragModeFlag', TRUE);
            } else {
                $self->ivPoke('dragModeFlag', FALSE);
            }

            # Set the equivalent toolbar button
            if ($self->ivExists('menuToolItemHash', 'icon_drag_mode')) {

                my $menuItem = $self->ivShow('menuToolItemHash', 'icon_drag_mode');
                $menuItem->set_active($item_dragMode->get_active());
            }
        });
        $column_mode->append($item_dragMode);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'drag_mode', $item_dragMode);

        my $item_graffitMode = Gtk3::CheckMenuItem->new('_Graffiti mode');
        $item_graffitMode->set_active($self->graffitiModeFlag);
        $item_graffitMode->signal_connect('toggled' => sub {

            my @redrawList;

            if ($item_graffitMode->get_active()) {

                $self->ivPoke('graffitiModeFlag', TRUE);

                # Tag current room, if any

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


            # The menu items which toggle graffiti in selected rooms are desensitised if
            #   ->graffitiModeFlag is FALSE
            # Sensitise/desensitise menu bar/toolbar items, depending on current conditions
            $self->restrictWidgets();
        });
        $column_mode->append($item_graffitMode);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'graffiti_mode', $item_graffitMode);

        $column_mode->append(Gtk3::SeparatorMenuItem->new());   # Separator

            # 'Match rooms' submenu
            my $subMenu_matchRooms = Gtk3::Menu->new();

            my $item_matchTitle = Gtk3::CheckMenuItem->new('Match room _titles');
            $item_matchTitle->set_active($self->worldModelObj->matchTitleFlag);
            $item_matchTitle->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'matchTitleFlag',
                        $item_matchTitle->get_active(),
                        FALSE,          # Do call $self->redrawRegions
                        'match_title',
                    );
                }
            });
            $subMenu_matchRooms->append($item_matchTitle);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'match_title', $item_matchTitle);

            my $item_matchDescrip = Gtk3::CheckMenuItem->new('Match room _descriptions');
            $item_matchDescrip->set_active($self->worldModelObj->matchDescripFlag);
            $item_matchDescrip->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'matchDescripFlag',
                        $item_matchDescrip->get_active(),
                        FALSE,          # Do call $self->redrawRegions
                        'match_descrip',
                    );
                }
            });
            $subMenu_matchRooms->append($item_matchDescrip);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'match_descrip', $item_matchDescrip);

            my $item_matchExit = Gtk3::CheckMenuItem->new('Match _exits');
            $item_matchExit->set_active($self->worldModelObj->matchExitFlag);
            $item_matchExit->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'matchExitFlag',
                        $item_matchExit->get_active(),
                        FALSE,          # Do call $self->redrawRegions
                        'match_exit',
                    );
                }
            });
            $subMenu_matchRooms->append($item_matchExit);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'match_exit', $item_matchExit);

            my $item_matchSource = Gtk3::CheckMenuItem->new('Match _source code');
            $item_matchSource->set_active($self->worldModelObj->matchSourceFlag);
            $item_matchSource->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'matchSourceFlag',
                        $item_matchSource->get_active(),
                        FALSE,          # Do call $self->redrawRegions
                        'match_source',
                    );
                }
            });
            $subMenu_matchRooms->append($item_matchSource);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'match_source', $item_matchSource);

            my $item_matchVNum = Gtk3::CheckMenuItem->new('Match room _vnum');
            $item_matchVNum->set_active($self->worldModelObj->matchVNumFlag);
            $item_matchVNum->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'matchVNumFlag',
                        $item_matchVNum->get_active(),
                        FALSE,          # Do call $self->redrawRegions
                        'match_vnum',
                    );
                }
            });
            $subMenu_matchRooms->append($item_matchVNum);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'match_vnum', $item_matchVNum);

            $subMenu_matchRooms->append(Gtk3::SeparatorMenuItem->new());   # Separator

            my $item_verboseChars = Gtk3::MenuItem->new('Set description _length...');
            $item_verboseChars->signal_connect('activate' => sub {

                $self->verboseCharsCallback();
            });
            $subMenu_matchRooms->append($item_verboseChars);

        my $item_matchRooms = Gtk3::MenuItem->new('_Match rooms');
        $item_matchRooms->set_submenu($subMenu_matchRooms);
        $column_mode->append($item_matchRooms);

            # 'Update rooms' submenu
            my $subMenu_updateRooms = Gtk3::Menu->new();

            my $item_updateTitle = Gtk3::CheckMenuItem->new('Update room _titles');
            $item_updateTitle->set_active($self->worldModelObj->updateTitleFlag);
            $item_updateTitle->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'updateTitleFlag',
                        $item_updateTitle->get_active(),
                        FALSE,          # Do call $self->redrawRegions
                        'update_title',
                    );
                }
            });
            $subMenu_updateRooms->append($item_updateTitle);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'update_title', $item_updateTitle);

            my $item_updateDescrip = Gtk3::CheckMenuItem->new('Update room _descriptions');
            $item_updateDescrip->set_active($self->worldModelObj->updateDescripFlag);
            $item_updateDescrip->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'updateDescripFlag',
                        $item_updateDescrip->get_active(),
                        FALSE,          # Do call $self->redrawRegions
                        'update_descrip',
                    );
                }
            });
            $subMenu_updateRooms->append($item_updateDescrip);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'update_descrip', $item_updateDescrip);

            my $item_updateExit = Gtk3::CheckMenuItem->new('Update _exits');
            $item_updateExit->set_active($self->worldModelObj->updateExitFlag);
            $item_updateExit->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'updateExitFlag',
                        $item_updateExit->get_active(),
                        FALSE,          # Do call $self->redrawRegions
                        'update_exit',
                    );
                }
            });
            $subMenu_updateRooms->append($item_updateExit);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'update_exit', $item_updateExit);

            my $item_updateOrnament
                = Gtk3::CheckMenuItem->new('Update _ornaments from exit state');
            $item_updateOrnament->set_active($self->worldModelObj->updateOrnamentFlag);
            $item_updateOrnament->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'updateOrnamentFlag',
                        $item_updateOrnament->get_active(),
                        FALSE,          # Do call $self->redrawRegions
                        'update_ornament',
                    );
                }
            });
            $subMenu_updateRooms->append($item_updateOrnament);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'update_ornament', $item_updateOrnament);

            my $item_updateSource = Gtk3::CheckMenuItem->new('Update _source code');
            $item_updateSource->set_active($self->worldModelObj->updateSourceFlag);
            $item_updateSource->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'updateSourceFlag',
                        $item_updateSource->get_active(),
                        FALSE,          # Do call $self->redrawRegions
                        'update_source',
                    );
                }
            });
            $subMenu_updateRooms->append($item_updateSource);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'update_source', $item_updateSource);

            my $item_updateVNum = Gtk3::CheckMenuItem->new('Update room _vnum, etc');
            $item_updateVNum->set_active($self->worldModelObj->updateVNumFlag);
            $item_updateVNum->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'updateVNumFlag',
                        $item_updateVNum->get_active(),
                        FALSE,          # Do call $self->redrawRegions
                        'update_vnum',
                    );
                }
            });
            $subMenu_updateRooms->append($item_updateVNum);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'update_vnum', $item_updateVNum);

            my $item_updateRoomCmd = Gtk3::CheckMenuItem->new('Update room _commands');
            $item_updateRoomCmd->set_active($self->worldModelObj->updateRoomCmdFlag);
            $item_updateRoomCmd->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'updateRoomCmdFlag',
                        $item_updateRoomCmd->get_active(),
                        FALSE,          # Do call $self->redrawRegions
                        'update_room_cmd',
                    );
                }
            });
            $subMenu_updateRooms->append($item_updateRoomCmd);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'update_room_cmd', $item_updateRoomCmd);

            $subMenu_updateRooms->append(Gtk3::SeparatorMenuItem->new());   # Separator

            my $item_analyseDescrip = Gtk3::CheckMenuItem->new('_Analyse room descrips');
            $item_analyseDescrip->set_active($self->worldModelObj->analyseDescripFlag);
            $item_analyseDescrip->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'analyseDescripFlag',
                        $item_analyseDescrip->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'analyse_descrip',
                    );
                }
            });
            $subMenu_updateRooms->append($item_analyseDescrip);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'analyse_descrip', $item_analyseDescrip);

        my $item_updateRooms = Gtk3::MenuItem->new('Update _rooms');
        $item_updateRooms->set_submenu($subMenu_updateRooms);
        $column_mode->append($item_updateRooms);

        $column_mode->append(Gtk3::SeparatorMenuItem->new());   # Separator

            # 'Painter' submenu
            my $subMenu_painter = Gtk3::Menu->new();

            my $item_painterEnabled = Gtk3::CheckMenuItem->new('_Painter enabled');
            $item_painterEnabled->set_active($self->painterFlag);
            $item_painterEnabled->signal_connect('toggled' => sub {

                my $item;

                # Toggle the flag
                if ($item_painterEnabled->get_active()) {
                    $self->ivPoke('painterFlag', TRUE);
                } else {
                    $self->ivPoke('painterFlag', FALSE);
                }

                # Update the corresponding toolbar icon
                $item = $self->ivShow('menuToolItemHash', 'icon_enable_painter');
                if ($item) {

                    $item->set_active($self->painterFlag);
                }
            });
            $subMenu_painter->append($item_painterEnabled);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'enable_painter', $item_painterEnabled);

            $subMenu_painter->append(Gtk3::SeparatorMenuItem->new());   # Separator

            my $item_paintAll = Gtk3::RadioMenuItem->new_with_mnemonic(undef, 'Paint _all rooms');
            $item_paintAll->signal_connect('toggled' => sub {

                if ($item_paintAll->get_active) {

                    $self->worldModelObj->set_paintAllRoomsFlag(TRUE);

                    # Set the equivalent toolbar button
                    if ($self->ivExists('menuToolItemHash', 'icon_paint_all')) {

                        $self->ivShow('menuToolItemHash', 'icon_paint_all')->set_active(TRUE);
                    }
                }
            });
            my $item_paintGroup = $item_paintAll->get_group();
            $subMenu_painter->append($item_paintAll);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'paint_all', $item_paintAll);

            my $item_paintNew = Gtk3::RadioMenuItem->new_with_mnemonic(
                $item_paintGroup,
                'Paint _only new rooms',
            );
            if (! $self->worldModelObj->paintAllRoomsFlag) {

                $item_paintNew->set_active(TRUE);
            }
            $item_paintNew->signal_connect('toggled' => sub {

                if ($item_paintNew->get_active) {

                    $self->worldModelObj->set_paintAllRoomsFlag(FALSE);

                    # Set the equivalent toolbar button
                    if ($self->ivExists('menuToolItemHash', 'icon_paint_new')) {

                        $self->ivShow('menuToolItemHash', 'icon_paint_new')->set_active(TRUE);
                    }
                }
            });
            $subMenu_painter->append($item_paintNew);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'paint_new', $item_paintNew);

            $subMenu_painter->append(Gtk3::SeparatorMenuItem->new());   # Separator

            my $item_paintNormal = Gtk3::RadioMenuItem->new_with_mnemonic(
                undef,
                'Paint _normal rooms',
            );
            $item_paintNormal->signal_connect('toggled' => sub {

                if ($item_paintNormal->get_active) {

                    $self->worldModelObj->painterObj->ivPoke('wildMode', 'normal');

                    # Set the equivalent toolbar button
                    if ($self->ivExists('menuToolItemHash', 'icon_paint_normal')) {

                        $self->ivShow('menuToolItemHash', 'icon_paint_normal')->set_active(TRUE);
                    }
                }
            });
            my $item_paintGroup2 = $item_paintNormal->get_group();
            $subMenu_painter->append($item_paintNormal);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'paint_normal', $item_paintNormal);

            my $item_paintWild = Gtk3::RadioMenuItem->new_with_mnemonic(
                $item_paintGroup2,
                'Paint _wilderness rooms',
            );
            if ($self->worldModelObj->painterObj->wildMode eq 'wild') {

                $item_paintWild->set_active(TRUE);
            }
            $item_paintWild->signal_connect('toggled' => sub {

                if ($item_paintWild->get_active) {

                    $self->worldModelObj->painterObj->ivPoke('wildMode', 'wild');

                    # Set the equivalent toolbar button
                    if ($self->ivExists('menuToolItemHash', 'icon_paint_wild')) {

                        $self->ivShow('menuToolItemHash', 'icon_paint_wild')->set_active(TRUE);
                    }
                }
            });
            $subMenu_painter->append($item_paintWild);
            # (Requires $self->session->currentWorld->basicMappingFlag to be FALSE)
            $self->ivAdd('menuToolItemHash', 'paint_wild', $item_paintWild);

            my $item_paintBorder = Gtk3::RadioMenuItem->new_with_mnemonic(
                $item_paintGroup2,
                'Paint wilderness _border rooms',
            );
            if ($self->worldModelObj->painterObj->wildMode eq 'border') {

                $item_paintBorder->set_active(TRUE);
            }
            $item_paintBorder->signal_connect('toggled' => sub {

                if ($item_paintBorder->get_active) {

                    $self->worldModelObj->painterObj->ivPoke('wildMode', 'border');

                    # Set the equivalent toolbar button
                    if ($self->ivExists('menuToolItemHash', 'icon_paint_border')) {

                        $self->ivShow('menuToolItemHash', 'icon_paint_border')->set_active(TRUE);
                    }
                }
            });
            $subMenu_painter->append($item_paintBorder);
            # (Requires $self->session->currentWorld->basicMappingFlag to be FALSE)
            $self->ivAdd('menuToolItemHash', 'paint_border', $item_paintBorder);

            $subMenu_painter->append(Gtk3::SeparatorMenuItem->new());   # Separator

            my $item_repaintCurrentRoom = Gtk3::MenuItem->new('Repaint _current room');
            $item_repaintCurrentRoom->signal_connect('activate' => sub {

                if ($self->mapObj->currentRoom) {

                    # Repaint the current room. The TRUE argument instructs the function to tell
                    #   the world model to redraw the room in every Automapper window
                    $self->paintRoom($self->mapObj->currentRoom, TRUE);
                }
            });
            $subMenu_painter->append($item_repaintCurrentRoom);
            # (Requires $self->currentRegionmap and $self->mapObj->currentRoom)
            $self->ivAdd('menuToolItemHash', 'repaint_current', $item_repaintCurrentRoom);

            my $item_repaintSelectedRooms = Gtk3::MenuItem->new('Repaint _selected rooms');
            $item_repaintSelectedRooms->signal_connect('activate' => sub {

                $self->repaintSelectedRoomsCallback();
            });
            $subMenu_painter->append($item_repaintSelectedRooms);
            # (Requires $self->currentRegionmap and either $self->selectedRoom or
            #   $self->selectedRoomHash)
            $self->ivAdd('menuToolItemHash', 'repaint_selected', $item_repaintSelectedRooms);

            $subMenu_painter->append(Gtk3::SeparatorMenuItem->new());   # Separator

            my $item_editPainter = Gtk3::ImageMenuItem->new('_Edit painter...');
            my $img_editPainter = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
            $item_editPainter->set_image($img_editPainter);
            $item_editPainter->signal_connect('activate' => sub {

                # Open an 'edit' window for the painter object
                $self->createFreeWin(
                    'Games::Axmud::EditWin::Painter',
                    $self,
                    $self->session,
                    'Edit world model painter',
                    $self->worldModelObj->painterObj,
                    FALSE,          # Not temporary
                );
            });
            $subMenu_painter->append($item_editPainter);

            $subMenu_painter->append(Gtk3::SeparatorMenuItem->new());   # Separator

            my $item_resetPainter = Gtk3::MenuItem->new('_Reset painter');
            $item_resetPainter->signal_connect('activate' => sub {

                $self->worldModelObj->resetPainter($self->session);

                $self->showMsgDialogue(
                    'Painter',
                    'info',
                    'The painter object has been reset',
                    'ok',
                );
            });
            $subMenu_painter->append($item_resetPainter);

        my $item_painter = Gtk3::ImageMenuItem->new('_Painter');
        my $img_painter = Gtk3::Image->new_from_stock('gtk-select-color', 'menu');
        $item_painter->set_image($img_painter);
        $item_painter->set_submenu($subMenu_painter);
        $column_mode->append($item_painter);

        $column_mode->append(Gtk3::SeparatorMenuItem->new());   # Separator

            # 'Auto-compare' submenu
            my $subMenu_autoCompare = Gtk3::Menu->new();

            my $item_compareDefault = Gtk3::RadioMenuItem->new_with_mnemonic(
                undef,
                '_Don\'t auto-compare current room',
            );
            $item_compareDefault->signal_connect('toggled' => sub {

                if ($item_compareDefault->get_active) {

                    $self->worldModelObj->setAutoCompareMode('default');
                }
            });
            my $item_compareGroup = $item_compareDefault->get_group();
            $subMenu_autoCompare->append($item_compareDefault);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'auto_compare_default', $item_compareDefault);

            my $item_compareNew = Gtk3::RadioMenuItem->new_with_mnemonic(
                $item_compareGroup,
                'Auto-compare _new rooms',
            );
            if ($self->worldModelObj->autoCompareMode eq 'new') {

                $item_compareNew->set_active(TRUE);
            }
            $item_compareNew->signal_connect('toggled' => sub {

                if ($item_compareNew->get_active) {

                    $self->worldModelObj->setAutoCompareMode('new');
                }
            });
            $subMenu_autoCompare->append($item_compareNew);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'auto_compare_new', $item_compareNew);

            my $item_compareCurrent = Gtk3::RadioMenuItem->new_with_mnemonic(
                $item_compareGroup,
                'Auto-compare the _current room',
            );
            if ($self->worldModelObj->autoCompareMode eq 'current') {

                $item_compareCurrent->set_active(TRUE);
            }
            $item_compareCurrent->signal_connect('toggled' => sub {

                if ($item_compareCurrent->get_active) {

                    $self->worldModelObj->setAutoCompareMode('current');
                }
            });
            $subMenu_autoCompare->append($item_compareCurrent);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'auto_compare_current', $item_compareCurrent);

            $subMenu_autoCompare->append(Gtk3::SeparatorMenuItem->new());   # Separator

            my $item_compareRegion = Gtk3::RadioMenuItem->new_with_mnemonic(
                undef,
                'Compare with rooms in _same region',
            );
            $item_compareRegion->signal_connect('toggled' => sub {

                if ($item_compareRegion->get_active) {

                    $self->worldModelObj->toggleAutoCompareAllFlag(FALSE);
                }
            });
            my $item_compareRegionGroup = $item_compareRegion->get_group();
            $subMenu_autoCompare->append($item_compareRegion);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'auto_compare_region', $item_compareRegion);

            my $item_compareWhole = Gtk3::RadioMenuItem->new_with_mnemonic(
                $item_compareRegionGroup,
                'Compare with rooms in _whole world',
            );
            if ($self->worldModelObj->autoCompareAllFlag) {

                $item_compareWhole->set_active(TRUE);
            }
            $item_compareWhole->signal_connect('toggled' => sub {

                if ($item_compareWhole->get_active) {

                    $self->worldModelObj->toggleAutoCompareAllFlag(TRUE);
                }
            });
            $subMenu_autoCompare->append($item_compareWhole);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'auto_compare_model', $item_compareWhole);

            $subMenu_autoCompare->append(Gtk3::SeparatorMenuItem->new());   # Separator

            my $item_compareMax = Gtk3::MenuItem->new('Set _limit on room comparisons...');
            $item_compareMax->signal_connect('activate' => sub {

                $self->autoCompareMaxCallback();
            });
            $subMenu_autoCompare->append($item_compareMax);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'auto_compare_max', $item_compareMax);

        my $item_autoCompare = Gtk3::MenuItem->new('_Auto-compare');
        $item_autoCompare->set_submenu($subMenu_autoCompare);
        $column_mode->append($item_autoCompare);

            # 'Auto-rescue mode' submenu
            my $subMenu_autoRescue = Gtk3::Menu->new();

            my $item_autoRescueEnable = Gtk3::CheckMenuItem->new('_Enable auto-rescue mode');
            $item_autoRescueEnable->set_active($self->worldModelObj->autoRescueFlag);
            $item_autoRescueEnable->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'autoRescueFlag',
                        $item_autoRescueEnable->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'auto_rescue',
                    );
                }
            });
            $subMenu_autoRescue->append($item_autoRescueEnable);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'auto_rescue', $item_autoRescueEnable);

            $subMenu_autoRescue->append(Gtk3::SeparatorMenuItem->new());   # Separator

            my $item_autoRescueFirst = Gtk3::CheckMenuItem->new(
                '_Merge at first matching room',
            );
            $item_autoRescueFirst->set_active($self->worldModelObj->autoRescueFirstFlag);
            $item_autoRescueFirst->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'autoRescueFirstFlag',
                        $item_autoRescueFirst->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'auto_rescue_prompt',
                    );
                }
            });
            $subMenu_autoRescue->append($item_autoRescueFirst);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'auto_rescue_first', $item_autoRescueFirst);

            my $item_autoRescuePrompt = Gtk3::CheckMenuItem->new('_Prompt before merging');
            $item_autoRescuePrompt->set_active($self->worldModelObj->autoRescuePromptFlag);
            $item_autoRescuePrompt->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'autoRescuePromptFlag',
                        $item_autoRescuePrompt->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'auto_rescue_prompt',
                    );
                }
            });
            $subMenu_autoRescue->append($item_autoRescuePrompt);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'auto_rescue_prompt', $item_autoRescuePrompt);

            $subMenu_autoRescue->append(Gtk3::SeparatorMenuItem->new());   # Separator

            my $item_autoRescueNoMove = Gtk3::CheckMenuItem->new('_Don\'t move non-matching rooms');
            $item_autoRescueNoMove->set_active($self->worldModelObj->autoRescueNoMoveFlag);
            $item_autoRescueNoMove->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'autoRescueNoMoveFlag',
                        $item_autoRescueNoMove->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'auto_rescue_no_move',
                    );
                }
            });
            $subMenu_autoRescue->append($item_autoRescueNoMove);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'auto_rescue_no_move', $item_autoRescueNoMove);

            my $item_autoRescueVisits = Gtk3::CheckMenuItem->new(
                '_Only update visits in merged rooms',
            );
            $item_autoRescueVisits->set_active($self->worldModelObj->autoRescueVisitsFlag);
            $item_autoRescueVisits->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'autoRescueVisitsFlag',
                        $item_autoRescueVisits->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'auto_rescue_visits',
                    );
                }
            });
            $subMenu_autoRescue->append($item_autoRescueVisits);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'auto_rescue_visits', $item_autoRescueVisits);

            my $item_autoRescueForce = Gtk3::CheckMenuItem->new(
                '_Temporarily switch to \'update\' mode',
            );
            $item_autoRescueForce->set_active($self->worldModelObj->autoRescueForceFlag);
            $item_autoRescueForce->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'autoRescueForceFlag',
                        $item_autoRescueForce->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'auto_rescue_force',
                    );
                }
            });
            $subMenu_autoRescue->append($item_autoRescueForce);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'auto_rescue_force', $item_autoRescueForce);

        my $item_autoRescue = Gtk3::MenuItem->new('Auto-r_escue mode');
        $item_autoRescue->set_submenu($subMenu_autoRescue);
        $column_mode->append($item_autoRescue);

            # 'Auto-slide mode' submenu
            my $subMenu_autoSlide = Gtk3::Menu->new();

            my $item_slideMode = Gtk3::RadioMenuItem->new_with_mnemonic(
                undef,
                '_Don\'t auto-slide new rooms',
            );
            $item_slideMode->signal_connect('toggled' => sub {

                if ($item_slideMode->get_active) {

                    $self->worldModelObj->setAutoSlideMode('default');
                }
            });
            my $item_slideGroup = $item_slideMode->get_group();
            $subMenu_autoSlide->append($item_slideMode);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'slide_default', $item_slideMode);

            my $item_slideOrigPull = Gtk3::RadioMenuItem->new_with_mnemonic(
                $item_slideGroup,
                'Slide original room _backwards',
            );
            if ($self->worldModelObj->autoSlideMode eq 'orig_pull') {

                $item_slideOrigPull->set_active(TRUE);
            }
            $item_slideOrigPull->signal_connect('toggled' => sub {

                if ($item_slideOrigPull->get_active) {

                    $self->worldModelObj->setAutoSlideMode('orig_pull');
                }
            });
            $subMenu_autoSlide->append($item_slideOrigPull);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'slide_orig_pull', $item_slideOrigPull);

            my $item_slideOrigPush = Gtk3::RadioMenuItem->new_with_mnemonic(
                $item_slideGroup,
                'Slide original room _forwards',
            );
            if ($self->worldModelObj->autoSlideMode eq 'orig_push') {

                $item_slideOrigPush->set_active(TRUE);
            }
            $item_slideOrigPush->signal_connect('toggled' => sub {

                if ($item_slideOrigPush->get_active) {

                    $self->worldModelObj->setAutoSlideMode('orig_push');
                }
            });
            $subMenu_autoSlide->append($item_slideOrigPush);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'slide_orig_pull', $item_slideOrigPush);

            my $item_slideOtherPull = Gtk3::RadioMenuItem->new_with_mnemonic(
                $item_slideGroup,
                'Slide blocking room b_ackwards',
            );
            if ($self->worldModelObj->autoSlideMode eq 'other_pull') {

                $item_slideOtherPull->set_active(TRUE);
            }
            $item_slideOtherPull->signal_connect('toggled' => sub {

                if ($item_slideOtherPull->get_active) {

                    $self->worldModelObj->setAutoSlideMode('other_pull');
                }
            });
            $subMenu_autoSlide->append($item_slideOtherPull);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'slide_orig_pull', $item_slideOtherPull);

            my $item_slideOtherPush = Gtk3::RadioMenuItem->new_with_mnemonic(
                $item_slideGroup,
                'Slide blocking room f_orwards',
            );
            if ($self->worldModelObj->autoSlideMode eq 'other_push') {

                $item_slideOtherPush->set_active(TRUE);
            }
            $item_slideOtherPush->signal_connect('toggled' => sub {

                if ($item_slideOtherPush->get_active) {

                    $self->worldModelObj->setAutoSlideMode('other_push');
                }
            });
            $subMenu_autoSlide->append($item_slideOtherPush);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'slide_orig_pull', $item_slideOtherPush);

            my $item_slideDestPull = Gtk3::RadioMenuItem->new_with_mnemonic(
                $item_slideGroup,
                'Slide new room ba_ckwards',
            );
            if ($self->worldModelObj->autoSlideMode eq 'dest_pull') {

                $item_slideDestPull->set_active(TRUE);
            }
            $item_slideDestPull->signal_connect('toggled' => sub {

                if ($item_slideDestPull->get_active) {

                    $self->worldModelObj->setAutoSlideMode('dest_pull');
                }
            });
            $subMenu_autoSlide->append($item_slideDestPull);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'slide_orig_pull', $item_slideDestPull);

            my $item_slideDestPush = Gtk3::RadioMenuItem->new_with_mnemonic(
                $item_slideGroup,
                'Slide new room fo_rwards',
            );
            if ($self->worldModelObj->autoSlideMode eq 'dest_push') {

                $item_slideDestPush->set_active(TRUE);
            }
            $item_slideDestPush->signal_connect('toggled' => sub {

                if ($item_slideDestPush->get_active) {

                    $self->worldModelObj->setAutoSlideMode('dest_push');
                }
            });
            $subMenu_autoSlide->append($item_slideDestPush);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'slide_orig_pull', $item_slideDestPush);

            $subMenu_autoSlide->append(Gtk3::SeparatorMenuItem->new());   # Separator

            my $item_slideMax = Gtk3::MenuItem->new('Set _limit on slide distance...');
            $item_slideMax->signal_connect('activate' => sub {

                $self->autoSlideMaxCallback();
            });
            $subMenu_autoSlide->append($item_slideMax);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'slide_max', $item_slideMax);

        my $item_autoSlide = Gtk3::MenuItem->new('Auto-s_lide mode');
        $item_autoSlide->set_submenu($subMenu_autoSlide);
        $column_mode->append($item_autoSlide);

        $column_mode->append(Gtk3::SeparatorMenuItem->new());   # Separator

            # 'Start-up flags' submenu
            my $subMenu_startUpFlags = Gtk3::Menu->new();

            my $item_autoOpenWindow = Gtk3::CheckMenuItem->new('Open _automapper on startup');
            $item_autoOpenWindow->set_active($self->worldModelObj->autoOpenWinFlag);
            $item_autoOpenWindow->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'autoOpenWinFlag',
                        $item_autoOpenWindow->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'auto_open_win',
                    );
                }
            });
            $subMenu_startUpFlags->append($item_autoOpenWindow);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'auto_open_win', $item_autoOpenWindow);

            my $item_pseudoWin = Gtk3::CheckMenuItem->new('Open as _pseudo-window');
            $item_pseudoWin->set_active($self->worldModelObj->pseudoWinFlag);
            $item_pseudoWin->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'pseudoWinFlag',
                        $item_pseudoWin->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'pseudo_win',
                    );
                }
            });
            $subMenu_startUpFlags->append($item_pseudoWin);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'pseudo_win', $item_pseudoWin);

            my $item_allowTrackAlone = Gtk3::CheckMenuItem->new('_Follow character after closing');
            $item_allowTrackAlone->set_active($self->worldModelObj->allowTrackAloneFlag);
            $item_allowTrackAlone->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'allowTrackAloneFlag',
                        $item_allowTrackAlone->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'keep_following',
                    );
                }
            });
            $subMenu_startUpFlags->append($item_allowTrackAlone);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'keep_following', $item_allowTrackAlone);

        my $item_startUpFlags = Gtk3::MenuItem->new('S_tart-up flags');
        $item_startUpFlags->set_submenu($subMenu_startUpFlags);
        $column_mode->append($item_startUpFlags);

            # 'Drawing flags' submenu
            my $subMenu_drawingFlags = Gtk3::Menu->new();

            my $item_roomTagsInCaps = Gtk3::CheckMenuItem->new('_Capitalise room tags');
            $item_roomTagsInCaps->set_active($self->worldModelObj->capitalisedRoomTagFlag);
            $item_roomTagsInCaps->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'capitalisedRoomTagFlag',
                        $item_roomTagsInCaps->get_active(),
                        TRUE,      # Do call $self->redrawRegions
                        'room_tags_capitalised',
                    );
                }
            });
            $subMenu_drawingFlags->append($item_roomTagsInCaps);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'room_tags_capitalised', $item_roomTagsInCaps);

            my $item_drawBentExits = Gtk3::CheckMenuItem->new('Draw _bent broken exits');
            $item_drawBentExits->set_active($self->worldModelObj->drawBentExitsFlag);
            $item_drawBentExits->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'drawBentExitsFlag',
                        $item_drawBentExits->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'draw_bent_exits',
                    );
                }
            });
            $subMenu_drawingFlags->append($item_drawBentExits);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'draw_bent_exits', $item_drawBentExits);

            my $item_drawRoomEcho = Gtk3::CheckMenuItem->new('Draw _room echos');
            $item_drawRoomEcho->set_active($self->worldModelObj->drawRoomEchoFlag);
            $item_drawRoomEcho->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'drawRoomEchoFlag',
                        $item_drawRoomEcho->get_active(),
                        TRUE,      # Do call $self->redrawRegions
                        'draw_room_echo',
                    );
                }
            });
            $subMenu_drawingFlags->append($item_drawRoomEcho);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'draw_room_echo', $item_drawRoomEcho);

            my $item_showTooltips = Gtk3::CheckMenuItem->new('Show _tooltips');
            $item_showTooltips->set_active($self->worldModelObj->showTooltipsFlag);
            $item_showTooltips->signal_connect('toggled' => sub {

                $self->worldModelObj->toggleShowTooltipsFlag(
                    $item_showTooltips->get_active(),
                );
            });
            $subMenu_drawingFlags->append($item_showTooltips);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'show_tooltips', $item_showTooltips);

            my $item_showNotes = Gtk3::CheckMenuItem->new('Show room _notes in tooltips');
            $item_showNotes->set_active($self->worldModelObj->showNotesFlag);
            $item_showNotes->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'showNotesFlag',
                        $item_showNotes->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'show_notes',
                    );
                }
            });
            $subMenu_drawingFlags->append($item_showNotes);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'show_notes', $item_showNotes);

        my $item_drawingFlags = Gtk3::MenuItem->new('Draw_ing flags');
        $item_drawingFlags->set_submenu($subMenu_drawingFlags);
        $column_mode->append($item_drawingFlags);

            # 'Movement flags' submenu
            my $subMenu_moves = Gtk3::Menu->new();

            my $item_allowAssisted = Gtk3::CheckMenuItem->new('_Allow assisted moves');
            $item_allowAssisted->set_active($self->worldModelObj->assistedMovesFlag);
            $item_allowAssisted->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'assistedMovesFlag',
                        $item_allowAssisted->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'allow_assisted_moves',
                    );

                    # The menu items below which set ->protectedMovesFlag and
                    #   ->superProtectedMovesFlag are desensitised if ->assistedMovesFlag is FALSE
                    # Sensitise/desensitise menu bar/toolbar items, depending on current conditions
                    $self->restrictWidgets();
                }
            });
            $subMenu_moves->append($item_allowAssisted);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'allow_assisted_moves', $item_allowAssisted);

            $subMenu_moves->append(Gtk3::SeparatorMenuItem->new()); # Separator

            my $item_assistedBreak = Gtk3::CheckMenuItem->new('_Break doors before move');
            $item_assistedBreak->set_active($self->worldModelObj->assistedBreakFlag);
            $item_assistedBreak->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'assistedBreakFlag',
                        $item_assistedBreak->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'break_before_move',
                    );
                }
            });
            $subMenu_moves->append($item_assistedBreak);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'break_before_move', $item_assistedBreak);

            my $item_assistedPick = Gtk3::CheckMenuItem->new('_Pick doors before move');
            $item_assistedPick->set_active($self->worldModelObj->assistedPickFlag);
            $item_assistedPick->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'assistedPickFlag',
                        $item_assistedPick->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'pick_before_move',
                    );
                }
            });
            $subMenu_moves->append($item_assistedPick);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'pick_before_move', $item_assistedPick);

            my $item_assistedUnlock = Gtk3::CheckMenuItem->new('_Unlock doors before move');
            $item_assistedUnlock->set_active($self->worldModelObj->assistedUnlockFlag);
            $item_assistedUnlock->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'assistedUnlockFlag',
                        $item_assistedUnlock->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'unlock_before_move',
                    );
                }
            });
            $subMenu_moves->append($item_assistedUnlock);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'unlock_before_move', $item_assistedUnlock);

            my $item_assistedOpen = Gtk3::CheckMenuItem->new('_Open doors before move');
            $item_assistedOpen->set_active($self->worldModelObj->assistedOpenFlag);
            $item_assistedOpen->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'assistedOpenFlag',
                        $item_assistedOpen->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'open_before_move',
                    );
                }
            });
            $subMenu_moves->append($item_assistedOpen);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'open_before_move', $item_assistedOpen);

            my $item_assistedClose = Gtk3::CheckMenuItem->new('_Close doors after move');
            $item_assistedClose->set_active($self->worldModelObj->assistedCloseFlag);
            $item_assistedClose->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'assistedCloseFlag',
                        $item_assistedClose->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'close_after_move',
                    );
                }
            });
            $subMenu_moves->append($item_assistedClose);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'close_after_move', $item_assistedClose);

            my $item_assistedLock = Gtk3::CheckMenuItem->new('_Lock doors after move');
            $item_assistedLock->set_active($self->worldModelObj->assistedLockFlag);
            $item_assistedLock->signal_connect('toggled' => sub {

                if (! $self->assistedLockFlag) {

                    $self->worldModelObj->toggleFlag(
                        'assistedLockFlag',
                        $item_assistedLock->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'lock_after_move',
                    );
                }
            });
            $subMenu_moves->append($item_assistedLock);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'lock_after_move', $item_assistedLock);

            $subMenu_moves->append(Gtk3::SeparatorMenuItem->new()); # Separator

            my $item_allowProtected = Gtk3::CheckMenuItem->new('Allow p_rotected moves');
            $item_allowProtected->set_active($self->worldModelObj->protectedMovesFlag);
            $item_allowProtected->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'protectedMovesFlag',
                        $item_allowProtected->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'allow_protected_moves',
                    );

                    # The menu item below which sets ->crafyMovesFlag is desensitised if
                    #   ->assistedMovesFlag is false
                    # Sensitise/desensitise menu bar/toolbar items, depending on current conditions
                    $self->restrictWidgets();
                }
            });
            $subMenu_moves->append($item_allowProtected);
            # (Requires $self->worldModelObj->assistedMovesFlag)
            $self->ivAdd('menuToolItemHash', 'allow_protected_moves', $item_allowProtected);

            my $item_allowSuper = Gtk3::CheckMenuItem->new('Ca_ncel commands when overruled');
            $item_allowSuper->set_active($self->worldModelObj->superProtectedMovesFlag);
            $item_allowSuper->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'superProtectedMovesFlag',
                        $item_allowSuper->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'allow_super_protected_moves',
                    );
                }
            });
            $subMenu_moves->append($item_allowSuper);
            # (Requires $self->worldModelObj->assistedMovesFlag)
            $self->ivAdd('menuToolItemHash', 'allow_super_protected_moves', $item_allowSuper);

            $subMenu_moves->append(Gtk3::SeparatorMenuItem->new()); # Separator

            my $item_allowCrafty = Gtk3::CheckMenuItem->new('Allow crafty _moves');
            $item_allowCrafty->set_active($self->worldModelObj->craftyMovesFlag);
            $item_allowCrafty->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'craftyMovesFlag',
                        $item_allowCrafty->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'allow_crafty_moves',
                    );
                }
            });
            $subMenu_moves->append($item_allowCrafty);
            # (Requires $self->worldModelObj->protectedMovesFlag set to be FALSE)
            $self->ivAdd('menuToolItemHash', 'allow_crafty_moves', $item_allowCrafty);

        my $item_moves = Gtk3::MenuItem->new('Mo_vement flags');
        $item_moves->set_submenu($subMenu_moves);
        $column_mode->append($item_moves);

            # 'Other flags' submenu
            my $subMenu_otherFlags = Gtk3::Menu->new();

            my $item_allowModelScripts = Gtk3::CheckMenuItem->new('_Allow model-wide scripts');
            $item_allowModelScripts->set_active($self->worldModelObj->allowModelScriptFlag);
            $item_allowModelScripts->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'allowModelScriptFlag',
                        $item_allowModelScripts->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'allow_model_scripts',
                    );
                }
            });
            $subMenu_otherFlags->append($item_allowModelScripts);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'allow_model_scripts', $item_allowModelScripts);

            my $item_allowRoomScripts = Gtk3::CheckMenuItem->new(
                'Allow ' . $axmud::BASIC_NAME . ' _scripts',
            );
            $item_allowRoomScripts->set_active($self->worldModelObj->allowRoomScriptFlag);
            $item_allowRoomScripts->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'allowRoomScriptFlag',
                        $item_allowRoomScripts->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'allow_room_scripts',
                    );
                }
            });
            $subMenu_otherFlags->append($item_allowRoomScripts);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'allow_room_scripts', $item_allowRoomScripts);

            my $item_countVisits = Gtk3::CheckMenuItem->new('_Count character visits');
            $item_countVisits->set_active($self->worldModelObj->countVisitsFlag);
            $item_countVisits->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'countVisitsFlag',
                        $item_countVisits->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'count_char_visits',
                    );
                }
            });
            $subMenu_otherFlags->append($item_countVisits);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'count_char_visits', $item_countVisits);

            my $item_disableUpdate = Gtk3::CheckMenuItem->new('_Disable update mode');
            $item_disableUpdate->set_active($self->worldModelObj->disableUpdateModeFlag);
            $item_disableUpdate->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleDisableUpdateModeFlag(
                        $item_disableUpdate->get_active(),
                    );
                }
            });
            $subMenu_otherFlags->append($item_disableUpdate);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'disable_update_mode', $item_disableUpdate);

            my $item_explainGetLost = Gtk3::CheckMenuItem->new('_Explain when getting lost');
            $item_explainGetLost->set_active($self->worldModelObj->explainGetLostFlag);
            $item_explainGetLost->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'explainGetLostFlag',
                        $item_explainGetLost->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'explain_get_lost',
                    );
                }
            });
            $subMenu_otherFlags->append($item_explainGetLost);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'explain_get_lost', $item_explainGetLost);

            my $item_followAnchor = Gtk3::CheckMenuItem->new('New exits for _follow anchors');
            $item_followAnchor->set_active($self->worldModelObj->followAnchorFlag);
            $item_followAnchor->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'followAnchorFlag',
                        $item_followAnchor->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'follow_anchor',
                    );
                }
            });
            $subMenu_otherFlags->append($item_followAnchor);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'follow_anchor', $item_followAnchor);

            my $item_allowCtrlCopy = Gtk3::CheckMenuItem->new('_Move rooms to click with CTRL+C');
            $item_allowCtrlCopy->set_active($self->worldModelObj->allowCtrlCopyFlag);
            $item_allowCtrlCopy->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'allowCtrlCopyFlag',
                        $item_allowCtrlCopy->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'allow_ctrl_copy',
                    );
                }
            });
            $subMenu_otherFlags->append($item_allowCtrlCopy);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'allow_ctrl_copy', $item_allowCtrlCopy);

            my $item_showAllPrimary = Gtk3::CheckMenuItem->new('S_how all directions in dialogues');
            $item_showAllPrimary->set_active($self->worldModelObj->showAllPrimaryFlag);
            $item_showAllPrimary->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'showAllPrimaryFlag',
                        $item_showAllPrimary->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'show_all_primary',
                    );
                }
            });
            $subMenu_otherFlags->append($item_showAllPrimary);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'show_all_primary', $item_showAllPrimary);

        my $item_otherFlags = Gtk3::MenuItem->new('_Other flags');
        $item_otherFlags->set_submenu($subMenu_otherFlags);
        $column_mode->append($item_otherFlags);

        # Setup complete
        return $column_mode;
    }

    sub enableRegionsColumn {

        # Called by $self->enableMenu
        # Sets up the 'Regions' column of the Automapper window's menu bar
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments or if the widget can't be created
        #   Otherwise returns the Gtk3::Menu created

        my ($self, $check) = @_;

        # Check for improper arguments
        if (defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->enableRegionsColumn', @_);
        }

        # Set up column
        my $column_regions = Gtk3::Menu->new();
        if (! $column_regions) {

            return undef;
        }

        my $item_newRegion = Gtk3::ImageMenuItem->new('_New region...');
        my $img_newRegion = Gtk3::Image->new_from_stock('gtk-add', 'menu');
        $item_newRegion->set_image($img_newRegion);
        $item_newRegion->signal_connect('activate' => sub {

            $self->newRegionCallback(FALSE);
        });
        $column_regions->append($item_newRegion);

        my $item_newTempRegion = Gtk3::ImageMenuItem->new('New _temporary region...');
        my $img_newTempRegion = Gtk3::Image->new_from_stock('gtk-add', 'menu');
        $item_newTempRegion->set_image($img_newTempRegion);
        $item_newTempRegion->signal_connect('activate' => sub {

            $self->newRegionCallback(TRUE);
        });
        $column_regions->append($item_newTempRegion);

        $column_regions->append(Gtk3::SeparatorMenuItem->new());    # Separator

        my $item_editRegion = Gtk3::ImageMenuItem->new('_Edit region...');
        my $img_editRegion = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
        $item_editRegion->set_image($img_editRegion);
        $item_editRegion->signal_connect('activate' => sub {

            $self->editRegionCallback();
        });
        $column_regions->append($item_editRegion);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'edit_region', $item_editRegion);

        my $item_editRegionmap = Gtk3::ImageMenuItem->new('Edit _regionmap...');
        my $img_editRegionmap = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
        $item_editRegionmap->set_image($img_editRegionmap);
        $item_editRegionmap->signal_connect('activate' => sub {

            # Open an 'edit' window for the regionmap
            $self->createFreeWin(
                'Games::Axmud::EditWin::Regionmap',
                $self,
                $self->session,
                'Edit \'' . $self->currentRegionmap->name . '\' regionmap',
                $self->currentRegionmap,
                FALSE,          # Not temporary
            );
        });
        $column_regions->append($item_editRegionmap);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'edit_regionmap', $item_editRegionmap);

        $column_regions->append(Gtk3::SeparatorMenuItem->new());    # Separator

            # 'Region list' submenu
            my $subMenu_regionsTree = Gtk3::Menu->new();

            my $item_resetList = Gtk3::MenuItem->new('_Reset region list');
            $item_resetList->signal_connect('activate' => sub {

                $self->worldModelObj->resetRegionList();
            });
            $subMenu_regionsTree->append($item_resetList);

            my $item_reverseList = Gtk3::MenuItem->new('Re_verse region list');
            $item_reverseList->signal_connect('activate' => sub {

                $self->worldModelObj->reverseRegionList();
            });
            $subMenu_regionsTree->append($item_reverseList);

            $subMenu_regionsTree->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $item_moveCurrentRegion = Gtk3::MenuItem->new('_Move current region to top');
            $item_moveCurrentRegion->signal_connect('activate' => sub {

                $self->worldModelObj->moveRegionToTop($self->currentRegionmap);
            });
            $subMenu_regionsTree->append($item_moveCurrentRegion);
            # (Requires $self->currentRegionmap for a region that doesn't have a parent region)
            $self->ivAdd('menuToolItemHash', 'move_region_top', $item_moveCurrentRegion);

            $subMenu_regionsTree->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $item_identifyRegion = Gtk3::MenuItem->new('_Identify highlighted region');
            $item_identifyRegion->signal_connect('activate' => sub {

                $self->identifyRegionCallback();
            });
            $subMenu_regionsTree->append($item_identifyRegion);
            # (Requires $self->treeViewSelectedLine)
            $self->ivAdd('menuToolItemHash', 'identify_region', $item_identifyRegion);

        my $item_regionsTree = Gtk3::MenuItem->new('Region _list');
        $item_regionsTree->set_submenu($subMenu_regionsTree);
        $column_regions->append($item_regionsTree);

            # 'Current region' submenu
            my $subMenu_currentRegion = Gtk3::Menu->new();

            my $item_renameRegion = Gtk3::MenuItem->new('_Rename region...');
            $item_renameRegion->signal_connect('activate' => sub {

                $self->renameRegionCallback();
            });
            $subMenu_currentRegion->append($item_renameRegion);

            my $item_changeParent = Gtk3::MenuItem->new('_Set parent region...');
            $item_changeParent->signal_connect('activate' => sub {

                $self->changeRegionParentCallback();
            });
            $subMenu_currentRegion->append($item_changeParent);

            $subMenu_currentRegion->append(Gtk3::SeparatorMenuItem->new());  # Separator

            my $item_regionFinished = Gtk3::MenuItem->new('Set f_inished region');
            $item_regionFinished->signal_connect('activate' => sub {

                $self->regionFinishedCallback();
            });
            $subMenu_currentRegion->append($item_regionFinished);

            $subMenu_currentRegion->append(Gtk3::SeparatorMenuItem->new());  # Separator

            my $item_convertRegionExit = Gtk3::MenuItem->new('_Convert all region exits');
            $item_convertRegionExit->signal_connect('activate' => sub {

                $self->convertRegionExitCallback(TRUE);
            });
            $subMenu_currentRegion->append($item_convertRegionExit);

            my $item_deconvertRegionExit = Gtk3::MenuItem->new(
                '_Deconvert all super-region exits',
            );
            $item_deconvertRegionExit->signal_connect('activate' => sub {

                $self->convertRegionExitCallback(FALSE);
            });
            $subMenu_currentRegion->append($item_deconvertRegionExit);

            $subMenu_currentRegion->append(Gtk3::SeparatorMenuItem->new());  # Separator

            my $item_resetObjectCounts = Gtk3::MenuItem->new('Reset _object counts');
            $item_resetObjectCounts->signal_connect('activate' => sub {

                 # Empty the hashes which store temporary object counts and redraw the region
                 $self->worldModelObj->resetRegionCounts($self->currentRegionmap);
            });
            $subMenu_currentRegion->append($item_resetObjectCounts);

            my $item_removeRoomFlags = Gtk3::MenuItem->new('Remove room _flags...');
            $item_removeRoomFlags->signal_connect('activate' => sub {

                $self->removeRoomFlagsCallback();
            });
            $subMenu_currentRegion->append($item_removeRoomFlags);

        my $item_currentRegion = Gtk3::MenuItem->new('C_urrent region');
        $item_currentRegion->set_submenu($subMenu_currentRegion);
        $column_regions->append($item_currentRegion);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'current_region', $item_currentRegion);

            # 'Pre-drawn regions' submenu
            my $subMenu_preDrawRegion = Gtk3::Menu->new();

            my $item_allowPreDraw = Gtk3::CheckMenuItem->new('_Allow pre-drawing of maps');
            $item_allowPreDraw->set_active($self->worldModelObj->preDrawAllowFlag);
            $item_allowPreDraw->signal_connect('toggled' => sub {

                $self->worldModelObj->toggleFlag(
                    'preDrawAllowFlag',
                    $item_allowPreDraw->get_active(),
                    FALSE,      # Don't call $self->redrawRegions
                    'allow_pre_draw',
                );
            });
            $subMenu_preDrawRegion->append($item_allowPreDraw);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'allow_pre_draw', $item_allowPreDraw);

            my $item_setPreDrawSize = Gtk3::MenuItem->new('_Set minimum region size');
            $item_setPreDrawSize->signal_connect('activate' => sub {

                $self->preDrawSizeCallback();
            });
            $subMenu_preDrawRegion->append($item_setPreDrawSize);

            my $item_setRetainSize = Gtk3::MenuItem->new('Set minimum retention size');
            $item_setRetainSize->signal_connect('activate' => sub {

                $self->preDrawRetainCallback();
            });
            $subMenu_preDrawRegion->append($item_setRetainSize);

            my $item_setPreDrawSpeed = Gtk3::MenuItem->new('Set pre-draw speed');
            $item_setPreDrawSpeed->signal_connect('activate' => sub {

                $self->preDrawSpeedCallback();
            });
            $subMenu_preDrawRegion->append($item_setPreDrawSpeed);

            $subMenu_preDrawRegion->append(Gtk3::SeparatorMenuItem->new());  # Separator

            my $item_redrawRegion = Gtk3::MenuItem->new('Re_draw this region');
            $item_redrawRegion->signal_connect('activate' => sub {

                $self->redrawRegions($self->currentRegionmap, TRUE);
            });
            $subMenu_preDrawRegion->append($item_redrawRegion);
            # (Requires $self->currentRegionmap)
            $self->ivAdd('menuToolItemHash', 'redraw_region', $item_redrawRegion);

            my $item_redrawAllRegions = Gtk3::MenuItem->new('Redraw _all drawn regions');
            $item_redrawAllRegions->signal_connect('activate' => sub {

                $self->redrawRegionsCallback();
            });
            $subMenu_preDrawRegion->append($item_redrawAllRegions);

        my $item_preDrawRegion = Gtk3::MenuItem->new('_Pre-drawn regions');
        $item_preDrawRegion->set_submenu($subMenu_preDrawRegion);
        $column_regions->append($item_preDrawRegion);

        $column_regions->append(Gtk3::SeparatorMenuItem->new());    # Separator

            # 'Colour schemes' submenu
            my $subMenu_regionScheme = Gtk3::Menu->new();

            my $item_addScheme = Gtk3::MenuItem->new('_Add new colour scheme...');
            $item_addScheme->signal_connect('activate' => sub {

                $self->addRegionSchemeCallback();
            });
            $subMenu_regionScheme->append($item_addScheme);

            my $item_editScheme = Gtk3::MenuItem->new('_Edit colour scheme...');
            $item_editScheme->signal_connect('activate' => sub {

                $self->doRegionSchemeCallback('edit');
            });
            $subMenu_regionScheme->append($item_editScheme);

            my $item_renameScheme = Gtk3::MenuItem->new('_Rename colour scheme...');
            $item_renameScheme->signal_connect('activate' => sub {

                $self->doRegionSchemeCallback('rename');
            });
            $subMenu_regionScheme->append($item_renameScheme);

            my $item_deleteScheme = Gtk3::MenuItem->new('_Delete colour scheme...');
            $item_deleteScheme->signal_connect('activate' => sub {

                $self->doRegionSchemeCallback('delete');
            });
            $subMenu_regionScheme->append($item_deleteScheme);

            $subMenu_regionScheme->append(Gtk3::SeparatorMenuItem->new());  # Separator

                # 'This region' sub-submenu
                my $subSubMenu_thisRegionScheme = Gtk3::Menu->new();

                my $item_attachScheme = Gtk3::MenuItem->new('_Attach colour scheme...');
                $item_attachScheme->signal_connect('activate' => sub {

                    $self->attachRegionSchemeCallback();
                });
                $subSubMenu_thisRegionScheme->append($item_attachScheme);
                # (Requires $self->currentRegionmap and at least one non-default region colour
                #   schemes)
                $self->ivAdd('menuToolItemHash', 'attach_region_scheme', $item_attachScheme);

                my $item_detachScheme = Gtk3::MenuItem->new('_Detach colour scheme');
                $item_detachScheme->signal_connect('activate' => sub {

                    $self->detachRegionSchemeCallback();
                });
                $subSubMenu_thisRegionScheme->append($item_detachScheme);
                # (Requires $self->currentRegionmap with a defined ->regionScheme IV)
                $self->ivAdd('menuToolItemHash', 'detach_region_scheme', $item_detachScheme);

                $subSubMenu_thisRegionScheme->append(Gtk3::SeparatorMenuItem->new());  # Separator

                my $item_editThisScheme = Gtk3::MenuItem->new('_Edit colour scheme...');
                $item_editThisScheme->signal_connect('activate' => sub {

                    $self->doRegionSchemeCallback('edit', $self->currentRegionmap);
                });
                $subSubMenu_thisRegionScheme->append($item_editThisScheme);

            my $item_thisRegionScheme = Gtk3::MenuItem->new('_Current region');
            $item_thisRegionScheme->set_submenu($subSubMenu_thisRegionScheme);
            $subMenu_regionScheme->append($item_thisRegionScheme);
            # (Requires $self->currentRegionmap)
            $self->ivAdd('menuToolItemHash', 'this_region_scheme', $item_thisRegionScheme);

        my $item_colourScheme = Gtk3::MenuItem->new('Colour sc_hemes');
        $item_colourScheme->set_submenu($subMenu_regionScheme);
        $column_regions->append($item_colourScheme);

            # 'Background colours' submenu
            my $subMenu_bgColours = Gtk3::Menu->new();

            my $item_removeBGAll = Gtk3::MenuItem->new('_Remove colour...');
            $item_removeBGAll->signal_connect('activate' => sub {

                $self->removeBGColourCallback();
            });
            $subMenu_bgColours->append($item_removeBGAll);

            my $item_removeBGColour = Gtk3::MenuItem->new('Remove _all colours');
            $item_removeBGColour->signal_connect('activate' => sub {

                $self->removeBGAllCallback();
            });
            $subMenu_bgColours->append($item_removeBGColour);

        my $item_bgColours = Gtk3::MenuItem->new('_Background colours');
        $item_bgColours->set_submenu($subMenu_bgColours);
        $column_regions->append($item_bgColours);
        # (Requires $self->currentRegionmap whose ->gridColourBlockHash and/or ->gridColourObjHash
        #   is not empty)
        $self->ivAdd('menuToolItemHash', 'empty_bg_colours', $item_bgColours);

        $column_regions->append(Gtk3::SeparatorMenuItem->new());    # Separator

            # 'Recalculate paths' submenu
            my $subMenu_recalculatePaths = Gtk3::Menu->new();

            my $item_recalculateInCurrentRegion = Gtk3::MenuItem->new('In _current region');
            $item_recalculateInCurrentRegion->signal_connect('activate' => sub {

                $self->recalculatePathsCallback('current');
            });
            $subMenu_recalculatePaths->append($item_recalculateInCurrentRegion);
            # (Requires $self->currentRegionmap and a non-empty
            #   self->currentRegionmap->gridRoomHash)
            $self->ivAdd(
                'menuToolItemHash',
                'recalculate_in_region',
                $item_recalculateInCurrentRegion,
            );

            my $item_recalculateSelectRegion = Gtk3::MenuItem->new('In _region...');
            $item_recalculateSelectRegion->signal_connect('activate' => sub {

                $self->recalculatePathsCallback('select');
            });
            $subMenu_recalculatePaths->append($item_recalculateSelectRegion);

            my $item_recalculateAllRegions = Gtk3::MenuItem->new('In _all regions');
            $item_recalculateAllRegions->signal_connect('activate' => sub {

                $self->recalculatePathsCallback('all');
            });
            $subMenu_recalculatePaths->append($item_recalculateAllRegions);

            $subMenu_recalculatePaths->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $item_recalculateFromExit = Gtk3::MenuItem->new('For selected _exit');
            $item_recalculateFromExit->signal_connect('activate' => sub {

                $self->recalculatePathsCallback('exit');
            });
            $subMenu_recalculatePaths->append($item_recalculateFromExit);
            # (Requires $self->currentRegionmap and a $self->selectedExit which is a super-region
            #   exit)
            $self->ivAdd('menuToolItemHash', 'recalculate_from_exit', $item_recalculateFromExit);

        my $item_recalculatePaths = Gtk3::MenuItem->new('Re_calculate region paths');
        $item_recalculatePaths->set_submenu($subMenu_recalculatePaths);
        $column_regions->append($item_recalculatePaths);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'recalculate_paths', $item_recalculatePaths);

            # 'Locate current room' submenu
            my $subMenu_locateCurrentRoom = Gtk3::Menu->new();

            my $item_locateInCurrentRegion = Gtk3::MenuItem->new('In _current region');
            $item_locateInCurrentRegion->signal_connect('activate' => sub {

                $self->locateCurrentRoomCallback('current');
            });
            $subMenu_locateCurrentRoom->append($item_locateInCurrentRegion);
            # (Requires $self->currentRegionmap and a non-empty GA::Obj::Regionmap->gridRoomHash)
            $self->ivAdd('menuToolItemHash', 'locate_room_in_current', $item_locateInCurrentRegion);

            my $item_locateInSelectRegion = Gtk3::MenuItem->new('In _region...');
            $item_locateInSelectRegion->signal_connect('activate' => sub {

                $self->locateCurrentRoomCallback('select');
            });
            $subMenu_locateCurrentRoom->append($item_locateInSelectRegion);

            my $item_locateInAllRegions = Gtk3::MenuItem->new('In _all regions');
            $item_locateInAllRegions->signal_connect('activate' => sub {

                $self->locateCurrentRoomCallback('all');
            });
            $subMenu_locateCurrentRoom->append($item_locateInAllRegions);

        my $item_locateCurrentRoom = Gtk3::ImageMenuItem->new('L_ocate current room');
        my $img_locateCurrentRoom = Gtk3::Image->new_from_stock('gtk-find', 'menu');
        $item_locateCurrentRoom->set_image($img_locateCurrentRoom);
        $item_locateCurrentRoom->set_submenu($subMenu_locateCurrentRoom);
        $column_regions->append($item_locateCurrentRoom);

            # 'Screenshots' submenu
            my $subMenu_screenshots = Gtk3::Menu->new();

            my $item_visibleScreenshot = Gtk3::MenuItem->new('_Visible map');
            $item_visibleScreenshot->signal_connect('activate' => sub {

                $self->regionScreenshotCallback('visible');
            });
            $subMenu_screenshots->append($item_visibleScreenshot);

            my $item_occupiedScreenshot = Gtk3::MenuItem->new('_Occupied portion');
            $item_occupiedScreenshot->signal_connect('activate' => sub {

                $self->regionScreenshotCallback('occupied');
            });
            $subMenu_screenshots->append($item_occupiedScreenshot);

            my $item_wholeScreenshot = Gtk3::MenuItem->new('_Whole region');
            $item_wholeScreenshot->signal_connect('activate' => sub {

                $self->regionScreenshotCallback('whole');
            });
            $subMenu_screenshots->append($item_wholeScreenshot);

        my $item_screenshots = Gtk3::MenuItem->new('Take _screenshot');
        $item_screenshots->set_submenu($subMenu_screenshots);
        $column_regions->append($item_screenshots);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'screenshots', $item_screenshots);

        $column_regions->append(Gtk3::SeparatorMenuItem->new());    # Separator

        my $item_emptyRegion = Gtk3::MenuItem->new('E_mpty region');
        $item_emptyRegion->signal_connect('activate' => sub {

            $self->emptyRegionCallback();
        });
        $column_regions->append($item_emptyRegion);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'empty_region', $item_emptyRegion);

        my $item_deleteRegion = Gtk3::ImageMenuItem->new('_Delete region');
        my $img_deleteRegion = Gtk3::Image->new_from_stock('gtk-delete', 'menu');
        $item_deleteRegion->set_image($img_deleteRegion);
        $item_deleteRegion->signal_connect('activate' => sub {

            $self->deleteRegionCallback();
        });
        $column_regions->append($item_deleteRegion);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'delete_region', $item_deleteRegion);

        my $item_deleteTempRegion = Gtk3::ImageMenuItem->new('Delete temporar_y regions');
        my $img_deleteTempRegion = Gtk3::Image->new_from_stock('gtk-delete', 'menu');
        $item_deleteTempRegion->set_image($img_deleteTempRegion);
        $item_deleteTempRegion->signal_connect('activate' => sub {

            $self->deleteTempRegionsCallback();
        });
        $column_regions->append($item_deleteTempRegion);

        # Setup complete
        return $column_regions;
    }

    sub enableRoomsColumn {

        # Called by $self->enableMenu
        # Sets up the 'Rooms' column of the Automapper window's menu bar
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments or if the widget can't be created
        #   Otherwise returns the Gtk3::Menu created

        my ($self, $check) = @_;

        # Check for improper arguments
        if (defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->enableRoomsColumn', @_);
        }

        # Set up column
        my $column_rooms = Gtk3::Menu->new();
        if (! $column_rooms) {

            return undef;
        }

        my $item_setCurrentRoom = Gtk3::MenuItem->new('_Set current room');
        $item_setCurrentRoom->signal_connect('activate' => sub {

            $self->mapObj->setCurrentRoom($self->selectedRoom);
        });
        $column_rooms->append($item_setCurrentRoom);
        # (Requires $self->currentRegionmap & $self->selectedRoom)
        $self->ivAdd('menuToolItemHash', 'set_current_room', $item_setCurrentRoom);

        my $item_unsetCurrentRoom = Gtk3::MenuItem->new('_Unset current room');
        $item_unsetCurrentRoom->signal_connect('activate' => sub {

            # This function automatically redraws the room
            $self->mapObj->setCurrentRoom();
        });
        $column_rooms->append($item_unsetCurrentRoom);
        # (Requires $self->currentRegionmap & $self->mapObj->currentRoom)
        $self->ivAdd('menuToolItemHash', 'unset_current_room', $item_unsetCurrentRoom);

        $column_rooms->append(Gtk3::SeparatorMenuItem->new());  # Separator

            # 'Locator task' submenu
            my $subMenu_locatorTask = Gtk3::Menu->new();

            my $item_resetLocator = Gtk3::MenuItem->new('_Reset Locator');
            $item_resetLocator->signal_connect('activate' => sub {

                $self->resetLocatorCallback();
            });
            $subMenu_locatorTask->append($item_resetLocator);
            # (Requires $self->currentRegionmap)
            $self->ivAdd('menuToolItemHash', 'reset_locator', $item_resetLocator);

            my $item_updateLocator = Gtk3::MenuItem->new('_Update Locator');
            $item_updateLocator->signal_connect('activate' => sub {

                # Update the Locator task
                $self->mapObj->updateLocator();
            });
            $subMenu_locatorTask->append($item_updateLocator);
            # (Requires $self->currentRegionmap & $self->mapObj->currentRoom)
            $self->ivAdd('menuToolItemHash', 'update_locator', $item_updateLocator);

            $subMenu_locatorTask->append(Gtk3::SeparatorMenuItem->new());  # Separator

            my $item_setFacing = Gtk3::MenuItem->new('_Set facing direction...');
            $item_setFacing->signal_connect('activate' => sub {

                $self->setFacingCallback();
            });
            $subMenu_locatorTask->append($item_setFacing);

            my $item_resetFacing = Gtk3::MenuItem->new('R_eset facing direction...');
            $item_resetFacing->signal_connect('activate' => sub {

                $self->resetFacingCallback();
            });
            $subMenu_locatorTask->append($item_resetFacing);

            $subMenu_locatorTask->append(Gtk3::SeparatorMenuItem->new());  # Separator

            my $item_viewLocatorRoom = Gtk3::MenuItem->new('_View Locator room...');
            $item_viewLocatorRoom->signal_connect('activate' => sub {

                $self->editLocatorRoomCallback();
            });
            $subMenu_locatorTask->append($item_viewLocatorRoom);

        my $item_locatorTask = Gtk3::MenuItem->new('_Locator task');
        $item_locatorTask->set_submenu($subMenu_locatorTask);
        $column_rooms->append($item_locatorTask);

            # 'Pathfinding' submenu
            my $subMenu_pathFinding = Gtk3::Menu->new();

            my $item_highlightPath = Gtk3::MenuItem->new('_Highlight path');
            $item_highlightPath->signal_connect('activate' => sub {

                $self->processPathCallback('select_room');
            });
            $subMenu_pathFinding->append($item_highlightPath);
            # (Requires $self->currentRegionmap, $self->mapObj->currentRoom and $self->selectedRoom)
            $self->ivAdd('menuToolItemHash', 'path_finding_highlight', $item_highlightPath);

            my $item_displayPath = Gtk3::MenuItem->new('_Edit path...');
            $item_displayPath->signal_connect('activate' => sub {

                $self->processPathCallback('pref_win');
            });
            $subMenu_pathFinding->append($item_displayPath);
            # (Requires $self->currentRegionmap, $self->mapObj->currentRoom and $self->selectedRoom)
            $self->ivAdd('menuToolItemHash', 'path_finding_edit', $item_displayPath);

            my $item_goToRoom = Gtk3::MenuItem->new('_Go to room');
            $item_goToRoom->signal_connect('activate' => sub {

                $self->processPathCallback('send_char');
            });
            $subMenu_pathFinding->append($item_goToRoom);
            # (Requires $self->currentRegionmap, $self->mapObj->currentRoom and $self->selectedRoom)
            $self->ivAdd('menuToolItemHash', 'path_finding_go', $item_goToRoom);

            $subMenu_pathFinding->append(Gtk3::SeparatorMenuItem->new());   # Separator

            my $item_allowPostProcessing = Gtk3::CheckMenuItem->new('_Allow post-processing');
            $item_allowPostProcessing->set_active($self->worldModelObj->postProcessingFlag);
            $item_allowPostProcessing->signal_connect('toggled' => sub {

                $self->worldModelObj->toggleFlag(
                    'postProcessingFlag',
                    $item_allowPostProcessing->get_active(),
                    FALSE,      # Don't call $self->redrawRegions
                    'allow_post_process',
                );
            });
            $subMenu_pathFinding->append($item_allowPostProcessing);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'allow_post_process', $item_allowPostProcessing);

            my $item_avoidHazardousRooms = Gtk3::CheckMenuItem->new('A_void hazardous rooms');
            $item_avoidHazardousRooms->set_active($self->worldModelObj->avoidHazardsFlag);
            $item_avoidHazardousRooms->signal_connect('toggled' => sub {

                $self->worldModelObj->toggleFlag(
                    'avoidHazardsFlag',
                    $item_avoidHazardousRooms->get_active(),
                    FALSE,      # Don't call $self->redrawRegions
                    'allow_hazard_rooms',
                );
            });
            $subMenu_pathFinding->append($item_avoidHazardousRooms);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'allow_hazard_rooms', $item_avoidHazardousRooms);

            my $item_doubleClickPathFind = Gtk3::CheckMenuItem->new(
                'Allow _double-click moves',
            );
            $item_doubleClickPathFind->set_active($self->worldModelObj->quickPathFindFlag);
            $item_doubleClickPathFind->signal_connect('toggled' => sub {

                $self->worldModelObj->toggleFlag(
                    'quickPathFindFlag',
                    $item_doubleClickPathFind->get_active(),
                    FALSE,      # Don't call $self->redrawRegions
                    'allow_quick_path_find',
                );
            });
            $subMenu_pathFinding->append($item_doubleClickPathFind);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'allow_quick_path_find', $item_doubleClickPathFind);

            $subMenu_pathFinding->append(Gtk3::SeparatorMenuItem->new());   # Separator

            my $item_adjacentMode = Gtk3::MenuItem->new('_Set adjacent regions mode...');
            $item_adjacentMode->signal_connect('activate' => sub {

                $self->adjacentModeCallback();
            });
            $subMenu_pathFinding->append($item_adjacentMode);

        my $item_pathFinding = Gtk3::MenuItem->new('_Pathfinding');
        $item_pathFinding->set_submenu($subMenu_pathFinding);
        $column_rooms->append($item_pathFinding);

            # 'Move rooms/labels' submenu
            my $subMenu_moveRooms = Gtk3::Menu->new();

            my $item_moveSelected = Gtk3::MenuItem->new('Move in _direction...');
            $item_moveSelected->signal_connect('activate' => sub {

                $self->moveSelectedRoomsCallback();
            });
            $subMenu_moveRooms->append($item_moveSelected);
            # (Requires $self->currentRegionmap and one or more selected rooms)
            $self->ivAdd('menuToolItemHash', 'move_rooms_dir', $item_moveSelected);

            my $item_moveSelectedToClick = Gtk3::MenuItem->new('Move to _click');
            $item_moveSelectedToClick->signal_connect('activate' => sub {

                # Set the free clicking mode: $self->mouseClickEvent will move the objects when the
                #   user next clicks on an empty part of the map
                $self->set_freeClickMode('move_room');
            });
            $subMenu_moveRooms->append($item_moveSelectedToClick);
            # (Requires $self->currentRegionmap and one or more selected rooms)
            $self->ivAdd('menuToolItemHash', 'move_rooms_click', $item_moveSelectedToClick);

            $subMenu_moveRooms->append(Gtk3::SeparatorMenuItem->new());  # Separator

                # 'Transfer to region' sub-submenu
                my $subSubMenu_transferRegion = Gtk3::Menu->new();

                if ($self->recentRegionList) {

                    foreach my $name ($self->recentRegionList) {

                        my $item_regionName = Gtk3::MenuItem->new($name);
                        $item_regionName->signal_connect('activate' => sub {

                            $self->transferSelectedRoomsCallback($name);
                        });
                        $subSubMenu_transferRegion->append($item_regionName);
                    }

                } else {

                    my $item_regionNone = Gtk3::MenuItem->new('(No recent regions)');
                    $item_regionNone->set_sensitive(FALSE);
                    $subSubMenu_transferRegion->append($item_regionNone);
                }

                $subSubMenu_transferRegion->append(Gtk3::SeparatorMenuItem->new());  # Separator

                my $item_transferSelect = Gtk3::MenuItem->new('Select region...');
                $item_transferSelect->signal_connect('activate' => sub {

                    $self->transferSelectedRoomsCallback();
                });
                $subSubMenu_transferRegion->append($item_transferSelect);

            my $item_transferRegion = Gtk3::MenuItem->new('_Transfer to region');
            $item_transferRegion->set_submenu($subSubMenu_transferRegion);
            $subMenu_moveRooms->append($item_transferRegion);
            # (Requires $self->currentRegionmap, one or more selected rooms and at least two regions
            #   in the world model)
            $self->ivAdd('menuToolItemHash', 'transfer_to_region', $item_transferRegion);

            $subMenu_moveRooms->append(Gtk3::SeparatorMenuItem->new());  # Separator

            my $item_mergeMoveRooms = Gtk3::MenuItem->new('_Merge/move rooms');
            $item_mergeMoveRooms->signal_connect('activate' => sub {

                $self->doMerge($self->mapObj->currentRoom);
            });
            $subMenu_moveRooms->append($item_mergeMoveRooms);
            # (Requires $self->currentRegionmap, a current room and the automapper object being set
            #   up to perform a merge)
            $self->ivAdd('menuToolItemHash', 'move_merge_rooms', $item_mergeMoveRooms);

        my $item_moveRooms = Gtk3::MenuItem->new('_Move rooms/labels');
        $item_moveRooms->set_submenu($subMenu_moveRooms);
        $column_rooms->append($item_moveRooms);
        # (Requires $self->currentRegionmap and EITHER one or more selected rooms OR a current room
        #   and the automapper being set up to perform a merge)
        $self->ivAdd('menuToolItemHash', 'move_rooms_labels', $item_moveRooms);

        $column_rooms->append(Gtk3::SeparatorMenuItem->new());  # Separator

            # 'Add room' submenu
            my $subMenu_addRoom = Gtk3::Menu->new();

            my $item_addFirstRoom = Gtk3::MenuItem->new('Add _first room');
            $item_addFirstRoom->signal_connect('activate' => sub {

                $self->addFirstRoomCallback();
            });
            $subMenu_addRoom->append($item_addFirstRoom);
            # (Requires $self->currentRegionmap & an empty $self->currentRegionmap->gridRoomHash)
            $self->ivAdd('menuToolItemHash', 'add_first_room', $item_addFirstRoom);

            my $item_addRoomAtClick = Gtk3::MenuItem->new('Add room at _click');
            $item_addRoomAtClick->signal_connect('activate' => sub {

                # Set the free clicking mode: $self->mouseClickEvent will create the new room when
                #   the user next clicks on an empty part of the map
                if ($self->currentRegionmap) {

                    $self->set_freeClickMode('add_room');
                }
            });
            $subMenu_addRoom->append($item_addRoomAtClick);

            my $item_addRoomAtBlock = Gtk3::MenuItem->new('Add room at _block...');
            $item_addRoomAtBlock->signal_connect('activate' => sub {

                $self->addRoomAtBlockCallback();
            });
            $subMenu_addRoom->append($item_addRoomAtBlock);

        my $item_addRoom = Gtk3::ImageMenuItem->new('Add _room');
        my $img_addRoom = Gtk3::Image->new_from_stock('gtk-add', 'menu');
        $item_addRoom->set_image($img_addRoom);
        $item_addRoom->set_submenu($subMenu_addRoom);
        $column_rooms->append($item_addRoom);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'add_room', $item_addRoom);

            # 'Add pattern' submenu
            my $subMenu_exitPatterns = Gtk3::Menu->new();

            my $item_addFailedExitWorld = Gtk3::MenuItem->new('Add failed exit to _world...');
            $item_addFailedExitWorld->signal_connect('activate' => sub {

                $self->addFailedExitCallback(TRUE);
            });
            $subMenu_exitPatterns->append($item_addFailedExitWorld);

            my $item_addFailedExitRoom = Gtk3::MenuItem->new('Add failed exit to current _room...');
            $item_addFailedExitRoom->signal_connect('activate' => sub {

                $self->addFailedExitCallback(FALSE, $self->mapObj->currentRoom);
            });
            $subMenu_exitPatterns->append($item_addFailedExitRoom);
            # (Requires $self->currentRegionmap & $self->mapObj->currentRoom)
            $self->ivAdd('menuToolItemHash', 'add_failed_room', $item_addFailedExitRoom);

            $subMenu_exitPatterns->append(Gtk3::SeparatorMenuItem->new()); # Separator

            my $item_addInvoluntaryExitRoom = Gtk3::MenuItem->new(
                'Add _involuntary exit to current room...',
            );
            $item_addInvoluntaryExitRoom->signal_connect('activate' => sub {

                $self->addInvoluntaryExitCallback($self->mapObj->currentRoom);
            });
            $subMenu_exitPatterns->append($item_addInvoluntaryExitRoom);
            # (Requires $self->currentRegionmap & $self->mapObj->currentRoom)
            $self->ivAdd('menuToolItemHash', 'add_involuntary_exit', $item_addInvoluntaryExitRoom);

            my $item_addRepulseExitRoom = Gtk3::MenuItem->new(
                'Add r_epulse exit to current room...',
            );
            $item_addRepulseExitRoom->signal_connect('activate' => sub {

                $self->addRepulseExitCallback($self->mapObj->currentRoom);
            });
            $subMenu_exitPatterns->append($item_addRepulseExitRoom);
            # (Requires $self->currentRegionmap & $self->mapObj->currentRoom)
            $self->ivAdd('menuToolItemHash', 'add_repulse_exit', $item_addRepulseExitRoom);

            $subMenu_exitPatterns->append(Gtk3::SeparatorMenuItem->new()); # Separator

            my $item_addSpecialDepartRoom = Gtk3::MenuItem->new(
                'Add _special departure to current room...',
            );
            $item_addSpecialDepartRoom->signal_connect('activate' => sub {

                $self->addSpecialDepartureCallback($self->mapObj->currentRoom);
            });
            $subMenu_exitPatterns->append($item_addSpecialDepartRoom);
            # (Requires $self->currentRegionmap & $self->mapObj->currentRoom)
            $self->ivAdd('menuToolItemHash', 'add_special_depart', $item_addSpecialDepartRoom);

            my $item_addUnspecifiedRoom = Gtk3::MenuItem->new(
                'Add _unspecified room pattern...',
            );
            $item_addUnspecifiedRoom->signal_connect('activate' => sub {

                $self->addUnspecifiedPatternCallback($self->mapObj->currentRoom);
            });
            $subMenu_exitPatterns->append($item_addUnspecifiedRoom);
            # (Requires $self->currentRegionmap & $self->mapObj->currentRoom)
            $self->ivAdd('menuToolItemHash', 'add_unspecified_pattern', $item_addUnspecifiedRoom);

        my $item_exitPatterns = Gtk3::MenuItem->new('Add p_attern');
        $item_exitPatterns->set_submenu($subMenu_exitPatterns);
        $column_rooms->append($item_exitPatterns);

            # 'Add to model' submenu
            my $subMenu_addToModel = Gtk3::Menu->new();

            my $item_addRoomContents = Gtk3::MenuItem->new('Add _contents...');
            $item_addRoomContents->signal_connect('activate' => sub {

                $self->addContentsCallback(FALSE);
            });
            $subMenu_addToModel->append($item_addRoomContents);
            # Requires $self->currentRegionmap, $self->mapObj->currentRoom
            $self->ivAdd('menuToolItemHash', 'add_room_contents', $item_addRoomContents);

            my $item_addContentsString = Gtk3::MenuItem->new('Add c_ontents from string...');
            $item_addContentsString->signal_connect('activate' => sub {

                $self->addContentsCallback(TRUE);
            });
            $subMenu_addToModel->append($item_addContentsString);
            # Requires $self->currentRegionmap, $self->selectedRoom
            $self->ivAdd('menuToolItemHash', 'add_contents_string', $item_addContentsString);

            $subMenu_addToModel->append(Gtk3::SeparatorMenuItem->new()); # Separator

            my $item_addHiddenObj = Gtk3::MenuItem->new('Add _hidden object...');
            $item_addHiddenObj->signal_connect('activate' => sub {

                $self->addHiddenObjCallback(FALSE);
            });
            $subMenu_addToModel->append($item_addHiddenObj);
            # Requires $self->currentRegionmap, $self->mapObj->currentRoom
            $self->ivAdd('menuToolItemHash', 'add_hidden_object', $item_addHiddenObj);

            my $item_addHiddenString = Gtk3::MenuItem->new('Add h_idden object from string...');
            $item_addHiddenString->signal_connect('activate' => sub {

                $self->addHiddenObjCallback(TRUE);
            });
            $subMenu_addToModel->append($item_addHiddenString);
            # Requires $self->currentRegionmap, $self->selectedRoom
            $self->ivAdd('menuToolItemHash', 'add_hidden_string', $item_addHiddenString);

            $subMenu_addToModel->append(Gtk3::SeparatorMenuItem->new()); # Separator

            my $item_addSearchResult = Gtk3::MenuItem->new('Add _search result...');
            $item_addSearchResult->signal_connect('activate' => sub {

                $self->addSearchResultCallback();
            });
            $subMenu_addToModel->append($item_addSearchResult);
            # Requires $self->currentRegionmap and $self->mapObj->currentRoom
            $self->ivAdd('menuToolItemHash', 'add_search_result', $item_addSearchResult);

        my $item_addToModel = Gtk3::MenuItem->new('Add to m_odel');
        $item_addToModel->set_submenu($subMenu_addToModel);
        $column_rooms->append($item_addToModel);
        # Requires $self->currentRegionmap and either $self->mapObj->currentRoom or
        #   $self->selectedRoom
        $self->ivAdd('menuToolItemHash', 'add_to_model', $item_addToModel);

        $column_rooms->append(Gtk3::SeparatorMenuItem->new());  # Separator

            # 'Add/set exits' submenu
            my $subMenu_setExits = Gtk3::Menu->new();

            my $item_addNormal = Gtk3::MenuItem->new('Add _normal exit...');
            $item_addNormal->signal_connect('activate' => sub {

                $self->addExitCallback(FALSE);  # FALSE - not a hidden exit
            });
            $subMenu_setExits->append($item_addNormal);
            # (Requires $self->currentRegionmap and a $self->selectedRoom whose ->wildMode is not
            #   'wild' - the value 'border' is ok, though)
            $self->ivAdd('menuToolItemHash', 'add_normal_exit', $item_addNormal);

            my $item_addHiddenExit = Gtk3::MenuItem->new('Add _hidden exit...');
            $item_addHiddenExit->signal_connect('activate' => sub {

                $self->addExitCallback(TRUE);   # TRUE - a hidden exit
            });
            $subMenu_setExits->append($item_addHiddenExit);
            # (Requires $self->currentRegionmap and a $self->selectedRoom whose ->wildMode is not
            #   'wild' - the value 'border' is ok, though)
            $self->ivAdd('menuToolItemHash', 'add_hidden_exit', $item_addHiddenExit);

            $subMenu_setExits->append(Gtk3::SeparatorMenuItem->new()); # Separator

            my $item_addMultiple = Gtk3::MenuItem->new('Add _multiple exits...');
            $item_addMultiple->signal_connect('activate' => sub {

                $self->addMultipleExitsCallback();
            });
            $subMenu_setExits->append($item_addMultiple);
            # (Requires $self->currentRegionmap and one or more selected rooms)
            $self->ivAdd('menuToolItemHash', 'add_multiple_exits', $item_addMultiple);

            $subMenu_setExits->append(Gtk3::SeparatorMenuItem->new()); # Separator

            my $item_removeChecked = Gtk3::MenuItem->new('Remove _checked direction...');
            $item_removeChecked->signal_connect('activate' => sub {

                $self->removeCheckedDirCallback(FALSE);
            });
            $subMenu_setExits->append($item_removeChecked);
            # (Require a current regionmap, a single selected room that has one or more checked
            #   directions)
            $self->ivAdd('menuToolItemHash', 'remove_checked', $item_removeChecked);

            my $item_removeCheckedAll = Gtk3::MenuItem->new('Remove _all checked directions');
            $item_removeCheckedAll->signal_connect('activate' => sub {

                $self->removeCheckedDirCallback(TRUE);
            });
            $subMenu_setExits->append($item_removeCheckedAll);
            # (Require a current regionmap, a single selected room that has one or more checked
            #   directions)
            $self->ivAdd('menuToolItemHash', 'remove_checked_all', $item_removeCheckedAll);

            $subMenu_setExits->append(Gtk3::SeparatorMenuItem->new()); # Separator

            my $item_markNormal = Gtk3::MenuItem->new('Mark room(s) as n_ormal');
            $item_markNormal->signal_connect('activate' => sub {

                $self->setWildCallback('normal');
            });
            $subMenu_setExits->append($item_markNormal);
            # (Require a current regionmap and one or more selected rooms)
            $self->ivAdd('menuToolItemHash', 'wilderness_normal', $item_markNormal);

            my $item_markWild = Gtk3::MenuItem->new('Mark room(s) as _wilderness');
            $item_markWild->signal_connect('activate' => sub {

                $self->setWildCallback('wild');
            });
            $subMenu_setExits->append($item_markWild);
            # (Require a current regionmap, one or more selected rooms and
            #   $self->session->currentWorld->basicMappingFlag to be FALSE)
            $self->ivAdd('menuToolItemHash', 'wilderness_wild', $item_markWild);

            my $item_markBorder = Gtk3::MenuItem->new('Mark room(s) as wilderness _border');
            $item_markBorder->signal_connect('activate' => sub {

                $self->setWildCallback('border');
            });
            $subMenu_setExits->append($item_markBorder);
            # (Require a current regionmap, one or more selected rooms and
            #   $self->session->currentWorld->basicMappingFlag to be FALSE)
            $self->ivAdd('menuToolItemHash', 'wilderness_border', $item_markBorder);

        my $item_setExits = Gtk3::ImageMenuItem->new('Add/set _exits');
        my $img_setExits = Gtk3::Image->new_from_stock('gtk-add', 'menu');
        $item_setExits->set_image($img_setExits);
        $item_setExits->set_submenu($subMenu_setExits);
        $column_rooms->append($item_setExits);
        # (Require a current regionmap and one or more selected rooms)
        $self->ivAdd('menuToolItemHash', 'set_exits', $item_setExits);

        my $item_selectExit = Gtk3::MenuItem->new('Select e_xit in room...');
        $item_selectExit->signal_connect('activate' => sub {

            $self->selectExitCallback();
        });
        $column_rooms->append($item_selectExit);
        # (Requires $self->currentRegionmap & $self->selectedRoom)
        $self->ivAdd('menuToolItemHash', 'select_exit', $item_selectExit);

        $column_rooms->append(Gtk3::SeparatorMenuItem->new());  # Separator

        my $item_editRoom = Gtk3::ImageMenuItem->new('Ed_it room...');
        my $img_editRoom = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
        $item_editRoom->set_image($img_editRoom);
        $item_editRoom->signal_connect('activate' => sub {

            # Open the room's 'edit' window
            $self->createFreeWin(
                'Games::Axmud::EditWin::ModelObj::Room',
                $self,
                $self->session,
                'Edit ' . $self->selectedRoom->category . ' model object',
                $self->selectedRoom,
                FALSE,                          # Not temporary
            );
        });
        $column_rooms->append($item_editRoom);
        # (Requires $self->currentRegionmap & $self->selectedRoom)
        $self->ivAdd('menuToolItemHash', 'edit_room', $item_editRoom);

            # 'Room text' submenu
            my $subMenu_roomText = Gtk3::Menu->new();

            my $item_setRoomTag = Gtk3::MenuItem->new('Set room _tag...');
            $item_setRoomTag->signal_connect('activate' => sub {

                $self->setRoomTagCallback();
            });
            $subMenu_roomText->append($item_setRoomTag);
            # (Requires $self->currentRegionmap and either $self->selectedRoom or
            #   $self->selectedRoomTag)
            $self->ivAdd('menuToolItemHash', 'set_room_tag', $item_setRoomTag);

            my $item_setGuild = Gtk3::MenuItem->new('Set room _guild...');
            $item_setGuild->signal_connect('activate' => sub {

                $self->setRoomGuildCallback();
            });
            $subMenu_roomText->append($item_setGuild);
            # (Requires $self->currentRegionmap and one or more of $self->selectedRoom,
            #   $self->selectedRoomHash, $self->selectedRoomGuild, $self->selectedRoomGuildHash)
            $self->ivAdd('menuToolItemHash', 'set_room_guild', $item_setGuild);

            $subMenu_roomText->append(Gtk3::SeparatorMenuItem->new());  # Separator

            my $item_resetPositions = Gtk3::MenuItem->new('_Reset text positions');
            $item_resetPositions->signal_connect('activate' => sub {

                $self->resetRoomOffsetsCallback();
            });
            $subMenu_roomText->append($item_resetPositions);
            # (Requires $self->currentRegionmap & $self->selectedRoom)
            $self->ivAdd('menuToolItemHash', 'reset_positions', $item_resetPositions);

            $subMenu_roomText->append(Gtk3::SeparatorMenuItem->new());  # Separator

        my $item_roomText = Gtk3::MenuItem->new('Set room _text');
        $item_roomText->set_submenu($subMenu_roomText);
        $column_rooms->append($item_roomText);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'room_text', $item_roomText);

            # 'Toggle room flag' submenu
            my $subMenu_toggleRoomFlag = Gtk3::Menu->new();

            if ($self->worldModelObj->roomFlagShowMode eq 'default') {

                # Show all room flags, sorted by filter
                foreach my $filter ($axmud::CLIENT->constRoomFilterList) {

                    # A sub-sub menu for $filter
                    my $subSubMenu_filter = Gtk3::Menu->new();

                    my @nameList = $self->worldModelObj->getRoomFlagsInFilter($filter);
                    foreach my $name (@nameList) {

                        my $obj = $self->worldModelObj->ivShow('roomFlagHash', $name);
                        if ($obj) {

                            my $menuItem = Gtk3::MenuItem->new($obj->descrip);
                            $menuItem->signal_connect('activate' => sub {

                                # Toggle the flags for all selected rooms, redraw them and (if the
                                #   flag is one of the hazardous room flags) recalculate the
                                #   regionmap's paths. The TRUE argument tells the world model to
                                #   redraw the rooms
                                $self->worldModelObj->toggleRoomFlags(
                                    $self->session,
                                    TRUE,
                                    $obj->name,
                                    $self->compileSelectedRooms(),
                                );
                            });
                            $subSubMenu_filter->append($menuItem);
                        }
                    }

                    if (! @nameList) {

                        my $menuItem = Gtk3::MenuItem->new('(No flags in this filter)');
                        $menuItem->set_sensitive(FALSE);
                        $subSubMenu_filter->append($menuItem);
                    }

                    my $menuItem = Gtk3::MenuItem->new(ucfirst($filter));
                    $menuItem->set_submenu($subSubMenu_filter);
                    $subMenu_toggleRoomFlag->append($menuItem);
                }

            } else {

                # Show selected room flags, sorted only by priority
                my %showHash = $self->worldModelObj->getVisibleRoomFlags();
                if (%showHash) {

                    foreach my $obj (sort {$a->priority <=> $b->priority} (values %showHash)) {

                        my $menuItem = Gtk3::MenuItem->new($obj->descrip);
                        $menuItem->signal_connect('activate' => sub {

                            # Toggle the flags for all selected rooms, redraw them and (if the
                            #   flag is one of the hazardous room flags) recalculate the
                            #   regionmap's paths. The TRUE argument tells the world model to
                            #   redraw the rooms
                            $self->worldModelObj->toggleRoomFlags(
                                $self->session,
                                TRUE,
                                $obj->name,
                                $self->compileSelectedRooms(),
                            );
                        });
                        $subMenu_toggleRoomFlag->append($menuItem);
                    }

                } else {

                    my $menuItem = Gtk3::MenuItem->new('(None are marked visible)');
                    $menuItem->set_sensitive(FALSE);
                    $subMenu_toggleRoomFlag->append($menuItem);
                }
            }

        my $item_toggleRoomFlag = Gtk3::MenuItem->new('Toggle room _flags');
        $item_toggleRoomFlag->set_submenu($subMenu_toggleRoomFlag);
        $column_rooms->append($item_toggleRoomFlag);
        # (Requires $self->currentRegionmap & either $self->selectedRoom or
        #   $self->selectedRoomHash)
        $self->ivAdd('menuToolItemHash', 'toggle_room_flag_sub', $item_toggleRoomFlag);

            # 'Other room features' submenu
            my $subMenu_roomFeatures = Gtk3::Menu->new();

                # 'Update character visits' sub-submenu
                my $subSubMenu_updateVisits = Gtk3::Menu->new();

                my $item_increaseSetCurrent = Gtk3::MenuItem->new('Increase & set _current');
                $item_increaseSetCurrent->signal_connect('activate' => sub {

                    $self->updateVisitsCallback('increase');
                    $self->mapObj->setCurrentRoom($self->selectedRoom);
                });
                $subSubMenu_updateVisits->append($item_increaseSetCurrent);
                # (Requires $self->currentRegionmap and $self->selectedRoom)
                $self->ivAdd('menuToolItemHash', 'increase_set_current', $item_increaseSetCurrent);

                $subSubMenu_updateVisits->append(Gtk3::SeparatorMenuItem->new()); # Separator

                my $item_increaseVisits = Gtk3::MenuItem->new('_Increase by one');
                $item_increaseVisits->signal_connect('activate' => sub {

                    $self->updateVisitsCallback('increase');
                });
                $subSubMenu_updateVisits->append($item_increaseVisits);

                my $item_decreaseVisits = Gtk3::MenuItem->new('_Decrease by one');
                $item_decreaseVisits->signal_connect('activate' => sub {

                    $self->updateVisitsCallback('decrease');
                });
                $subSubMenu_updateVisits->append($item_decreaseVisits);

                my $item_manualVisits = Gtk3::MenuItem->new('Set _manually');
                $item_manualVisits->signal_connect('activate' => sub {

                    $self->updateVisitsCallback('manual');
                });
                $subSubMenu_updateVisits->append($item_manualVisits);

                my $item_resetVisits = Gtk3::MenuItem->new('_Reset to zero');
                $item_resetVisits->signal_connect('activate' => sub {

                    $self->updateVisitsCallback('reset');
                });
                $subSubMenu_updateVisits->append($item_resetVisits);

                $subSubMenu_updateVisits->append(Gtk3::SeparatorMenuItem->new()); # Separator

                my $item_toggleGraffiti = Gtk3::MenuItem->new('Toggle _graffiti');
                $item_toggleGraffiti->signal_connect('activate' => sub {

                    $self->toggleGraffitiCallback();
                });
                $subSubMenu_updateVisits->append($item_toggleGraffiti);
                # (Requires $self->currentRegionmap, $self->graffitiModeFlag & one or more selected
                #   rooms)
                $self->ivAdd('menuToolItemHash', 'toggle_graffiti', $item_toggleGraffiti);

            my $item_updateVisits = Gtk3::MenuItem->new('Update character _visits');
            $item_updateVisits->set_submenu($subSubMenu_updateVisits);
            $subMenu_roomFeatures->append($item_updateVisits);
            # (Requires $self->currentRegionmap & either $self->selectedRoom or
            #   $self->selectedRoomHash)
            $self->ivAdd('menuToolItemHash', 'update_visits', $item_updateVisits);

                # 'Room exclusivity' sub-submenu
                my $subSubMenu_exclusivity = Gtk3::Menu->new();

                my $item_toggleExclusivity = Gtk3::MenuItem->new('_Toggle exclusivity');
                $item_toggleExclusivity->signal_connect('activate' => sub {

                    $self->toggleExclusiveProfileCallback();
                });
                $subSubMenu_exclusivity->append($item_toggleExclusivity);
                # (Requires $self->currentRegionmap & either $self->selectedRoom or
                #   $self->selectedRoomHash)
                $self->ivAdd('menuToolItemHash', 'toggle_exclusivity', $item_toggleExclusivity);

                $subSubMenu_exclusivity->append(Gtk3::SeparatorMenuItem->new());  # Separator

                my $item_addExclusiveProf = Gtk3::MenuItem->new('_Add exclusive profile...');
                $item_addExclusiveProf->signal_connect('activate' => sub {

                    $self->addExclusiveProfileCallback();
                });
                $subSubMenu_exclusivity->append($item_addExclusiveProf);
                # (Requires $self->currentRegionmap & $self->selectedRoom)
                $self->ivAdd('menuToolItemHash', 'add_exclusive_prof', $item_addExclusiveProf);

                my $item_clearExclusiveProf = Gtk3::MenuItem->new('_Clear exclusive profiles');
                $item_clearExclusiveProf->signal_connect('activate' => sub {

                    $self->resetExclusiveProfileCallback();
                });
                $subSubMenu_exclusivity->append($item_clearExclusiveProf);
                # (Requires $self->currentRegionmap & either $self->selectedRoom or
                #   $self->selectedRoomHash)
                $self->ivAdd('menuToolItemHash', 'clear_exclusive_profs', $item_clearExclusiveProf);

            my $item_exclusivity = Gtk3::MenuItem->new('Room _exclusivity');
            $item_exclusivity->set_submenu($subSubMenu_exclusivity);
            $subMenu_roomFeatures->append($item_exclusivity);
            # (Requires $self->currentRegionmap & either $self->selectedRoom or
            #   $self->selectedRoomHash)
            $self->ivAdd('menuToolItemHash', 'room_exclusivity', $item_exclusivity);

                # 'Source code' sub-submenu
                my $subSubMenu_sourceCode = Gtk3::Menu->new();

                my $item_setFilePath = Gtk3::MenuItem->new('_Set file path...');
                $item_setFilePath->signal_connect('activate' => sub {

                    $self->setFilePathCallback();
                });
                $subSubMenu_sourceCode->append($item_setFilePath);
                # (Requires $self->currentRegionmap and $self->selectedRoom)
                $self->ivAdd('menuToolItemHash', 'set_file_path', $item_setFilePath);

                my $item_setVirtualArea = Gtk3::MenuItem->new('Set virtual _area...');
                $item_setVirtualArea->signal_connect('activate' => sub {

                    $self->setVirtualAreaCallback(TRUE);
                });
                $subSubMenu_sourceCode->append($item_setVirtualArea);
                # (Requires $self->currentRegionmap & either $self->selectedRoom or
                #   $self->selectedRoomHash)
                $self->ivAdd('menuToolItemHash', 'set_virtual_area', $item_setVirtualArea);

                my $item_resetVirtualArea = Gtk3::MenuItem->new('_Reset virtual area...');
                $item_resetVirtualArea->signal_connect('activate' => sub {

                    $self->setVirtualAreaCallback(FALSE);
                });
                $subSubMenu_sourceCode->append($item_resetVirtualArea);
                # (Requires $self->currentRegionmap & either $self->selectedRoom or
                #   $self->selectedRoomHash)
                $self->ivAdd('menuToolItemHash', 'reset_virtual_area', $item_resetVirtualArea);

                my $item_showSourceCode = Gtk3::MenuItem->new('S_how file paths');
                $item_showSourceCode->signal_connect('activate' => sub {

                    # (Don't use $self->pseudoCmdMode - we want to see the footer messages)
                    $self->session->pseudoCmd('listsourcecode', 'show_all');
                });
                $subSubMenu_sourceCode->append($item_showSourceCode);

                $subSubMenu_sourceCode->append(Gtk3::SeparatorMenuItem->new()); # Separator

                my $item_viewSourceCode = Gtk3::MenuItem->new('_View file...');
                $item_viewSourceCode->signal_connect('activate' => sub {

                    $self->quickFreeWin(
                        'Games::Axmud::OtherWin::SourceCode',
                        $self->session,
                        # Config
                        'model_obj' => $self->selectedRoom,
                    );
                });
                $subSubMenu_sourceCode->append($item_viewSourceCode);
                # (Requires $self->currentRegionmap, $self->selectedRoom &
                #   $self->selectedRoom->sourceCodePath & empty
                #   $self->selectedRoom->virtualAreaPath)
                $self->ivAdd('menuToolItemHash', 'view_source_code', $item_viewSourceCode);

                my $item_editSourceCode = Gtk3::MenuItem->new('_Edit file...');
                $item_editSourceCode->signal_connect('activate' => sub {

                    $self->editFileCallback();
                });
                $subSubMenu_sourceCode->append($item_editSourceCode);
                # (Requires $self->currentRegionmap, $self->selectedRoom &
                #   $self->selectedRoom->sourceCodePath & empty
                #   $self->selectedRoom->virtualAreaPath)
                $self->ivAdd('menuToolItemHash', 'edit_source_code', $item_editSourceCode);

                $subSubMenu_sourceCode->append(Gtk3::SeparatorMenuItem->new()); # Separator

                my $item_viewVirtualArea = Gtk3::MenuItem->new('View virtual area _file...');
                $item_viewVirtualArea->signal_connect('activate' => sub {

                    $self->quickFreeWin(
                        'Games::Axmud::OtherWin::SourceCode',
                        $self->session,
                        # Config
                        'model_obj' => $self->selectedRoom,
                        'virtual_flag' => TRUE,
                    );
                });
                $subSubMenu_sourceCode->append($item_viewVirtualArea);
                # (Requires $self->currentRegionmap, $self->selectedRoom &
                #   $self->selectedRoom->virtualAreaPath
                $self->ivAdd('menuToolItemHash', 'view_virtual_area', $item_viewVirtualArea);

                my $item_editVirtualArea = Gtk3::MenuItem->new('E_dit virtual area file...');
                $item_editVirtualArea->signal_connect('activate' => sub {

                    # Use TRUE to specify that the virtual area file should be opened
                    $self->editFileCallback(TRUE);
                });
                $subSubMenu_sourceCode->append($item_editVirtualArea);
                # (Requires $self->currentRegionmap, $self->selectedRoom &
                #   $self->selectedRoom->virtualAreaPath
                $self->ivAdd('menuToolItemHash', 'edit_virtual_area', $item_editVirtualArea);

            my $item_sourceCode = Gtk3::MenuItem->new('Source _code');
            $item_sourceCode->set_submenu($subSubMenu_sourceCode);
            $subMenu_roomFeatures->append($item_sourceCode);

            $subMenu_roomFeatures->append(Gtk3::SeparatorMenuItem->new()); # Separator

            my $item_setInteriorOffsets = Gtk3::MenuItem->new('_Synchronise grid coordinates...');
            $item_setInteriorOffsets->signal_connect('activate' => sub {

                $self->setInteriorOffsetsCallback();
            });
            $subMenu_roomFeatures->append($item_setInteriorOffsets);

            my $item_resetInteriorOffsets = Gtk3::MenuItem->new('_Reset grid coordinates');
            $item_resetInteriorOffsets->signal_connect('activate' => sub {

                $self->resetInteriorOffsetsCallback();
            });
            $subMenu_roomFeatures->append($item_resetInteriorOffsets);

        my $item_roomFeatures = Gtk3::MenuItem->new('Ot_her room features');
        $item_roomFeatures->set_submenu($subMenu_roomFeatures);
        $column_rooms->append($item_roomFeatures);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'other_room_features', $item_roomFeatures);

        $column_rooms->append(Gtk3::SeparatorMenuItem->new());  # Separator

        my $item_deleteRoom = Gtk3::ImageMenuItem->new('_Delete rooms');
        my $img_deleteRoom = Gtk3::Image->new_from_stock('gtk-delete', 'menu');
        $item_deleteRoom->set_image($img_deleteRoom);
        $item_deleteRoom->signal_connect('activate' => sub {

            $self->deleteRoomsCallback();
        });
        $column_rooms->append($item_deleteRoom);
        # (Requires $self->currentRegionmap & either $self->selectedRoom or
        #   $self->selectedRoomHash)
        $self->ivAdd('menuToolItemHash', 'delete_room', $item_deleteRoom);

        # Setup complete
        return $column_rooms;
    }

    sub enableExitsColumn {

        # Called by $self->enableMenu
        # Sets up the 'Exits' column of the Automapper window's menu bar
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments or if the widget can't be created
        #   Otherwise returns the Gtk3::Menu created

        my ($self, $check) = @_;

        # Local variables
        my @titleList;

        # Check for improper arguments
        if (defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->enableExitsColumn', @_);
        }

        # Set up column
        my $column_exits = Gtk3::Menu->new();
        if (! $column_exits) {

            return undef;
        }

            # 'Set direction' submenu
            my $subMenu_setDir = Gtk3::Menu->new();

            my $item_changeDir = Gtk3::MenuItem->new('_Change direction...');
            $item_changeDir->signal_connect('activate' => sub {

                $self->changeDirCallback();
            });
            $subMenu_setDir->append($item_changeDir);
            # (Requires $self->currentRegionmap and $self->selectedExit and
            #   $self->selectedExit->drawMode is 'primary' or 'perm_alloc')
            $self->ivAdd('menuToolItemHash', 'change_direction', $item_changeDir);

            my $item_altDir = Gtk3::MenuItem->new('Set _alternative direction(s)...');
            $item_altDir->signal_connect('activate' => sub {

                $self->setAltDirCallback();
            });
            $subMenu_setDir->append($item_altDir);

        my $item_setDir = Gtk3::MenuItem->new('Set di_rection');
        $item_setDir->set_submenu($subMenu_setDir);
        $column_exits->append($item_setDir);
        # (Requires $self->currentRegionmap and $self->selectedExit)
        $self->ivAdd('menuToolItemHash', 'set_exit_dir', $item_setDir);

        my $item_setAssisted = Gtk3::MenuItem->new('Set assisted _move...');
        $item_setAssisted->signal_connect('activate' => sub {

            $self->setAssistedMoveCallback();
        });
        $column_exits->append($item_setAssisted);
        # (Requires $self->currentRegionmap and $self->selectedExit and
        #   $self->selectedExit->drawMode is 'primary', 'temp_unalloc' or 'perm_alloc')
        $self->ivAdd('menuToolItemHash', 'set_assisted_move', $item_setAssisted);

            # 'Allocate map direction' submenu
            my $subMenu_allocateMapDir = Gtk3::Menu->new();

            my $item_allocatePrimary = Gtk3::MenuItem->new('Choose _direction...');
            $item_allocatePrimary->signal_connect('activate' => sub {

                $self->allocateMapDirCallback();
            });
            $subMenu_allocateMapDir->append($item_allocatePrimary);

            my $item_confirmTwoWay = Gtk3::MenuItem->new('Confirm _two-way exit...');
            $item_confirmTwoWay->signal_connect('activate' => sub {

                $self->confirmTwoWayCallback();
            });
            $subMenu_allocateMapDir->append($item_confirmTwoWay);

        my $item_allocateMapDir = Gtk3::MenuItem->new('_Allocate map direction');
        $item_allocateMapDir->set_submenu($subMenu_allocateMapDir);
        $column_exits->append($item_allocateMapDir);
        # (Requires $self->currentRegionmap and $self->selectedExit and
        #   $self->selectedExit->drawMode is 'temp_alloc' or 'temp_unalloc')
        $self->ivAdd('menuToolItemHash', 'allocate_map_dir', $item_allocateMapDir);

        my $item_allocateShadow = Gtk3::MenuItem->new('Allocate _shadow...');
        $item_allocateShadow->signal_connect('activate' => sub {

            $self->allocateShadowCallback();
        });
        $column_exits->append($item_allocateShadow);
        # (Requires $self->currentRegionmap and $self->selectedExit and
        #   $self->selectedExit->drawMode is 'temp_alloc' or 'temp_unalloc')
        $self->ivAdd('menuToolItemHash', 'allocate_shadow', $item_allocateShadow);

        $column_exits->append(Gtk3::SeparatorMenuItem->new());  # Separator

        my $item_connectExitToClick = Gtk3::MenuItem->new('_Connect to click');
        $item_connectExitToClick->signal_connect('activate' => sub {

            $self->connectToClickCallback();
        });
        $column_exits->append($item_connectExitToClick);
        # (Requires $self->currentRegionmap, $self->selectedExit and
        #   $self->selectedExit->drawMode 'primary', 'temp_unalloc' or 'perm_alloc')
        $self->ivAdd('menuToolItemHash', 'connect_to_click', $item_connectExitToClick);

        my $item_disconnectExit = Gtk3::MenuItem->new('D_isconnect exit');
        $item_disconnectExit->signal_connect('activate' => sub {

            $self->disconnectExitCallback();
        });
        $column_exits->append($item_disconnectExit);
        # (Requires $self->currentRegionmap and $self->selectedExit)
        $self->ivAdd('menuToolItemHash', 'disconnect_exit', $item_disconnectExit);

        $column_exits->append(Gtk3::SeparatorMenuItem->new());  # Separator

            # 'Set ornaments' submenu
            my $subMenu_setOrnament = Gtk3::Menu->new();

            # Create a list of exit ornament types, in groups of two, in the form
            #   (menu_item_title, exit_ornament_type)
            @titleList = (
                '_No ornament', 'none',
                '_Openable exit', 'open',
                '_Lockable exit', 'lock',
                '_Pickable exit', 'pick',
                '_Breakable exit', 'break',
                '_Impassable exit', 'impass',
                '_Mystery exit', 'mystery',
            );

            do {

                my ($title, $type);

                $title = shift @titleList;
                $type = shift @titleList;

                my $menuItem = Gtk3::MenuItem->new($title);
                $menuItem->signal_connect('activate' => sub {

                    $self->exitOrnamentCallback($type);
                });
                $subMenu_setOrnament->append($menuItem);

            } until (! @titleList);

            $subMenu_setOrnament->append(Gtk3::SeparatorMenuItem->new());   # Separator

            my $item_setTwinOrnament = Gtk3::CheckMenuItem->new('Also set _twin exits');
            $item_setTwinOrnament->set_active($self->worldModelObj->setTwinOrnamentFlag);
            $item_setTwinOrnament->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'setTwinOrnamentFlag',
                        $item_setTwinOrnament->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'also_set_twin_exits',
                    );
                }
            });
            $subMenu_setOrnament->append($item_setTwinOrnament);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'also_set_twin_exits', $item_setTwinOrnament);

        my $item_setOrnament = Gtk3::MenuItem->new('Set _ornaments');
        $item_setOrnament->set_submenu($subMenu_setOrnament);
        $column_exits->append($item_setOrnament);
        # (Requires $self->currentRegionmap & either $self->selectedExit or
        #   $self->selectedExitHash)
        $self->ivAdd('menuToolItemHash', 'set_ornament_sub', $item_setOrnament);

            # 'Set exit type' submenu
            my $subMenu_setExitType = Gtk3::Menu->new();

                # 'Set hidden' sub-submenu
                my $subSubMenu_setHidden = Gtk3::Menu->new();

                my $item_setHiddenExit = Gtk3::MenuItem->new('Mark exit _hidden');
                $item_setHiddenExit->signal_connect('activate' => sub {

                    $self->hiddenExitCallback(TRUE);
                });
                $subSubMenu_setHidden->append($item_setHiddenExit);

                my $item_setNotHiddenExit = Gtk3::MenuItem->new('Mark exit _not hidden');
                $item_setNotHiddenExit->signal_connect('activate' => sub {

                    $self->hiddenExitCallback(FALSE);
                });
                $subSubMenu_setHidden->append($item_setNotHiddenExit);

            my $item_setHidden = Gtk3::MenuItem->new('Set _hidden');
            $item_setHidden->set_submenu($subSubMenu_setHidden);
            $subMenu_setExitType->append($item_setHidden);
            # (Requires $self->currentRegionmap and $self->selectedExit)
            $self->ivAdd('menuToolItemHash', 'set_hidden_sub', $item_setHidden);

                # 'Set broken' sub-submenu
                my $subSubMenu_setBroken = Gtk3::Menu->new();

                my $item_markBrokenExit = Gtk3::MenuItem->new('_Mark exit as broken');
                $item_markBrokenExit->signal_connect('activate' => sub {

                    $self->markBrokenExitCallback();
                });
                $subSubMenu_setBroken->append($item_markBrokenExit);

                my $item_toggleBrokenExit = Gtk3::MenuItem->new('_Toggle bent broken exit');
                $item_toggleBrokenExit->signal_connect('activate' => sub {

                    $self->worldModelObj->toggleBentExit(
                        TRUE,                       # Update Automapper windows now
                        $self->selectedExit,
                    );
                });
                $subSubMenu_setBroken->append($item_toggleBrokenExit);
                # (Requires $self->currentRegionmap and a $self->selectedExit which is a broken
                #   exit)
                $self->ivAdd('menuToolItemHash', 'toggle_bent_exit', $item_toggleBrokenExit);

                $subSubMenu_setBroken->append(Gtk3::SeparatorMenuItem->new());    # Separator

                my $item_restoreBrokenExit = Gtk3::MenuItem->new('_Restore unbroken exit');
                $item_restoreBrokenExit->signal_connect('activate' => sub {

                    $self->restoreBrokenExitCallback();
                });
                $subSubMenu_setBroken->append($item_restoreBrokenExit);

            my $item_setBroken = Gtk3::MenuItem->new('Set _broken');
            $item_setBroken->set_submenu($subSubMenu_setBroken);
            $subMenu_setExitType->append($item_setBroken);
            # (Requires $self->currentRegionmap and $self->selectedExit)
            $self->ivAdd('menuToolItemHash', 'set_broken_sub', $item_setBroken);

                # 'Set one-way' sub-submenu
                my $subSubMenu_setOneWay = Gtk3::Menu->new();

                my $item_markOneWayExit = Gtk3::MenuItem->new('_Mark exit as one-way');
                $item_markOneWayExit->signal_connect('activate' => sub {

                    $self->markOneWayExitCallback();
                });
                $subSubMenu_setOneWay->append($item_markOneWayExit);

                $subSubMenu_setOneWay->append(Gtk3::SeparatorMenuItem->new());    # Separator

                my $item_restoreUncertainExit = Gtk3::MenuItem->new('Restore _uncertain exit');
                $item_restoreUncertainExit->signal_connect('activate' => sub {

                    $self->restoreOneWayExitCallback(FALSE);
                });
                $subSubMenu_setOneWay->append($item_restoreUncertainExit);

                my $item_restoreTwoWayExit = Gtk3::MenuItem->new('Restore _two-way exit');
                $item_restoreTwoWayExit->signal_connect('activate' => sub {

                    $self->restoreOneWayExitCallback(TRUE);
                });
                $subSubMenu_setOneWay->append($item_restoreTwoWayExit);

                $subSubMenu_setOneWay->append(Gtk3::SeparatorMenuItem->new());    # Separator

                my $item_setIncomingDir = Gtk3::MenuItem->new('Set incoming _direction...');
                $item_setIncomingDir->signal_connect('activate' => sub {

                    $self->setIncomingDirCallback();
                });
                $subSubMenu_setOneWay->append($item_setIncomingDir);
                # (Requires $self->currentRegionmap and a $self->selectedExit which is a one-way
                #   exit)
                $self->ivAdd('menuToolItemHash', 'set_incoming_dir', $item_setIncomingDir);

            my $item_setOneWay = Gtk3::MenuItem->new('Set _one-way');
            $item_setOneWay->set_submenu($subSubMenu_setOneWay);
            $subMenu_setExitType->append($item_setOneWay);
            # (Requires $self->currentRegionmap and $self->selectedExit)
            $self->ivAdd('menuToolItemHash', 'set_oneway_sub', $item_setOneWay);

                # 'Set retracing' sub-submenu
                my $subSubMenu_setRetracing = Gtk3::Menu->new();

                my $item_markRetracingExit = Gtk3::MenuItem->new('_Mark exit as retracing');
                $item_markRetracingExit->signal_connect('activate' => sub {

                    $self->markRetracingExitCallback();
                });
                $subSubMenu_setRetracing->append($item_markRetracingExit);

                $subSubMenu_setRetracing->append(Gtk3::SeparatorMenuItem->new());    # Separator

                my $item_restoreRetracingExit = Gtk3::MenuItem->new('_Restore incomplete exit');
                $item_restoreRetracingExit->signal_connect('activate' => sub {

                    $self->restoreRetracingExitCallback();
                });
                $subSubMenu_setRetracing->append($item_restoreRetracingExit);

            my $item_setRetracing = Gtk3::MenuItem->new('Set _retracing');
            $item_setRetracing->set_submenu($subSubMenu_setRetracing);
            $subMenu_setExitType->append($item_setRetracing);
            # (Requires $self->currentRegionmap and $self->selectedExit)
            $self->ivAdd('menuToolItemHash', 'set_retracing_sub', $item_setRetracing);

                # 'Set random' sub-submenu
                my $subSubMenu_setRandomExit = Gtk3::Menu->new();

                my $item_markRandomRegion = Gtk3::MenuItem->new(
                    'Set random destination in same _region',
                );
                $item_markRandomRegion->signal_connect('activate' => sub {

                    $self->markRandomExitCallback('same_region');
                });
                $subSubMenu_setRandomExit->append($item_markRandomRegion);

                my $item_markRandomAnywhere
                    = Gtk3::MenuItem->new('Set random destination _anywhere');
                $item_markRandomAnywhere->signal_connect('activate' => sub {

                    $self->markRandomExitCallback('any_region');
                });
                $subSubMenu_setRandomExit->append($item_markRandomAnywhere);

                my $item_randomTempRegion
                    = Gtk3::MenuItem->new('_Create destination in temporary region');
                $item_randomTempRegion->signal_connect('activate' => sub {

                    $self->markRandomExitCallback('temp_region');
                });
                $subSubMenu_setRandomExit->append($item_randomTempRegion);

                my $item_markRandomList = Gtk3::MenuItem->new('_Use list of random destinations');
                $item_markRandomList->signal_connect('activate' => sub {

                    $self->markRandomExitCallback('room_list');
                });
                $subSubMenu_setRandomExit->append($item_markRandomList);

                $subSubMenu_setRandomExit->append(Gtk3::SeparatorMenuItem->new());    # Separator

                my $item_restoreRandomExit = Gtk3::MenuItem->new('Restore _incomplete exit');
                $item_restoreRandomExit->signal_connect('activate' => sub {

                    $self->restoreRandomExitCallback();
                });
                $subSubMenu_setRandomExit->append($item_restoreRandomExit);

            my $item_setRandomExit = Gtk3::MenuItem->new('Set r_andom');
            $item_setRandomExit->set_submenu($subSubMenu_setRandomExit);
            $subMenu_setExitType->append($item_setRandomExit);
            # (Requires $self->currentRegionmap and $self->selectedExit)
            $self->ivAdd('menuToolItemHash', 'set_random_sub', $item_setRandomExit);

                # 'Set super' sub-submenu
                my $subSubMenu_setSuperExit = Gtk3::Menu->new();

                my $item_markSuper = Gtk3::MenuItem->new('Mark exit as _super-region exit');
                $item_markSuper->signal_connect('activate' => sub {

                    $self->markSuperExitCallback(FALSE);
                });
                $subSubMenu_setSuperExit->append($item_markSuper);

                my $item_markSuperExcl = Gtk3::MenuItem->new(
                    'Mark exit as _exclusive super-region exit',
                );
                $item_markSuperExcl->signal_connect('activate' => sub {

                    $self->markSuperExitCallback(TRUE);
                });
                $subSubMenu_setSuperExit->append($item_markSuperExcl);

                $subSubMenu_setSuperExit->append(Gtk3::SeparatorMenuItem->new());    # Separator

                my $item_markNotSuper = Gtk3::MenuItem->new('Mark exit as _normal region exit');
                $item_markNotSuper->signal_connect('activate' => sub {

                    $self->restoreSuperExitCallback();
                });
                $subSubMenu_setSuperExit->append($item_markNotSuper);

            my $item_setSuperExit = Gtk3::MenuItem->new('Set _super');
            $item_setSuperExit->set_submenu($subSubMenu_setSuperExit);
            $subMenu_setExitType->append($item_setSuperExit);
            # (Requires $self->currentRegionmap and $self->selectedExit which is a region exit)
            $self->ivAdd('menuToolItemHash', 'set_super_sub', $item_setSuperExit);

            $subMenu_setExitType->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $item_setExitTwin = Gtk3::MenuItem->new('Set exit _twin...');
            $item_setExitTwin->signal_connect('activate' => sub {

                $self->setExitTwinCallback();
            });
            $subMenu_setExitType->append($item_setExitTwin);
            # (Requires $self->currentRegionmap and a $self->selectedExit which is either a one-way
            #   exit or an uncertain exit)
            $self->ivAdd('menuToolItemHash', 'set_exit_twin', $item_setExitTwin);

        my $item_setExitType = Gtk3::MenuItem->new('Set _exit type');
        $item_setExitType->set_submenu($subMenu_setExitType);
        $column_exits->append($item_setExitType);
        # (Requires $self->currentRegionmap and $self->selectedExit)
        $self->ivAdd('menuToolItemHash', 'set_exit_type', $item_setExitType);

            # 'Exit tags' submenu
            my $subMenu_exitTags = Gtk3::Menu->new();

            my $item_setExitText = Gtk3::MenuItem->new('_Edit tag text');
            $item_setExitText->signal_connect('activate' => sub {

                $self->editExitTagCallback();
            });
            $subMenu_exitTags->append($item_setExitText);
            # (Requires $self->currentRegionmap and either a $self->selectedExit which is a region
            #   exit, or a $self->selectedExitTag)
            $self->ivAdd('menuToolItemHash', 'edit_tag_text', $item_setExitText);

            my $item_toggleExitTag = Gtk3::MenuItem->new('_Toggle exit tag');
            $item_toggleExitTag->signal_connect('activate' => sub {

                $self->toggleExitTagCallback();
            });
            $subMenu_exitTags->append($item_toggleExitTag);
            # (Requires $self->currentRegionmap and either a $self->selectedExit which is a region
            #   exit, or a $self->selectedExitTag)
            $self->ivAdd('menuToolItemHash', 'toggle_exit_tag', $item_toggleExitTag);

            $subMenu_exitTags->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $item_resetPositions = Gtk3::MenuItem->new('_Reset tag positions');
            $item_resetPositions->signal_connect('activate' => sub {

                $self->resetExitOffsetsCallback();
            });
            $subMenu_exitTags->append($item_resetPositions);
            # (Requires $self->currentRegionmap and one or more of $self->selectedExit,
            #   $self->selectedExitHash, $self->selectedExitTag and $self->selectedExitTagHash)
            $self->ivAdd('menuToolItemHash', 'reset_exit_tags', $item_resetPositions);

            $subMenu_exitTags->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $item_applyExitTags = Gtk3::MenuItem->new('_Apply all tags in region');
            $item_applyExitTags->signal_connect('activate' => sub {

                $self->applyExitTagsCallback(TRUE);
            });
            $subMenu_exitTags->append($item_applyExitTags);


            my $item_cancelExitTags = Gtk3::MenuItem->new('_Cancel all tags in region');
            $item_cancelExitTags->signal_connect('activate' => sub {

                $self->applyExitTagsCallback(FALSE);
            });
            $subMenu_exitTags->append($item_cancelExitTags);

        my $item_exitTags = Gtk3::MenuItem->new('Exit _tags');
        $item_exitTags->set_submenu($subMenu_exitTags);
        $column_exits->append($item_exitTags);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'exit_tags', $item_exitTags);

        $column_exits->append(Gtk3::SeparatorMenuItem->new());  # Separator

        my $item_editExit = Gtk3::ImageMenuItem->new('Edit e_xit...');
        my $img_editExit = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
        $item_editExit->set_image($img_editExit);
        $item_editExit->signal_connect('activate' => sub {

            $self->editExitCallback();
        });
        $column_exits->append($item_editExit);
        # (Requires $self->currentRegionmap and $self->selectedExit)
        $self->ivAdd('menuToolItemHash', 'edit_exit', $item_editExit);

        $column_exits->append(Gtk3::SeparatorMenuItem->new());  # Separator

            # 'Exit options' submenu
            my $subMenu_exitOptions = Gtk3::Menu->new();

            my $item_completeSelected = Gtk3::MenuItem->new('_Complete selected uncertain exits');
            $item_completeSelected->signal_connect('activate' => sub {

                $self->completeExitsCallback();
            });
            $subMenu_exitOptions->append($item_completeSelected);

            my $item_connectAdjacent = Gtk3::MenuItem->new('C_onnect selected adjacent rooms');
            $item_connectAdjacent->signal_connect('activate' => sub {

                $self->connectAdjacentCallback();
            });
            $subMenu_exitOptions->append($item_connectAdjacent);
            # (Requires $self->currentRegionmap and one or more selected rooms)
            $self->ivAdd('menuToolItemHash', 'connect_adjacent', $item_connectAdjacent);

            $subMenu_exitOptions->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $item_autocomplete = Gtk3::CheckMenuItem->new('_Autocomplete uncertain exits');
            $item_autocomplete->set_active($self->worldModelObj->autocompleteExitsFlag);
            $item_autocomplete->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'autocompleteExitsFlag',
                        $item_autocomplete->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'autcomplete_uncertain',
                    );
                }
            });
            $subMenu_exitOptions->append($item_autocomplete);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'autocomplete_uncertain', $item_autocomplete);

            my $item_intUncertain = Gtk3::CheckMenuItem->new('_Intelligent uncertain exits');
            $item_intUncertain->set_active(
                $self->worldModelObj->intelligentExitsFlag,
            );
            $item_intUncertain->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'intelligentExitsFlag',
                        $item_intUncertain->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'intelligent_uncertain',
                    );
                }
            });
            $subMenu_exitOptions->append($item_intUncertain);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'intelligent_uncertain', $item_intUncertain);

            $subMenu_exitOptions->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $item_collectChecked = Gtk3::CheckMenuItem->new('Co_llect checked directions');
            $item_collectChecked->set_active(
                $self->worldModelObj->collectCheckedDirsFlag,
            );
            $item_collectChecked->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'collectCheckedDirsFlag',
                        $item_collectChecked->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'collect_checked_dirs',
                    );
                }
            });
            $subMenu_exitOptions->append($item_collectChecked);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'collect_checked_dirs', $item_collectChecked);

            my $item_drawChecked = Gtk3::CheckMenuItem->new('_Draw checked directions');
            $item_drawChecked->set_active(
                $self->worldModelObj->drawCheckedDirsFlag,
            );
            $item_drawChecked->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'drawCheckedDirsFlag',
                        $item_drawChecked->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'draw_checked_dirs',
                    );
                }

                # Redraw the region, if one is visible
                if ($self->currentRegionmap) {

                    $self->redrawRegions();
                }
            });
            $subMenu_exitOptions->append($item_drawChecked);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'draw_checked_dirs', $item_drawChecked);

            $subMenu_exitOptions->append(Gtk3::SeparatorMenuItem->new());    # Separator

                 # 'Checkable directions' sub-submenu
                my $subSubMenu_checkable = Gtk3::Menu->new();

                my $item_checkableSimple
                    = Gtk3::RadioMenuItem->new_with_mnemonic(undef, 'Count _NSEW');
                $item_checkableSimple->signal_connect('toggled' => sub {

                    if ($item_checkableSimple->get_active) {

                        $self->worldModelObj->setCheckableDirMode('simple');
                    }
                });
                my $item_checkableGroup = $item_checkableSimple->get_group();
                $subSubMenu_checkable->append($item_checkableSimple);
                # (Never desensitised)
                $self->ivAdd('menuToolItemHash', 'checkable_dir_simple', $item_checkableSimple);

                my $item_checkableDiku = Gtk3::RadioMenuItem->new_with_mnemonic(
                    $item_checkableGroup,
                    'Count NSEW_UD',
                );
                if ($self->worldModelObj->checkableDirMode eq 'diku') {

                    $item_checkableDiku->set_active(TRUE);
                }
                $item_checkableDiku->signal_connect('toggled' => sub {

                    if ($item_checkableDiku->get_active) {

                        $self->worldModelObj->setCheckableDirMode('diku');
                    }
                });
                $subSubMenu_checkable->append($item_checkableDiku);
                # (Never desensitised)
                $self->ivAdd('menuToolItemHash', 'checkable_dir_diku', $item_checkableDiku);

                my $item_checkableLP = Gtk3::RadioMenuItem->new_with_mnemonic(
                    $item_checkableGroup,
                    'Count NSEWUD, N_E/NW/SE/SW',
                );
                if ($self->worldModelObj->checkableDirMode eq 'lp') {

                    $item_checkableLP->set_active(TRUE);
                }
                $item_checkableLP->signal_connect('toggled' => sub {

                    if ($item_checkableLP->get_active) {

                        $self->worldModelObj->setCheckableDirMode('lp');
                    }
                });
                $subSubMenu_checkable->append($item_checkableLP);
                # (Never desensitised)
                $self->ivAdd('menuToolItemHash', 'checkable_dir_lp', $item_checkableLP);

                my $item_checkableComplex = Gtk3::RadioMenuItem->new_with_mnemonic(
                    $item_checkableGroup,
                    'Count _all primary directions',
                );
                if ($self->worldModelObj->checkableDirMode eq 'complex') {

                    $item_checkableComplex->set_active(TRUE);
                }
                $item_checkableComplex->signal_connect('toggled' => sub {

                    if ($item_checkableComplex->get_active) {

                        $self->worldModelObj->setCheckableDirMode('complex');
                    }
                });
                $subSubMenu_checkable->append($item_checkableComplex);
                # (Never desensitised)
                $self->ivAdd('menuToolItemHash', 'checkable_dir_complex', $item_checkableComplex);

            my $item_exits = Gtk3::MenuItem->new('C_heckable directions');
            $item_exits->set_submenu($subSubMenu_checkable);
            $subMenu_exitOptions->append($item_exits);

        my $item_exitOptions = Gtk3::MenuItem->new('Exit o_ptions');
        $item_exitOptions->set_submenu($subMenu_exitOptions);
        $column_exits->append($item_exitOptions);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'exit_options', $item_exitOptions);

            # 'Exit lengths' submenu
            my $subMenu_exitLengths = Gtk3::Menu->new();

            my $item_horizontalLength = Gtk3::MenuItem->new('Set _horizontal length...');
            $item_horizontalLength->signal_connect('activate' => sub {

                $self->setExitLengthCallback('horizontal');
            });
            $subMenu_exitLengths->append($item_horizontalLength);

            my $item_verticalLength = Gtk3::MenuItem->new('Set _vertical length...');
            $item_verticalLength->signal_connect('activate' => sub {

                $self->setExitLengthCallback('vertical');
            });
            $subMenu_exitLengths->append($item_verticalLength);

            $subMenu_exitLengths->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $item_resetLength = Gtk3::MenuItem->new('_Reset exit lengths');
            $item_resetLength->signal_connect('activate' => sub {

                $self->resetExitLengthCallback();
            });
            $subMenu_exitLengths->append($item_resetLength);

        my $item_exitLengths = Gtk3::MenuItem->new('Exit _lengths');
        $item_exitLengths->set_submenu($subMenu_exitLengths);
        $column_exits->append($item_exitLengths);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'exit_lengths', $item_exitLengths);

        $column_exits->append(Gtk3::SeparatorMenuItem->new());  # Separator

        my $item_deleteExit = Gtk3::ImageMenuItem->new('_Delete exit');
        my $img_deleteExit = Gtk3::Image->new_from_stock('gtk-delete', 'menu');
        $item_deleteExit->set_image($img_deleteExit);
        $item_deleteExit->signal_connect('activate' => sub {

            $self->deleteExitCallback();
        });
        $column_exits->append($item_deleteExit);
        # (Requires $self->currentRegionmap and $self->selectedExit)
        $self->ivAdd('menuToolItemHash', 'delete_exit', $item_deleteExit);

        # Setup complete
        return $column_exits;
    }

    sub enableLabelsColumn {

        # Called by $self->enableMenu
        # Sets up the 'Labels' column of the Automapper window's menu bar
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments or if the widget can't be created
        #   Otherwise returns the Gtk3::Menu created

        my ($self, $check) = @_;

        # Local variables
        my $alignFlag;

        # Check for improper arguments
        if (defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->enableLabelsColumn', @_);
        }

        # Set up column
        my $column_labels = Gtk3::Menu->new();
        if (! $column_labels) {

            return undef;
        }

        my $item_addLabelAtClick = Gtk3::ImageMenuItem->new('Add label at _click');
        my $img_addLabelAtClick = Gtk3::Image->new_from_stock('gtk-add', 'menu');
        $item_addLabelAtClick->set_image($img_addLabelAtClick);
        $item_addLabelAtClick->signal_connect('activate' => sub {

            # Set the free click mode; $self->canvasEventHandler will create the new label when the
            #   user next clicks on an empty part of the map
            if ($self->currentRegionmap) {

                $self->set_freeClickMode('add_label');
            }
        });
        $column_labels->append($item_addLabelAtClick);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'add_label_at_click', $item_addLabelAtClick);

        my $item_addLabelAtBlock = Gtk3::ImageMenuItem->new('Add label at _block');
        my $img_addLabelAtBlock = Gtk3::Image->new_from_stock('gtk-add', 'menu');
        $item_addLabelAtBlock->set_image($img_addLabelAtBlock);
        $item_addLabelAtBlock->signal_connect('activate' => sub {

            $self->addLabelAtBlockCallback();
        });
        $column_labels->append($item_addLabelAtBlock);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'add_label_at_block', $item_addLabelAtBlock);

        $column_labels->append(Gtk3::SeparatorMenuItem->new()); # Separator

        my $item_setLabel = Gtk3::ImageMenuItem->new('_Set label...');
        my $img_setLabel = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
        $item_setLabel->set_image($img_setLabel);
        $item_setLabel->signal_connect('activate' => sub {

            $self->setLabelCallback(FALSE);
        });
        $column_labels->append($item_setLabel);
        # (Requires $self->currentRegionmap and $self->selectedLabel)
        $self->ivAdd('menuToolItemHash', 'set_label', $item_setLabel);

        my $item_customiseLabel = Gtk3::ImageMenuItem->new('C_ustomise label...');
        my $img_customiseLabel = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
        $item_customiseLabel->set_image($img_customiseLabel);
        $item_customiseLabel->signal_connect('activate' => sub {

            $self->setLabelCallback(TRUE);
        });
        $column_labels->append($item_customiseLabel);
        # (Requires $self->currentRegionmap and $self->selectedLabel)
        $self->ivAdd('menuToolItemHash', 'customise_label', $item_customiseLabel);

            my $item_useMultiLine = Gtk3::CheckMenuItem->new('Use _multiline labels');
            $item_useMultiLine->set_active($self->worldModelObj->mapLabelTextViewFlag);
            $item_useMultiLine->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'mapLabelTextViewFlag',
                        $item_useMultiLine->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'use_multi_line',
                    );
                }
            });
            $column_labels->append($item_useMultiLine);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'use_multi_line', $item_useMultiLine);

        $column_labels->append(Gtk3::SeparatorMenuItem->new()); # Separator

        my $item_selectLabel = Gtk3::MenuItem->new('S_elect label...');
        $item_selectLabel->signal_connect('activate' => sub {

            $self->selectLabelCallback();
        });
        $column_labels->append($item_selectLabel);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'select_label', $item_selectLabel);

        $column_labels->append(Gtk3::SeparatorMenuItem->new()); # Separator

        my $item_addStyle = Gtk3::ImageMenuItem->new('_Add label style...');
        my $img_addStyle = Gtk3::Image->new_from_stock('gtk-add', 'menu');
        $item_addStyle->set_image($img_addStyle);
        $item_addStyle->signal_connect('activate' => sub {

            $self->addStyleCallback();
        });
        $column_labels->append($item_addStyle);

        my $item_editStyle = Gtk3::ImageMenuItem->new('Ed_it label style...');
        my $img_editStyle = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
        $item_editStyle->set_image($img_editStyle);
        $item_editStyle->signal_connect('activate' => sub {

            $self->editStyleCallback();
        });
        $column_labels->append($item_editStyle);
        # (Requires at least one label style in $self->worldModelObj->mapLabelStyleHash)
        $self->ivAdd('menuToolItemHash', 'edit_style', $item_selectLabel);

            # 'Label alignment' submenu
            my $subMenu_alignment = Gtk3::Menu->new();

            my $item_alignHorizontal = Gtk3::CheckMenuItem->new('Align _horizontally');
            $item_alignHorizontal->set_active($self->worldModelObj->mapLabelAlignXFlag);
            $item_alignHorizontal->signal_connect('toggled' => sub {

                # Use $alignFlag to avoid an infinite loop, if we have to toggle the button back to
                #   its original state because the user declined to confirm the operation
                if (! $alignFlag) {

                    if (! $self->toggleAlignCallback('horizontal')) {

                        $alignFlag = TRUE;
                        if (! $item_alignHorizontal->get_active()) {
                            $item_alignHorizontal->set_active(TRUE);
                        } else {
                            $item_alignHorizontal->set_active(FALSE);
                        }

                        $alignFlag = FALSE;
                    }
                }
            });
            $subMenu_alignment->append($item_alignHorizontal);

            my $item_alignVertical = Gtk3::CheckMenuItem->new('Align _vertically');
            $item_alignVertical->set_active($self->worldModelObj->mapLabelAlignYFlag);
            $item_alignVertical->signal_connect('toggled' => sub {

                # Use $alignFlag to avoid an infinite loop, if we have to toggle the button back to
                #   its original state because the user declined to confirm the operation
                if (! $alignFlag) {

                    if (! $self->toggleAlignCallback('vertical')) {

                        $alignFlag = TRUE;
                        if (! $item_alignVertical->get_active()) {
                            $item_alignVertical->set_active(TRUE);
                        } else {
                            $item_alignVertical->set_active(FALSE);
                        }

                        $alignFlag = FALSE;
                    }
                }
            });
            $subMenu_alignment->append($item_alignVertical);

        my $item_alignment = Gtk3::MenuItem->new('_Label alignment');
        $item_alignment->set_submenu($subMenu_alignment);
        $column_labels->append($item_alignment);

        $column_labels->append(Gtk3::SeparatorMenuItem->new()); # Separator

        my $item_deleteLabel = Gtk3::ImageMenuItem->new('_Delete labels');
        my $img_deleteLabel = Gtk3::Image->new_from_stock('gtk-delete', 'menu');
        $item_deleteLabel->set_image($img_deleteLabel);
        $item_deleteLabel->signal_connect('activate' => sub {

            # Callback to prompt for confirmation, before deleting multiple labels
            $self->deleteLabelsCallback();
        });
        $column_labels->append($item_deleteLabel);
        # (Requires $self->currentRegionmap & either $self->selectedLabel or
        #   $self->selectedLabelHash)
        $self->ivAdd('menuToolItemHash', 'delete_label', $item_deleteLabel);

        my $item_quickDelete = Gtk3::ImageMenuItem->new('_Quick label deletion...');
        my $img_quickDelete = Gtk3::Image->new_from_stock('gtk-delete', 'menu');
        $item_quickDelete->set_image($img_quickDelete);
        $item_quickDelete->signal_connect('activate' => sub {

            $self->session->pseudoCmd('quicklabeldelete', $self->pseudoCmdMode);
        });
        $column_labels->append($item_quickDelete);

        # Setup complete
        return $column_labels;
    }

    # Popup menu widget methods

    sub enableCanvasPopupMenu {

        # Called by $self->canvasEventHandler
        # Creates a popup-menu for the Gtk3::Canvas when no rooms, exits, room tags or labels are
        #   selected
        #
        # Expected arguments
        #   $clickXPosPixels, $clickYPosPixels
        #       - Coordinates of the pixel that was right-clicked on the map
        #   $clickXPosBlocks, $clickYPosBlocks
        #       - Coordinates of the gridblock that was right-clicked on the map
        #
        # Return values
        #   'undef' on improper arguments or if the widget can't be created
        #   Otherwise returns the Gtk3::Menu created

        my (
            $self, $clickXPosPixels, $clickYPosPixels, $clickXPosBlocks, $clickYPosBlocks, $check,
        ) = @_;

        # Check for improper arguments
        if (
            ! defined $clickXPosPixels || ! defined $clickYPosPixels
            || ! defined $clickXPosBlocks || ! defined $clickYPosBlocks || defined $check
        ) {
            return $axmud::CLIENT->writeImproper($self->_objClass . '->enableCanvasPopupMenu', @_);
        }

        # Set up the popup menu
        my $menu_canvas = Gtk3::Menu->new();
        if (! $menu_canvas) {

            return undef;
        }

        # (Everything here assumes $self->currentRegionmap)

        my $item_addFirstRoom = Gtk3::ImageMenuItem->new('Add _first room');
        my $img_addFirstRoom = Gtk3::Image->new_from_stock('gtk-add', 'menu');
        $item_addFirstRoom->set_image($img_addFirstRoom);
        $item_addFirstRoom->signal_connect('activate' => sub {

            $self->addFirstRoomCallback();
        });
        $menu_canvas->append($item_addFirstRoom);
        # (Also requires empty $self->currentRegionmap->gridRoomHash)
        if ($self->currentRegionmap->gridRoomHash) {

            $item_addFirstRoom->set_sensitive(FALSE);
        }

        my $item_addRoomHere = Gtk3::ImageMenuItem->new('Add _room here');
        my $img_addRoomHere = Gtk3::Image->new_from_stock('gtk-add', 'menu');
        $item_addRoomHere->set_image($img_addRoomHere);
        $item_addRoomHere->signal_connect('activate' => sub {

            my $roomObj;

            # The 'Add room at click' operation from the main menu resets the value of
            #   ->freeClickMode; we must do the same here
            $self->reset_freeClickMode();

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

            if ($roomObj) {

                $self->setSelectedObj(
                    [$roomObj, 'room'],
                    FALSE,      # Select this object; unselect all other objects
                );
            }
        });
        $menu_canvas->append($item_addRoomHere);

        $menu_canvas->append(Gtk3::SeparatorMenuItem->new());  # Separator

        my $item_addLabelHere = Gtk3::ImageMenuItem->new('Add _label here');
        my $img_addLabelHere = Gtk3::Image->new_from_stock('gtk-add', 'menu');
        $item_addLabelHere->set_image($img_addLabelHere);
        $item_addLabelHere->signal_connect('activate' => sub {

            $self->addLabelAtClickCallback($clickXPosPixels, $clickYPosPixels);
        });
        $menu_canvas->append($item_addLabelHere);

        $menu_canvas->append(Gtk3::SeparatorMenuItem->new());  # Separator

        my $item_centreMap = Gtk3::MenuItem->new('_Centre map here');
        $item_centreMap->signal_connect('activate' => sub {

            $self->centreMapOverRoom(
                undef,              # Centre the map, not over a room...
                $clickXPosBlocks,   # ...but over this gridblock
                $clickYPosBlocks,
            );
        });
        $menu_canvas->append($item_centreMap);

        $menu_canvas->append(Gtk3::SeparatorMenuItem->new());  # Separator

        my $item_editRegionmap = Gtk3::ImageMenuItem->new('_Edit regionmap...');
        my $img_editRegionmap = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
        $item_editRegionmap->set_image($img_editRegionmap);
        $item_editRegionmap->signal_connect('activate' => sub {

            # Open an 'edit' window for the regionmap
            $self->createFreeWin(
                'Games::Axmud::EditWin::Regionmap',
                $self,
                $self->session,
                'Edit \'' . $self->currentRegionmap->name . '\' regionmap',
                $self->currentRegionmap,
                FALSE,                          # Not temporary
            );
        });
        $menu_canvas->append($item_editRegionmap);

        my $item_preferences = Gtk3::ImageMenuItem->new('Edit world _model...');
        my $img_preferences = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
        $item_preferences->set_image($img_preferences);
        $item_preferences->signal_connect('activate' => sub {

            # Open an 'edit' window for the world model
            $self->createFreeWin(
                'Games::Axmud::EditWin::WorldModel',
                $self,
                $self->session,
                'Edit world model',

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

            );
        });
        $menu_canvas->append($item_preferences);

        # Setup complete
        $menu_canvas->show_all();

        return $menu_canvas;
    }

    sub enableRoomsPopupMenu {

        # Called by $self->canvasObjEventHandler
        # Creates a popup-menu for the selected room
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments or if the widget can't be created
        #   Otherwise returns the Gtk3::Menu created

        my ($self, $check) = @_;

        # Check for improper arguments
        if (defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->enableRoomsPopupMenu', @_);
        }

        # Set up the popup menu
        my $menu_rooms = Gtk3::Menu->new();
        if (! $menu_rooms) {

            return undef;
        }

        # (Everything here assumes $self->currentRegionmap and $self->selectedRoom)

        my $item_setCurrentRoom = Gtk3::MenuItem->new('_Set current room');
        $item_setCurrentRoom->signal_connect('activate' => sub {

            $self->mapObj->setCurrentRoom($self->selectedRoom);
        });
        $menu_rooms->append($item_setCurrentRoom);

        my $item_centreMap = Gtk3::MenuItem->new('_Centre map over room');
        $item_centreMap->signal_connect('activate' => sub {

            $self->centreMapOverRoom($self->selectedRoom);
        });
        $menu_rooms->append($item_centreMap);

        my $item_executeScripts = Gtk3::MenuItem->new('Run _Axbasic scripts');
        $item_executeScripts->signal_connect('activate' => sub {

            $self->executeScriptsCallback();
        });
        $menu_rooms->append($item_executeScripts);
        # (Also requires $self->mapObj->currentRoom that's the same as $self->selectedRoom)
        if (! $self->mapObj->currentRoom || $self->mapObj->currentRoom ne $self->selectedRoom) {

            $item_executeScripts->set_sensitive(FALSE);
        }

        $menu_rooms->append(Gtk3::SeparatorMenuItem->new());  # Separator

            # 'Pathfinding' submenu
            my $subMenu_pathFinding = Gtk3::Menu->new();

            my $item_highlightPath = Gtk3::MenuItem->new('_Highlight path');
            $item_highlightPath->signal_connect('activate' => sub {

                $self->processPathCallback('select_room');
            });
            $subMenu_pathFinding->append($item_highlightPath);

            my $item_displayPath = Gtk3::MenuItem->new('_Edit path...');
            $item_displayPath->signal_connect('activate' => sub {

                $self->processPathCallback('pref_win');
            });
            $subMenu_pathFinding->append($item_displayPath);

            my $item_goToRoom = Gtk3::MenuItem->new('_Go to room');
            $item_goToRoom->signal_connect('activate' => sub {

                $self->processPathCallback('send_char');
            });
            $subMenu_pathFinding->append($item_goToRoom);

        my $item_pathFinding = Gtk3::MenuItem->new('_Pathfinding');
        $item_pathFinding->set_submenu($subMenu_pathFinding);
        $menu_rooms->append($item_pathFinding);
        # (Also requires $self->mapObj->currentRoom)
        if (! $self->mapObj->currentRoom) {

            $item_pathFinding->set_sensitive(FALSE);
        }

            # 'Moves rooms/labels' submenu
            my $subMenu_moveRooms = Gtk3::Menu->new();

            my $item_moveSelected = Gtk3::MenuItem->new('Move in _direction...');
            $item_moveSelected->signal_connect('activate' => sub {

                $self->moveSelectedRoomsCallback();
            });
            $subMenu_moveRooms->append($item_moveSelected);

            my $item_moveSelectedToClick = Gtk3::MenuItem->new('Move to _click');
            $item_moveSelectedToClick->signal_connect('activate' => sub {

                # Set the free clicking mode: $self->mouseClickEvent will move the objects when the
                #   user next clicks on an empty part of the map
                $self->set_freeClickMode('move_room');
            });
            $subMenu_moveRooms->append($item_moveSelectedToClick);

            $subMenu_moveRooms->append(Gtk3::SeparatorMenuItem->new());  # Separator

                # 'Transfer to region' sub-submenu
                my $subSubMenu_transferRegion = Gtk3::Menu->new();

                if ($self->recentRegionList) {

                    foreach my $name ($self->recentRegionList) {

                        my $item_regionName = Gtk3::MenuItem->new($name);
                        $item_regionName->signal_connect('activate' => sub {

                            $self->transferSelectedRoomsCallback($name);
                        });
                        $subSubMenu_transferRegion->append($item_regionName);
                    }

                } else {

                    my $item_regionNone = Gtk3::MenuItem->new('(No recent regions)');
                    $item_regionNone->set_sensitive(FALSE);
                    $subSubMenu_transferRegion->append($item_regionNone);
                }

                $subSubMenu_transferRegion->append(Gtk3::SeparatorMenuItem->new());  # Separator

                my $item_transferSelect = Gtk3::MenuItem->new('Select region...');
                $item_transferSelect->signal_connect('activate' => sub {

                    $self->transferSelectedRoomsCallback();
                });
                $subSubMenu_transferRegion->append($item_transferSelect);

            my $item_transferRegion = Gtk3::MenuItem->new('_Transfer to region');
            $item_transferRegion->set_submenu($subSubMenu_transferRegion);
            $subMenu_moveRooms->append($item_transferRegion);
            # (Also requires at least two regions in the world model)
            if ($self->worldModelObj->ivPairs('regionmapHash') <= 1) {

                $item_transferRegion->set_sensitive(FALSE);
            }

            $subMenu_moveRooms->append(Gtk3::SeparatorMenuItem->new());  # Separator

            my $item_mergeRoom = Gtk3::MenuItem->new('_Merge room');
            $item_mergeRoom->signal_connect('activate' => sub {

                $self->doMerge($self->mapObj->currentRoom);
            });
            $subMenu_moveRooms->append($item_mergeRoom);
            # (Also requires this to be the current room and the automapper being set up to perform
            #   a merge)
            if (
                ! $self->mapObj->currentRoom
                || $self->mapObj->currentRoom ne $self->selectedRoom
                || ! $self->mapObj->currentMatchFlag
            ) {
                $item_mergeRoom->set_sensitive(FALSE);
            }

                # 'Compare room' sub-submenu
                my $subSubMenu_compareRoom = Gtk3::Menu->new();

                my $item_compareRoomRegion = Gtk3::MenuItem->new('...with rooms in region');
                $item_compareRoomRegion->signal_connect('activate' => sub {

                    $self->compareRoomCallback(FALSE);
                });
                $subSubMenu_compareRoom->append($item_compareRoomRegion);

                my $item_compareRoomModel = Gtk3::MenuItem->new('...with rooms in whole world');
                $item_compareRoomModel->signal_connect('activate' => sub {

                    $self->compareRoomCallback(TRUE);
                });
                $subSubMenu_compareRoom->append($item_compareRoomModel);

            my $item_compareRoom = Gtk3::MenuItem->new('_Compare room');
            $item_compareRoom->set_submenu($subSubMenu_compareRoom);
            $subMenu_moveRooms->append($item_compareRoom);

        my $item_moveRooms = Gtk3::MenuItem->new('_Move rooms/labels');
        $item_moveRooms->set_submenu($subMenu_moveRooms);
        $menu_rooms->append($item_moveRooms);

            # 'Add pattern' submenu
            my $subMenu_exitPatterns = Gtk3::Menu->new();

            my $item_addFailedExitRoom = Gtk3::MenuItem->new('Add _failed exit...');
            $item_addFailedExitRoom->signal_connect('activate' => sub {

                $self->addFailedExitCallback(FALSE, $self->selectedRoom);
            });
            $subMenu_exitPatterns->append($item_addFailedExitRoom);

            $subMenu_exitPatterns->append(Gtk3::SeparatorMenuItem->new());  # Separator

            my $item_addInvoluntaryExitRoom = Gtk3::MenuItem->new('Add _involuntary exit...');
            $item_addInvoluntaryExitRoom->signal_connect('activate' => sub {

                $self->addInvoluntaryExitCallback($self->selectedRoom);
            });
            $subMenu_exitPatterns->append($item_addInvoluntaryExitRoom);

            my $item_addRepulseExitRoom = Gtk3::MenuItem->new('Add _repulse exit...');
            $item_addRepulseExitRoom->signal_connect('activate' => sub {

                $self->addRepulseExitCallback($self->selectedRoom);
            });
            $subMenu_exitPatterns->append($item_addRepulseExitRoom);

            $subMenu_exitPatterns->append(Gtk3::SeparatorMenuItem->new());  # Separator

            my $item_addSpecialDepartRoom = Gtk3::MenuItem->new('Add _special departure...');
            $item_addSpecialDepartRoom->signal_connect('activate' => sub {

                $self->addSpecialDepartureCallback($self->selectedRoom);
            });
            $subMenu_exitPatterns->append($item_addSpecialDepartRoom);

            my $item_addUnspecifiedRoom = Gtk3::MenuItem->new('Add _unspecified room pattern...');
            $item_addUnspecifiedRoom->signal_connect('activate' => sub {

                $self->addUnspecifiedPatternCallback($self->selectedRoom);
            });
            $subMenu_exitPatterns->append($item_addUnspecifiedRoom);

        $menu_rooms->append(Gtk3::SeparatorMenuItem->new());  # Separator

        my $item_patterns = Gtk3::MenuItem->new('Add pa_ttern');
        $item_patterns->set_submenu($subMenu_exitPatterns);
        $menu_rooms->append($item_patterns);

            # 'Add to model' submenu
            my $subMenu_addToModel = Gtk3::Menu->new();

            my $item_addRoomContents = Gtk3::MenuItem->new('Add _contents...');
            $item_addRoomContents->signal_connect('activate' => sub {

                $self->addContentsCallback(FALSE);
            });
            $subMenu_addToModel->append($item_addRoomContents);
            # (Also requires $self->mapObj->currentRoom that's the same as $self->selectedRoom
            if (! $self->mapObj->currentRoom || $self->mapObj->currentRoom ne $self->selectedRoom) {

                $item_addRoomContents->set_sensitive(FALSE);
            }

            my $item_addContentsString = Gtk3::MenuItem->new('Add c_ontents from string...');
            $item_addContentsString->signal_connect('activate' => sub {

                $self->addContentsCallback(TRUE);
            });
            $subMenu_addToModel->append($item_addContentsString);

            $subMenu_addToModel->append(Gtk3::SeparatorMenuItem->new()); # Separator

            my $item_addHiddenObj = Gtk3::MenuItem->new('Add _hidden object...');
            $item_addHiddenObj->signal_connect('activate' => sub {

                $self->addHiddenObjCallback(FALSE);
            });
            $subMenu_addToModel->append($item_addHiddenObj);
            # (Also requires $self->mapObj->currentRoom that's the same as $self->selectedRoom
            if (! $self->mapObj->currentRoom || $self->mapObj->currentRoom ne $self->selectedRoom) {

                $item_addHiddenObj->set_sensitive(FALSE);
            }

            my $item_addHiddenString = Gtk3::MenuItem->new('Add h_idden object from string...');
            $item_addHiddenString->signal_connect('activate' => sub {

                $self->addHiddenObjCallback(TRUE);
            });
            $subMenu_addToModel->append($item_addHiddenString);

            $subMenu_addToModel->append(Gtk3::SeparatorMenuItem->new()); # Separator

            my $item_addSearchResult = Gtk3::MenuItem->new('Add _search result...');
            $item_addSearchResult->signal_connect('activate' => sub {

                $self->addSearchResultCallback();
            });
            $subMenu_addToModel->append($item_addSearchResult);
            # (Also requires $self->mapObj->currentRoom that's the same as $self->selectedRoom)
            if (! $self->mapObj->currentRoom || $self->mapObj->currentRoom ne $self->selectedRoom) {

                $item_addSearchResult->set_sensitive(FALSE);
            }

        my $item_addToModel = Gtk3::MenuItem->new('Add to m_odel');
        $item_addToModel->set_submenu($subMenu_addToModel);
        $menu_rooms->append($item_addToModel);

        $menu_rooms->append(Gtk3::SeparatorMenuItem->new());  # Separator

             # 'Add/set exits' submenu
            my $subMenu_setExits = Gtk3::Menu->new();

            my $item_addExit = Gtk3::MenuItem->new('Add _normal exit...');
            $item_addExit->signal_connect('activate' => sub {

                $self->addExitCallback(FALSE);      # FALSE - not a hidden exit
            });
            $subMenu_setExits->append($item_addExit);
            # (Also requires the selected room's ->wildMode to be 'normal' or 'border')
            if ($self->selectedRoom->wildMode eq 'wild') {

                $item_addExit->set_sensitive(FALSE);
            }

            my $item_addHiddenExit = Gtk3::MenuItem->new('Add _hidden exit...');
            $item_addHiddenExit->signal_connect('activate' => sub {

                $self->addExitCallback(TRUE);       # TRUE - a hidden exit
            });
            $subMenu_setExits->append($item_addHiddenExit);
            # (Also requires the selected room's ->wildMode to be 'normal' or 'border')
            if ($self->selectedRoom->wildMode eq 'wild') {

                $item_addHiddenExit->set_sensitive(FALSE);
            }

            $subMenu_setExits->append(Gtk3::SeparatorMenuItem->new()); # Separator

            my $item_addMultiple = Gtk3::MenuItem->new('Add _multiple exits...');
            $item_addMultiple->signal_connect('activate' => sub {

                $self->addMultipleExitsCallback();
            });
            $subMenu_setExits->append($item_addMultiple);

            $subMenu_setExits->append(Gtk3::SeparatorMenuItem->new()); # Separator

            my $item_removeChecked = Gtk3::MenuItem->new('Remove _checked direction...');
            $item_removeChecked->signal_connect('activate' => sub {

                $self->removeCheckedDirCallback(FALSE);
            });
            $subMenu_setExits->append($item_removeChecked);
            # (Also requires the selected room's ->checkedDirHash to be non-empty)
            if (! $self->selectedRoom->checkedDirHash) {

                $item_removeChecked->set_sensitive(FALSE);
            }

            my $item_removeCheckedAll = Gtk3::MenuItem->new('Remove _all checked directions');
            $item_removeCheckedAll->signal_connect('activate' => sub {

                $self->removeCheckedDirCallback(TRUE);
            });
            $subMenu_setExits->append($item_removeCheckedAll);
            # (Also requires the selected room's ->checkedDirHash to be non-empty)
            if (! $self->selectedRoom->checkedDirHash) {

                $item_removeCheckedAll->set_sensitive(FALSE);
            }

            $subMenu_setExits->append(Gtk3::SeparatorMenuItem->new()); # Separator

            my $item_markNormal = Gtk3::MenuItem->new('Mark room as n_ormal');
            $item_markNormal->signal_connect('activate' => sub {

                $self->setWildCallback('normal');
            });
            $subMenu_setExits->append($item_markNormal);

            my $item_markWild = Gtk3::MenuItem->new('Mark room as _wilderness');
            $item_markWild->signal_connect('activate' => sub {

                $self->setWildCallback('wild');
            });
            $subMenu_setExits->append($item_markWild);
            # (Also requires $self->session->currentWorld->basicMappingFlag to be FALSE)
            if ($self->session->currentWorld->basicMappingFlag) {

                $item_markWild->set_sensitive(FALSE);
            }

            my $item_markBorder = Gtk3::MenuItem->new('Mark room as wilderness _border');
            $item_markBorder->signal_connect('activate' => sub {

                $self->setWildCallback('border');
            });
            $subMenu_setExits->append($item_markBorder);
            # (Also requires $self->session->currentWorld->basicMappingFlag to be FALSE)
            if ($self->session->currentWorld->basicMappingFlag) {

                $item_markBorder->set_sensitive(FALSE);
            }

        my $item_setExits = Gtk3::ImageMenuItem->new('Add/set _exits');
        my $img_setExits = Gtk3::Image->new_from_stock('gtk-add', 'menu');
        $item_setExits->set_image($img_setExits);
        $item_setExits->set_submenu($subMenu_setExits);
        $menu_rooms->append($item_setExits);

        my $item_selectExit = Gtk3::MenuItem->new('Se_lect exit...');
        $item_selectExit->signal_connect('activate' => sub {

            $self->selectExitCallback();
        });
        $menu_rooms->append($item_selectExit);

        $menu_rooms->append(Gtk3::SeparatorMenuItem->new());  # Separator

        my $item_editRoom = Gtk3::ImageMenuItem->new('Ed_it room...');
        my $img_editRoom = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
        $item_editRoom->set_image($img_editRoom);
        $item_editRoom->signal_connect('activate' => sub {

            if ($self->selectedRoom) {

                # Open the room's 'edit' window
                $self->createFreeWin(
                    'Games::Axmud::EditWin::ModelObj::Room',
                    $self,
                    $self->session,
                    'Edit ' . $self->selectedRoom->category . ' model object',
                    $self->selectedRoom,
                    FALSE,                          # Not temporary
                );
            }
        });
        $menu_rooms->append($item_editRoom);

            # 'Set room text' submenu
            my $subMenu_setRoomText = Gtk3::Menu->new();

            my $item_setRoomTag = Gtk3::MenuItem->new('Set room _tag...');
            $item_setRoomTag->signal_connect('activate' => sub {

                $self->setRoomTagCallback();
            });
            $subMenu_setRoomText->append($item_setRoomTag);

            my $item_setGuild = Gtk3::MenuItem->new('Set room _guild...');
            $item_setGuild->signal_connect('activate' => sub {

                $self->setRoomGuildCallback();
            });
            $subMenu_setRoomText->append($item_setGuild);

            $subMenu_setRoomText->append(Gtk3::SeparatorMenuItem->new());  # Separator

            my $item_resetPositions = Gtk3::MenuItem->new('_Reset text posit_ions');
            $item_resetPositions->signal_connect('activate' => sub {

                $self->resetRoomOffsetsCallback();
            });
            $subMenu_setRoomText->append($item_resetPositions);

        my $item_setRoomText = Gtk3::MenuItem->new('Set _room text');
        $item_setRoomText->set_submenu($subMenu_setRoomText);
        $menu_rooms->append($item_setRoomText);

            # 'Toggle room flag' submenu
            my $subMenu_toggleRoomFlag = Gtk3::Menu->new();

            if ($self->worldModelObj->roomFlagShowMode eq 'default') {

                # Show all room flags, sorted by filter
                foreach my $filter ($axmud::CLIENT->constRoomFilterList) {

                    # A sub-sub menu for $filter
                    my $subSubMenu_filter = Gtk3::Menu->new();

                    my @nameList = $self->worldModelObj->getRoomFlagsInFilter($filter);
                    foreach my $name (@nameList) {

                        my $obj = $self->worldModelObj->ivShow('roomFlagHash', $name);
                        if ($obj) {

                            my $menuItem = Gtk3::MenuItem->new($obj->descrip);
                            $menuItem->signal_connect('activate' => sub {

                                # Toggle the flags for all selected rooms, redraw them and (if the
                                #   flag is one of the hazardous room flags) recalculate the
                                #   regionmap's paths. The TRUE argument tells the world model to
                                #   redraw the rooms
                                $self->worldModelObj->toggleRoomFlags(
                                    $self->session,
                                    TRUE,
                                    $obj->name,
                                    $self->compileSelectedRooms(),
                                );
                            });
                            $subSubMenu_filter->append($menuItem);
                        }
                    }

                    if (! @nameList) {

                        my $menuItem = Gtk3::MenuItem->new('(No flags in this filter)');
                        $menuItem->set_sensitive(FALSE);
                        $subSubMenu_filter->append($menuItem);
                    }

                    my $menuItem = Gtk3::MenuItem->new(ucfirst($filter));
                    $menuItem->set_submenu($subSubMenu_filter);
                    $subMenu_toggleRoomFlag->append($menuItem);
                }

            } else {

                # Show selected room flags, sorted only by priority
                my %showHash = $self->worldModelObj->getVisibleRoomFlags();
                if (%showHash) {

                    foreach my $obj (sort {$a->priority <=> $b->priority} (values %showHash)) {

                        my $menuItem = Gtk3::MenuItem->new($obj->descrip);
                        $menuItem->signal_connect('activate' => sub {

                            # Toggle the flags for all selected rooms, redraw them and (if the
                            #   flag is one of the hazardous room flags) recalculate the
                            #   regionmap's paths. The TRUE argument tells the world model to
                            #   redraw the rooms
                            $self->worldModelObj->toggleRoomFlags(
                                $self->session,
                                TRUE,
                                $obj->name,
                                $self->compileSelectedRooms(),
                            );
                        });
                        $subMenu_toggleRoomFlag->append($menuItem);
                    }

                } else {

                    my $menuItem = Gtk3::MenuItem->new('(None are marked visible)');
                    $menuItem->set_sensitive(FALSE);
                    $subMenu_toggleRoomFlag->append($menuItem);
                }
            }

        my $item_toggleRoomFlag = Gtk3::MenuItem->new('To_ggle room flags');
        $item_toggleRoomFlag->set_submenu($subMenu_toggleRoomFlag);
        $menu_rooms->append($item_toggleRoomFlag);

            # 'Other room features' submenu
            my $subMenu_roomFeatures = Gtk3::Menu->new();

                # 'Update character visits' sub-submenu
                my $subSubMenu_updateVisits = Gtk3::Menu->new();

                my $item_increaseSetCurrent = Gtk3::MenuItem->new('Increase & set _current');
                $item_increaseSetCurrent->signal_connect('activate' => sub {

                    $self->updateVisitsCallback('increase');
                    $self->mapObj->setCurrentRoom($self->selectedRoom);
                });
                $subSubMenu_updateVisits->append($item_increaseSetCurrent);

                $subSubMenu_updateVisits->append(Gtk3::SeparatorMenuItem->new()); # Separator

                my $item_increaseVisits = Gtk3::MenuItem->new('_Increase by one');
                $item_increaseVisits->signal_connect('activate' => sub {

                    $self->updateVisitsCallback('increase');
                });
                $subSubMenu_updateVisits->append($item_increaseVisits);

                my $item_decreaseVisits = Gtk3::MenuItem->new('_Decrease by one');
                $item_decreaseVisits->signal_connect('activate' => sub {

                    $self->updateVisitsCallback('decrease');
                });
                $subSubMenu_updateVisits->append($item_decreaseVisits);

                my $item_manualVisits = Gtk3::MenuItem->new('Set _manually');
                $item_manualVisits->signal_connect('activate' => sub {

                    $self->updateVisitsCallback('manual');
                });
                $subSubMenu_updateVisits->append($item_manualVisits);

                my $item_resetVisits = Gtk3::MenuItem->new('_Reset to zero');
                $item_resetVisits->signal_connect('activate' => sub {

                    $self->updateVisitsCallback('reset');
                });
                $subSubMenu_updateVisits->append($item_resetVisits);

                $subSubMenu_updateVisits->append(Gtk3::SeparatorMenuItem->new()); # Separator

                my $item_toggleGraffiti = Gtk3::MenuItem->new('Toggle _graffiti');
                $item_toggleGraffiti->signal_connect('activate' => sub {

                    $self->toggleGraffitiCallback();
                });
                $subSubMenu_updateVisits->append($item_toggleGraffiti);
                # (Also requires $self->graffitiModeFlag)
                if (! $self->graffitiModeFlag) {

                    $item_toggleGraffiti->set_sensitive(FALSE);
                }

            my $item_updateVisits = Gtk3::MenuItem->new('Update character _visits');
            $item_updateVisits->set_submenu($subSubMenu_updateVisits);
            $subMenu_roomFeatures->append($item_updateVisits);

            # 'Room exclusivity' submenu
            my $subMenu_exclusivity = Gtk3::Menu->new();

                my $item_toggleExclusivity = Gtk3::MenuItem->new('_Toggle exclusivity');
                $item_toggleExclusivity->signal_connect('activate' => sub {

                    $self->toggleExclusiveProfileCallback();
                });
                $subMenu_exclusivity->append($item_toggleExclusivity);

                my $item_addExclusiveProf = Gtk3::MenuItem->new('_Add exclusive profile...');
                $item_addExclusiveProf->signal_connect('activate' => sub {

                    $self->addExclusiveProfileCallback();
                });
                $subMenu_exclusivity->append($item_addExclusiveProf);

                my $item_clearExclusiveProf = Gtk3::MenuItem->new('_Clear exclusive profiles');
                $item_clearExclusiveProf->signal_connect('activate' => sub {

                    $self->resetExclusiveProfileCallback();
                });
                $subMenu_exclusivity->append($item_clearExclusiveProf);

            my $item_exclusivity = Gtk3::MenuItem->new('Room _exclusivity');
            $item_exclusivity->set_submenu($subMenu_exclusivity);
            $subMenu_roomFeatures->append($item_exclusivity);

                # 'Source code' sub-submenu
                my $subSubMenu_sourceCode = Gtk3::Menu->new();

                my $item_setFilePath = Gtk3::MenuItem->new('_Set file path...');
                $item_setFilePath->signal_connect('activate' => sub {

                    $self->setFilePathCallback();
                });
                $subSubMenu_sourceCode->append($item_setFilePath);

                my $item_setVirtualArea = Gtk3::MenuItem->new('Set virtual _area...');
                $item_setVirtualArea->signal_connect('activate' => sub {

                    $self->setVirtualAreaCallback(TRUE);
                });
                $subSubMenu_sourceCode->append($item_setVirtualArea);

                my $item_resetVirtualArea = Gtk3::MenuItem->new('_Reset virtual area...');
                $item_resetVirtualArea->signal_connect('activate' => sub {

                    $self->setVirtualAreaCallback(FALSE);
                });
                $subSubMenu_sourceCode->append($item_resetVirtualArea);

                $subSubMenu_sourceCode->append(Gtk3::SeparatorMenuItem->new());  # Separator

                my $item_viewSource = Gtk3::MenuItem->new('_View source file...');
                $item_viewSource->signal_connect('activate' => sub {

                    my $flag;

                    if ($self->selectedRoom) {

                        if (! $self->selectedRoom->virtualAreaPath) {
                            $flag = FALSE;
                        } else {
                            $flag = TRUE;

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

                        # Show source code file
                        $self->quickFreeWin(
                            'Games::Axmud::OtherWin::SourceCode',
                            $self->session,
                            # Config
                            'model_obj' => $self->selectedRoom,
                            'virtual_flag' => $flag,
                        );
                    }
                });
                $subSubMenu_sourceCode->append($item_viewSource);
                # (Also requires either $self->selectedRoom->sourceCodePath or
                #   $self->selectedRoom->virtualAreaPath)
                if (
                    ! $self->selectedRoom->sourceCodePath
                    && ! $self->selectedRoom->virtualAreaPath
                ) {
                    $item_viewSource->set_sensitive(FALSE);
                }

                my $item_editSource = Gtk3::MenuItem->new('Edit so_urce file...');
                $item_editSource->signal_connect('activate' => sub {

                    if ($self->selectedRoom) {

                        if (! $self->selectedRoom->virtualAreaPath) {

                            # Edit source code file
                            $self->editFileCallback();

                        } else {

                            # Edit virtual area file
                            $self->editFileCallback(TRUE);
                        }
                    }
                });
                $subSubMenu_sourceCode->append($item_editSource);
                # (Also requires either $self->selectedRoom->sourceCodePath or
                #   $self->selectedRoom->virtualAreaPath)
                if (
                    ! $self->selectedRoom->sourceCodePath
                    && ! $self->selectedRoom->virtualAreaPath
                ) {
                    $item_editSource->set_sensitive(FALSE);
                }

            my $item_sourceCode = Gtk3::MenuItem->new('Source _code');
            $item_sourceCode->set_submenu($subSubMenu_sourceCode);
            $subMenu_roomFeatures->append($item_sourceCode);

            $subMenu_roomFeatures->append(Gtk3::SeparatorMenuItem->new());  # Separator

            my $item_setInteriorOffsets = Gtk3::MenuItem->new('_Synchronise grid coordinates...');
            $item_setInteriorOffsets->signal_connect('activate' => sub {

                $self->setInteriorOffsetsCallback();
            });
            $subMenu_roomFeatures->append($item_setInteriorOffsets);

            my $item_resetInteriorOffsets = Gtk3::MenuItem->new('_Reset grid coordinates');
            $item_resetInteriorOffsets->signal_connect('activate' => sub {

                $self->resetInteriorOffsetsCallback();
            });
            $subMenu_roomFeatures->append($item_resetInteriorOffsets);

        my $item_roomFeatures = Gtk3::MenuItem->new('Ot_her room features');
        $item_roomFeatures->set_submenu($subMenu_roomFeatures);
        $menu_rooms->append($item_roomFeatures);

        $menu_rooms->append(Gtk3::SeparatorMenuItem->new());  # Separator

        my $item_deleteRoom = Gtk3::ImageMenuItem->new('_Delete room');
        my $img_deleteRoom = Gtk3::Image->new_from_stock('gtk-delete', 'menu');
        $item_deleteRoom->set_image($img_deleteRoom);
        $item_deleteRoom->signal_connect('activate' => sub {

            $self->deleteRoomsCallback();
        });
        $menu_rooms->append($item_deleteRoom);

        # Setup complete
        $menu_rooms->show_all();

        return $menu_rooms;
    }

    sub enableRoomTagsPopupMenu {

        # Called by $self->canvasObjEventHandler
        # Creates a popup-menu for the selected room tag
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments or if the widget can't be created
        #   Otherwise returns the Gtk3::Menu created

        my ($self, $check) = @_;

        # Check for improper arguments
        if (defined $check) {

            return $axmud::CLIENT->writeImproper(
                $self->_objClass . '->enableRoomTagsPopupMenu',
                @_,
            );
        }

        # Set up the popup menu
        my $menu_tags = Gtk3::Menu->new();
        if (! $menu_tags) {

            return undef;
        }

        # (Everything here assumes $self->currentRegionmap and $self->selectedRoomTag)

        my $item_editTag = Gtk3::MenuItem->new('_Set room tag...');
        $item_editTag->signal_connect('activate' => sub {

            $self->setRoomTagCallback();
        });
        $menu_tags->append($item_editTag);

        my $item_resetPosition = Gtk3::MenuItem->new('_Reset position');
        $item_resetPosition->signal_connect('activate' => sub {

            if ($self->selectedRoomTag) {

                $self->worldModelObj->resetRoomOffsets(
                    TRUE,                       # Update Automapper windows now
                    1,                          # Mode 1 - reset room tag only
                    $self->selectedRoomTag,     # Set to the parent room's blessed reference
                );
            }
        });
        $menu_tags->append($item_resetPosition);

        # Setup complete
        $menu_tags->show_all();

        return $menu_tags;
    }

    sub enableRoomGuildsPopupMenu {

        # Called by $self->canvasObjEventHandler
        # Creates a popup-menu for the selected room guild
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments or if the widget can't be created
        #   Otherwise returns the Gtk3::Menu created

        my ($self, $check) = @_;

        # Check for improper arguments
        if (defined $check) {

            return $axmud::CLIENT->writeImproper(
                $self->_objClass . '->enableRoomGuildsPopupMenu',
                @_,
            );
        }

        # Set up the popup menu
        my $menu_guilds = Gtk3::Menu->new();
        if (! $menu_guilds) {

            return undef;
        }

        # (Everything here assumes $self->currentRegionmap and $self->selectedRoomGuild)

        my $item_editGuild = Gtk3::MenuItem->new('_Set room guild...');
        $item_editGuild->signal_connect('activate' => sub {

            $self->setRoomGuildCallback();
        });
        $menu_guilds->append($item_editGuild);

        my $item_resetPosition = Gtk3::MenuItem->new('_Reset position');
        $item_resetPosition->signal_connect('activate' => sub {

            if ($self->selectedRoomGuild) {

                $self->worldModelObj->resetRoomOffsets(
                    TRUE,                       # Update Automapper windows now
                    2,                          # Mode 2 - reset room guild only
                    $self->selectedRoomGuild,   # Set to the parent room's blessed reference
                );
            }
        });
        $menu_guilds->append($item_resetPosition);

        # Setup complete
        $menu_guilds->show_all();

        return $menu_guilds;
    }

    sub enableExitsPopupMenu {

        # Called by $self->canvasObjEventHandler
        # Creates a popup-menu for the selected exit
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments or if the widget can't be created
        #   Otherwise returns the Gtk3::Menu created

        my ($self, $check) = @_;

        # Local variables
        my @titleList;

        # Check for improper arguments
        if (defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->enableExitsPopupMenu', @_);
        }

        # Set up the popup menu
        my $menu_exits = Gtk3::Menu->new();
        if (! $menu_exits) {

            return undef;
        }

        # (Everything here assumes $self->currentRegionmap and $self->selectedExit)

            # 'Allocate map direction' submenu
            my $subMenu_setDir = Gtk3::Menu->new();

            my $item_changeDir = Gtk3::MenuItem->new('_Change direction...');
            $item_changeDir->signal_connect('activate' => sub {

                $self->changeDirCallback();
            });
            $subMenu_setDir->append($item_changeDir);
            # (Also requires $self->selectedExit->drawMode is 'primary' or 'perm_alloc'
            if (
                $self->selectedExit->drawMode ne 'primary'
                && $self->selectedExit->drawMode ne 'perm_alloc'
            ) {
                $item_changeDir->set_sensitive(FALSE);
            }

            my $item_altDir = Gtk3::MenuItem->new('Set _alternative direction(s)...');
            $item_altDir->signal_connect('activate' => sub {

                $self->setAltDirCallback();
            });
            $subMenu_setDir->append($item_altDir);

        my $item_setDir = Gtk3::MenuItem->new('Set di_rection');
        $item_setDir->set_submenu($subMenu_setDir);
        $menu_exits->append($item_setDir);

        my $item_setAssisted = Gtk3::MenuItem->new('Set assisted _move...');
        $item_setAssisted->signal_connect('activate' => sub {

            $self->setAssistedMoveCallback();
        });
        $menu_exits->append($item_setAssisted);
        # (Also requires $self->selectedExit->drawMode 'primary', 'temp_unalloc' or 'perm_unalloc')
        if ($self->selectedExit->drawMode eq 'temp_alloc') {

            $item_setAssisted->set_sensitive(FALSE);
        }

            # 'Allocate map direction' submenu
            my $subMenu_allocateMapDir = Gtk3::Menu->new();

            my $item_allocatePrimary = Gtk3::MenuItem->new('Choose _direction...');
            $item_allocatePrimary->signal_connect('activate' => sub {

                $self->allocateMapDirCallback();
            });
            $subMenu_allocateMapDir->append($item_allocatePrimary);


            my $item_confirmTwoWay = Gtk3::MenuItem->new('Confirm _two-way exit...');
            $item_confirmTwoWay->signal_connect('activate' => sub {

                $self->confirmTwoWayCallback();
            });
            $subMenu_allocateMapDir->append($item_confirmTwoWay);

        my $item_allocateMapDir = Gtk3::MenuItem->new('_Allocate map direction...');
        $item_allocateMapDir->set_submenu($subMenu_allocateMapDir);
        $menu_exits->append($item_allocateMapDir);
        # (Also requires $self->selectedExit->drawMode is 'temp_alloc' or 'temp_unalloc')
        if (
            $self->selectedExit->drawMode ne 'temp_alloc'
            && $self->selectedExit->drawMode ne 'temp_unalloc'
        ) {
            $item_allocateMapDir->set_sensitive(FALSE);
        }

        my $item_allocateShadow = Gtk3::MenuItem->new('Allocate _shadow...');
        $item_allocateShadow->signal_connect('activate' => sub {

            $self->allocateShadowCallback();
        });
        $menu_exits->append($item_allocateShadow);
        # (Also requires $self->selectedExit->drawMode is 'temp_alloc' or 'temp_unalloc')
        if (
            $self->selectedExit->drawMode ne 'temp_alloc'
            && $self->selectedExit->drawMode ne 'temp_unalloc'
        ) {
            $item_allocateShadow->set_sensitive(FALSE);
        }

        $menu_exits->append(Gtk3::SeparatorMenuItem->new());  # Separator

        my $item_connectExitToClick = Gtk3::MenuItem->new('_Connect to click');
        $item_connectExitToClick->signal_connect('activate' => sub {

            $self->connectToClickCallback();
        });
        $menu_exits->append($item_connectExitToClick);
        # (Also requires $self->selectedExit->drawMode 'primary', 'temp_unalloc' or 'perm_unalloc')
        if ($self->selectedExit->drawMode eq 'temp_alloc') {

            $item_connectExitToClick->set_sensitive(FALSE);
        }

        my $item_disconnectExit = Gtk3::MenuItem->new('D_isconnect exit');
        $item_disconnectExit->signal_connect('activate' => sub {

            $self->disconnectExitCallback();
        });
        $menu_exits->append($item_disconnectExit);

        $menu_exits->append(Gtk3::SeparatorMenuItem->new());  # Separator

        my $item_addExitBend = Gtk3::MenuItem->new('Add _bend');
        $item_addExitBend->signal_connect('activate' => sub {

            $self->addBendCallback();
        });
        $menu_exits->append($item_addExitBend);
        # (Also requires a $self->selectedExit that's a one-way or two-way broken exit, not a region
        #   exit, and also defined values for $self->exitClickXPosn and $self->exitClickYPosn)
        if (
            (! $self->selectedExit->oneWayFlag && ! $self->selectedExit->twinExit)
            || $self->selectedExit->regionFlag
            || ! defined $self->exitClickXPosn
            || ! defined $self->exitClickYPosn
        ) {
            $item_addExitBend->set_sensitive(FALSE);
        }

        my $item_removeExitBend = Gtk3::MenuItem->new('Remo_ve bend');
        $item_removeExitBend->signal_connect('activate' => sub {

            $self->removeBendCallback();
        });
        $menu_exits->append($item_removeExitBend);
        # (Also requires a $self->selectedExit that's a one-way or two-way exit with a bend, and
        #   also defined values for $self->exitClickXPosn and $self->exitClickYPosn)
        if (
            (! $self->selectedExit->oneWayFlag && ! $self->selectedExit->twinExit)
            || ! $self->selectedExit->bendOffsetList
            || ! defined $self->exitClickXPosn
            || ! defined $self->exitClickYPosn
        ) {
            $item_removeExitBend->set_sensitive(FALSE);
        }

        $menu_exits->append(Gtk3::SeparatorMenuItem->new());  # Separator

            # 'Set ornaments' submenu
            my $subMenu_setOrnament = Gtk3::Menu->new();

            # Create a list of exit ornament types, in groups of two, in the form
            #   (menu_item_title, exit_ornament_type)
            @titleList = (
                '_No ornament', 'none',
                '_Openable exit', 'open',
                '_Lockable exit', 'lock',
                '_Pickable exit', 'pick',
                '_Breakable exit', 'break',
                '_Impassable exit', 'impass',
                '_Mystery exit', 'mystery',
            );

            do {

                my ($title, $type);

                $title = shift @titleList;
                $type = shift @titleList;

                my $menuItem = Gtk3::MenuItem->new($title);
                $menuItem->signal_connect('activate' => sub {

                    $self->exitOrnamentCallback($type);
                });
                $subMenu_setOrnament->append($menuItem);

            } until (! @titleList);

            $subMenu_setOrnament->append(Gtk3::SeparatorMenuItem->new());   # Separator

            my $item_setTwinOrnament = Gtk3::CheckMenuItem->new('Also set _twin exits');
            $item_setTwinOrnament->set_active($self->worldModelObj->setTwinOrnamentFlag);
            $item_setTwinOrnament->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFlag(
                        'setTwinOrnamentFlag',
                        $item_setTwinOrnament->get_active(),
                        FALSE,      # Don't call $self->redrawRegions
                        'also_set_twin_exits',
                    );
                }
            });
            $subMenu_setOrnament->append($item_setTwinOrnament);

        my $item_setOrnament = Gtk3::MenuItem->new('Set _ornaments');
        $item_setOrnament->set_submenu($subMenu_setOrnament);
        $menu_exits->append($item_setOrnament);

            # 'Set exit type' submenu
            my $subMenu_setExitType = Gtk3::Menu->new();

                # 'Set hidden' sub-submenu
                my $subSubMenu_setHidden = Gtk3::Menu->new();

                my $item_setHiddenExit = Gtk3::MenuItem->new('Mark exit _hidden');
                $item_setHiddenExit->signal_connect('activate' => sub {

                    $self->hiddenExitCallback(TRUE);
                });
                $subSubMenu_setHidden->append($item_setHiddenExit);

                my $item_setNotHiddenExit = Gtk3::MenuItem->new('Mark exit _not hidden');
                $item_setNotHiddenExit->signal_connect('activate' => sub {

                    $self->hiddenExitCallback(FALSE);
                });
                $subSubMenu_setHidden->append($item_setNotHiddenExit);

            my $item_setHidden = Gtk3::MenuItem->new('Set _hidden');
            $item_setHidden->set_submenu($subSubMenu_setHidden);
            $subMenu_setExitType->append($item_setHidden);

                # 'Set broken' sub-submenu
                my $subSubMenu_setBroken = Gtk3::Menu->new();

                my $item_markBrokenExit = Gtk3::MenuItem->new('_Mark exit as broken');
                $item_markBrokenExit->signal_connect('activate' => sub {

                    $self->markBrokenExitCallback();
                });
                $subSubMenu_setBroken->append($item_markBrokenExit);

                my $item_toggleBrokenExit = Gtk3::MenuItem->new('_Toggle bent broken exit');
                $item_toggleBrokenExit->signal_connect('activate' => sub {

                    $self->worldModelObj->toggleBentExit(
                        TRUE,                       # Update Automapper windows now
                        $self->selectedExit,
                    );
                });
                $subSubMenu_setBroken->append($item_toggleBrokenExit);
                # (Also requires $self->selectedExit->brokenFlag)
                if (! $self->selectedExit->brokenFlag) {

                    $item_toggleBrokenExit->set_sensitive(FALSE);
                }

                $subSubMenu_setBroken->append(Gtk3::SeparatorMenuItem->new());  # Separator

                my $item_restoreBrokenExit = Gtk3::MenuItem->new('_Restore unbroken exit');
                $item_restoreBrokenExit->signal_connect('activate' => sub {

                    $self->restoreBrokenExitCallback();
                });
                $subSubMenu_setBroken->append($item_restoreBrokenExit);

            my $item_setBroken = Gtk3::MenuItem->new('Set _broken');
            $item_setBroken->set_submenu($subSubMenu_setBroken);
            $subMenu_setExitType->append($item_setBroken);

                # 'Set one-way' sub-submenu
                my $subSubMenu_setOneWay = Gtk3::Menu->new();

                my $item_markOneWayExit = Gtk3::MenuItem->new('_Mark exit as one-way');
                $item_markOneWayExit->signal_connect('activate' => sub {

                    $self->markOneWayExitCallback();
                });
                $subSubMenu_setOneWay->append($item_markOneWayExit);

                $subSubMenu_setOneWay->append(Gtk3::SeparatorMenuItem->new());  # Separator

                my $item_restoreUncertainExit = Gtk3::MenuItem->new('Restore _uncertain exit');
                $item_restoreUncertainExit->signal_connect('activate' => sub {

                    $self->restoreOneWayExitCallback(FALSE);
                });
                $subSubMenu_setOneWay->append($item_restoreUncertainExit);

                my $item_restoreTwoWayExit = Gtk3::MenuItem->new('Restore _two-way exit');
                $item_restoreTwoWayExit->signal_connect('activate' => sub {

                    $self->restoreOneWayExitCallback(TRUE);
                });
                $subSubMenu_setOneWay->append($item_restoreTwoWayExit);

                $subSubMenu_setOneWay->append(Gtk3::SeparatorMenuItem->new());  # Separator

                my $item_setIncomingDir = Gtk3::MenuItem->new('Set incoming _direction...');
                $item_setIncomingDir->signal_connect('activate' => sub {

                    $self->setIncomingDirCallback();
                });
                $subSubMenu_setOneWay->append($item_setIncomingDir);
                # (Also requires either a $self->selectedExit which is a one-way exit)
                if (! $self->selectedExit->oneWayFlag) {

                    $item_setIncomingDir->set_sensitive(FALSE);
                }

            my $item_setOneWay = Gtk3::MenuItem->new('Set _one-way');
            $item_setOneWay->set_submenu($subSubMenu_setOneWay);
            $subMenu_setExitType->append($item_setOneWay);

                # 'Set retracing' sub-submenu
                my $subSubMenu_setRetracing = Gtk3::Menu->new();

                my $item_markRetracingExit = Gtk3::MenuItem->new('_Mark exit as retracing');
                $item_markRetracingExit->signal_connect('activate' => sub {

                    $self->markRetracingExitCallback();
                });
                $subSubMenu_setRetracing->append($item_markRetracingExit);

                $subSubMenu_setRetracing->append(Gtk3::SeparatorMenuItem->new());    # Separator

                my $item_restoreRetracingExit = Gtk3::MenuItem->new('_Restore incomplete exit');
                $item_restoreRetracingExit->signal_connect('activate' => sub {

                    $self->restoreRetracingExitCallback();
                });
                $subSubMenu_setRetracing->append($item_restoreRetracingExit);

            my $item_setRetracing = Gtk3::MenuItem->new('Set _retracing');
            $item_setRetracing->set_submenu($subSubMenu_setRetracing);
            $subMenu_setExitType->append($item_setRetracing);

                # 'Set random' sub-submenu
                my $subSubMenu_setRandomExit = Gtk3::Menu->new();

                my $item_markRandomRegion = Gtk3::MenuItem->new(
                    'Set random destination in same _region',
                );
                $item_markRandomRegion->signal_connect('activate' => sub {

                    $self->markRandomExitCallback('same_region');
                });
                $subSubMenu_setRandomExit->append($item_markRandomRegion);

                my $item_markRandomAnywhere = Gtk3::MenuItem->new(
                    'Set random destination _anywhere',
                );
                $item_markRandomAnywhere->signal_connect('activate' => sub {

                    $self->markRandomExitCallback('any_region');
                });
                $subSubMenu_setRandomExit->append($item_markRandomAnywhere);

                my $item_randomTempRegion = Gtk3::MenuItem->new(
                    '_Create destination in temporary region',
                );
                $item_randomTempRegion->signal_connect('activate' => sub {

                    $self->markRandomExitCallback('temp_region');
                });
                $subSubMenu_setRandomExit->append($item_randomTempRegion);

                my $item_markRandomList = Gtk3::MenuItem->new('_Use list of random destinations');
                $item_markRandomList->signal_connect('activate' => sub {

                    $self->markRandomExitCallback('room_list');
                });
                $subSubMenu_setRandomExit->append($item_markRandomList);

                $subSubMenu_setRandomExit->append(Gtk3::SeparatorMenuItem->new());    # Separator

                my $item_restoreRandomExit = Gtk3::MenuItem->new('Restore _incomplete exit');
                $item_restoreRandomExit->signal_connect('activate' => sub {

                    $self->restoreRandomExitCallback();
                });
                $subSubMenu_setRandomExit->append($item_restoreRandomExit);

            my $item_setRandomExit = Gtk3::MenuItem->new('Set r_andom');
            $item_setRandomExit->set_submenu($subSubMenu_setRandomExit);
            $subMenu_setExitType->append($item_setRandomExit);

                # 'Set super' sub-submenu
                my $subSubMenu_setSuperExit = Gtk3::Menu->new();

                my $item_markSuper = Gtk3::MenuItem->new('Mark exit as _super-region exit');
                $item_markSuper->signal_connect('activate' => sub {

                    $self->markSuperExitCallback(FALSE);
                });
                $subSubMenu_setSuperExit->append($item_markSuper);

                my $item_markSuperExcl = Gtk3::MenuItem->new(
                    'Mark exit as _exclusive super-region exit',
                );
                $item_markSuperExcl->signal_connect('activate' => sub {

                    $self->markSuperExitCallback(TRUE);
                });
                $subSubMenu_setSuperExit->append($item_markSuperExcl);

                $subSubMenu_setSuperExit->append(Gtk3::SeparatorMenuItem->new());    # Separator

                my $item_markNotSuper = Gtk3::MenuItem->new('Mark exit as _normal region exit');
                $item_markNotSuper->signal_connect('activate' => sub {

                    $self->restoreSuperExitCallback();
                });
                $subSubMenu_setSuperExit->append($item_markNotSuper);

            my $item_setSuperExit = Gtk3::MenuItem->new('Set _super');
            $item_setSuperExit->set_submenu($subSubMenu_setSuperExit);
            $subMenu_setExitType->append($item_setSuperExit);
            # (Also requires $self->selectedExit->regionFlag)
            if (! $self->selectedExit->regionFlag) {

                $item_setSuperExit->set_sensitive(FALSE);
            }

            $subMenu_setExitType->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $item_setExitTwin = Gtk3::MenuItem->new('Set exit _twin...');
            $item_setExitTwin->signal_connect('activate' => sub {

                $self->setExitTwinCallback();
            });
            $subMenu_setExitType->append($item_setExitTwin);
            # (Also requires either a $self->selectedExit which is either a one-way exit or an
            #   uncertain exit)
            if (
                ! $self->selectedExit->oneWayFlag
                || ! (
                    $self->selectedExit->destRoom
                    && ! $self->selectedExit->twinExit
                    && ! $self->selectedExit->retraceFlag
                    && $self->selectedExit->randomType eq 'none'
                )
            ) {
                $item_setExitTwin->set_sensitive(FALSE);
            }

        my $item_setExitType = Gtk3::MenuItem->new('Set _exit type');
        $item_setExitType->set_submenu($subMenu_setExitType);
        $menu_exits->append($item_setExitType);

            # 'Exit tags' submenu
            my $subMenu_exitTags = Gtk3::Menu->new();

            my $item_editTag = Gtk3::MenuItem->new('_Edit exit tag');
            $item_editTag->signal_connect('activate' => sub {

                $self->editExitTagCallback();
            });
            $subMenu_exitTags->append($item_editTag);

            my $item_toggleExitTag = Gtk3::MenuItem->new('_Toggle exit tag');
            $item_toggleExitTag->signal_connect('activate' => sub {

                $self->toggleExitTagCallback();
            });
            $subMenu_exitTags->append($item_toggleExitTag);

            $subMenu_exitTags->append(Gtk3::SeparatorMenuItem->new());    # Separator

            my $item_resetPosition = Gtk3::MenuItem->new('_Reset text position');
            $item_resetPosition->signal_connect('activate' => sub {

                $self->resetExitOffsetsCallback();
            });
            $subMenu_exitTags->append($item_resetPosition);

        my $item_exitTags = Gtk3::MenuItem->new('Exit _tags');
        $item_exitTags->set_submenu($subMenu_exitTags);
        $menu_exits->append($item_exitTags);
        # (Also requires either a $self->selectedExit which is a region exit)
        if (! $self->selectedExit->regionFlag) {

            $item_exitTags->set_sensitive(FALSE);
        }

        $menu_exits->append(Gtk3::SeparatorMenuItem->new());  # Separator

        my $item_editExit = Gtk3::ImageMenuItem->new('Edit e_xit...');
        my $img_editExit = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
        $item_editExit->set_image($img_editExit);
        $item_editExit->signal_connect('activate' => sub {

            $self->editExitCallback();
        });
        $menu_exits->append($item_editExit);

        $menu_exits->append(Gtk3::SeparatorMenuItem->new());  # Separator

        my $item_deleteExit = Gtk3::ImageMenuItem->new('_Delete exit');
        my $img_deleteExit = Gtk3::Image->new_from_stock('gtk-add', 'menu');
        $item_deleteExit->set_image($img_deleteExit);
        $item_deleteExit->signal_connect('activate' => sub {

            $self->deleteExitCallback();
        });
        $menu_exits->append($item_deleteExit);

        # Setup complete
        $menu_exits->show_all();

        return $menu_exits;
    }

    sub enableExitTagsPopupMenu {

        # Called by $self->canvasObjEventHandler
        # Creates a popup-menu for the selected exit tag
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments or if the widget can't be created
        #   Otherwise returns the Gtk3::Menu created

        my ($self, $check) = @_;

        # Check for improper arguments
        if (defined $check) {

            return $axmud::CLIENT->writeImproper(
                $self->_objClass . '->enableExitTagsPopupMenu',
                @_,
            );
        }

        # Set up the popup menu
        my $menu_tags = Gtk3::Menu->new();
        if (! $menu_tags) {

            return undef;
        }

        # (Everything here assumes $self->currentRegionmap and $self->selectedExitTag)

        my $item_editTag = Gtk3::MenuItem->new('_Edit exit tag');
        $item_editTag->signal_connect('activate' => sub {

            $self->editExitTagCallback();
        });
        $menu_tags->append($item_editTag);

        my $item_cancelTag = Gtk3::MenuItem->new('_Cancel exit tag');
        $item_cancelTag->signal_connect('activate' => sub {

            $self->toggleExitTagCallback();
        });
        $menu_tags->append($item_cancelTag);

        $menu_tags->append(Gtk3::SeparatorMenuItem->new());  # Separator

        my $item_viewDestination = Gtk3::MenuItem->new('_View destination');
        $item_viewDestination->signal_connect('activate' => sub {

            $self->viewExitDestination();
        });
        $menu_tags->append($item_viewDestination);

        $menu_tags->append(Gtk3::SeparatorMenuItem->new());  # Separator

        my $item_resetPosition = Gtk3::MenuItem->new('_Reset position');
        $item_resetPosition->signal_connect('activate' => sub {

            $self->resetExitOffsetsCallback();
        });
        $menu_tags->append($item_resetPosition);

        # Setup complete
        $menu_tags->show_all();

        return $menu_tags;
    }

    sub enableLabelsPopupMenu {

        # Called by $self->canvasObjEventHandler
        # Creates a popup-menu for the selected label
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments or if the widget can't be created
        #   Otherwise returns the Gtk3::Menu created

        my ($self, $check) = @_;

        # Check for improper arguments
        if (defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->enableLabelsPopupMenu', @_);
        }

        # Set up the popup menu
        my $menu_labels = Gtk3::Menu->new();
        if (! $menu_labels) {

            return undef;
        }

        # (Everything here assumes $self->currentRegionmap and $self->selectedLabel)

        my $item_setLabel = Gtk3::ImageMenuItem->new('_Set label...');
        my $img_setLabel = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
        $item_setLabel->set_image($img_setLabel);
        $item_setLabel->signal_connect('activate' => sub {

            $self->setLabelCallback(FALSE)
        });
        $menu_labels->append($item_setLabel);

        my $item_customiseLabel = Gtk3::ImageMenuItem->new('_Customise label...');
        my $img_customiseLabel = Gtk3::Image->new_from_stock('gtk-edit', 'menu');
        $item_customiseLabel->set_image($img_customiseLabel);
        $item_customiseLabel->signal_connect('activate' => sub {

            $self->setLabelCallback(TRUE);
        });
        $menu_labels->append($item_customiseLabel);

        $menu_labels->append(Gtk3::SeparatorMenuItem->new());  # Separator

            # 'Set label style' submenu
            my $subMenu_setStyle = Gtk3::Menu->new();

            foreach my $style (
                sort {lc($a) cmp lc($b)} ($self->worldModelObj->ivKeys('mapLabelStyleHash'))
            ) {
                my $item_thisStyle = Gtk3::MenuItem->new($style);
                $item_thisStyle->signal_connect('activate' => sub {

                    $self->setLabelDirectCallback($style);
                });
                $subMenu_setStyle->append($item_thisStyle);
            }

        my $item_setStyle = Gtk3::MenuItem->new('S_et label style');
        $item_setStyle->set_submenu($subMenu_setStyle);
        $menu_labels->append($item_setStyle);
        # (Also requires at least one label style)
        if (! $self->worldModelObj->mapLabelStyleHash) {

            $item_setStyle->set_sensitive(FALSE);
        }

        $menu_labels->append(Gtk3::SeparatorMenuItem->new());  # Separator

        my $item_deleteLabel = Gtk3::ImageMenuItem->new('_Delete label');
        my $img_deleteLabel = Gtk3::Image->new_from_stock('gtk-delete', 'menu');
        $item_deleteLabel->set_image($img_deleteLabel);
        $item_deleteLabel->signal_connect('activate' => sub {

            if ($self->selectedLabel) {

                $self->worldModelObj->deleteLabels(
                    TRUE,           # Update Automapper windows now
                    $self->selectedLabel,
                );
            }
        });
        $menu_labels->append($item_deleteLabel);

        my $item_quickDelete = Gtk3::ImageMenuItem->new('_Quick label deletion...');
        my $img_quickDelete = Gtk3::Image->new_from_stock('gtk-delete', 'menu');
        $item_quickDelete->set_image($img_quickDelete);
        $item_quickDelete->signal_connect('activate' => sub {

            $self->session->pseudoCmd('quicklabeldelete', $self->pseudoCmdMode);
        });
        $menu_labels->append($item_quickDelete);

        # Setup complete
        $menu_labels->show_all();

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

            }
        }

        if (! @list) {

            # All button sets are visible (this shouldn't happen)
            return undef;
        }

        # Set up the popup menu
        my $popupMenu = Gtk3::Menu->new();
        if (! $popupMenu) {

            return undef;
        }

        # Add a title menu item, which does nothing
        my $title_item = Gtk3::MenuItem->new('Add button set:');
        $title_item->signal_connect('activate' => sub {

            return undef;
        });
        $title_item->set_sensitive(FALSE);
        $popupMenu->append($title_item);

        $popupMenu->append(Gtk3::SeparatorMenuItem->new());     # Separator

        # Fill the popup menu with button sets
        foreach my $descrip (@list) {

            my $menu_item = Gtk3::MenuItem->new($descrip);
            $menu_item->signal_connect('activate' => sub {

                # Add the set to the world model's list of button sets...
                $self->worldModelObj->add_buttonSet($hash{$descrip});
                # ...then redraw the window component containing the toolbar(s)
                $self->redrawWidgets('toolbar');
            });
            $popupMenu->append($menu_item);
        }

        # Also add a 'Cancel' menu item, which does nothing
        $popupMenu->append(Gtk3::SeparatorMenuItem->new());     # Separator

        my $cancel_item = Gtk3::MenuItem->new('Cancel');
        $cancel_item->signal_connect('activate' => sub {

            return undef;
        });
        $popupMenu->append($cancel_item);

        # Display the popup menu
        $popupMenu->popup(
            undef, undef, undef, undef,
            1,                              # Left mouse button
            Gtk3::get_current_event_time(),
        );

        $popupMenu->show_all();

        # Operation complete. Now wait for the user's response
        return 1;
    }

    sub removeToolbar {

        # Called by a ->signal_connect in $self->drawToolbar whenever the user clicks on the remove
        #   button in any toolbar except the original one
        # Removes the specified toolbar and updates IVs

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

            $radioButton_waitMode->set_active(TRUE);
        }
        $radioButton_waitMode->set_icon_widget(
            Gtk3::Image->new_from_file($axmud::SHARE_DIR . '/icons/map/icon_wait.png')
        );
        $radioButton_waitMode->set_label('Wait mode');
        $radioButton_waitMode->set_tooltip_text('Wait mode');
        $radioButton_waitMode->signal_connect('toggled' => sub {

            # (To stop the equivalent menu item from being toggled by the call to ->setMode, make
            #   use of $self->ignoreMenuUpdateFlag)
            if ($radioButton_waitMode->get_active && ! $self->ignoreMenuUpdateFlag) {

                $self->setMode('wait');
            }
        });
        push (@buttonList, $radioButton_waitMode);
        # (Never desensitised)
        $self->ivAdd('menuToolItemHash', 'icon_set_wait_mode', $radioButton_waitMode);

        # Radio button for 'follow mode'
        my $radioButton_followMode = Gtk3::RadioToolButton->new_from_widget($radioButton_waitMode);

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


            $radioButton_followMode->set_active(TRUE);
        }
        $radioButton_followMode->set_icon_widget(
            Gtk3::Image->new_from_file($axmud::SHARE_DIR . '/icons/map/icon_follow.png')
        );
        $radioButton_followMode->set_label('Follow mode');
        $radioButton_followMode->set_tooltip_text('Follow mode');
        $radioButton_followMode->signal_connect('toggled' => sub {

            if ($radioButton_followMode->get_active && ! $self->ignoreMenuUpdateFlag) {

                $self->setMode('follow');
            }
        });
        push (@buttonList, $radioButton_followMode);
        # (Requires $self->currentRegionmap)
        $self->ivAdd('menuToolItemHash', 'icon_set_follow_mode', $radioButton_followMode);

        # Radio button for 'update' mode
        my $radioButton_updateMode = Gtk3::RadioToolButton->new_from_widget(

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


            $radioButton_updateMode->set_active(TRUE);
        }
        $radioButton_updateMode->set_icon_widget(
            Gtk3::Image->new_from_file($axmud::SHARE_DIR . '/icons/map/icon_update.png')
        );
        $radioButton_updateMode->set_label('Update mode');
        $radioButton_updateMode->set_tooltip_text('Update mode');
        $radioButton_updateMode->signal_connect('toggled' => sub {

            if ($radioButton_updateMode->get_active && ! $self->ignoreMenuUpdateFlag) {

                $self->setMode('update');
            }
        });
        push (@buttonList, $radioButton_updateMode);
        # (Requires $self->currentRegionmap, GA::Obj::WorldModel->disableUpdateModeFlag set to
        #   FALSE and a session not in 'connect offline' mode
        $self->ivAdd('menuToolItemHash', 'icon_set_update_mode', $radioButton_updateMode);

        # Separator

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


        # Radio button for 'use region exit settings' mode
        my $radioButton_deferDrawExits = Gtk3::RadioToolButton->new(undef);
        $radioButton_deferDrawExits->set_icon_widget(
            Gtk3::Image->new_from_file($axmud::SHARE_DIR . '/icons/map/icon_use_region.png'),
        );
        $radioButton_deferDrawExits->set_label('Use region exit settings');
        $radioButton_deferDrawExits->set_tooltip_text('Use region exit settings');
        $radioButton_deferDrawExits->signal_connect('toggled' => sub {

            if (! $self->ignoreMenuUpdateFlag && $radioButton_deferDrawExits->get_active()) {

                $self->worldModelObj->switchMode(
                    'drawExitMode',
                    'ask_regionmap',    # New value of ->drawExitMode
                    TRUE,               # Do call $self->redrawRegions
                    'draw_defer_exits',
                    'icon_draw_defer_exits',
                );
            }
        });

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


            $radioButton_drawNoExits->set_active(TRUE);
        }
        $radioButton_drawNoExits->set_icon_widget(
            Gtk3::Image->new_from_file($axmud::SHARE_DIR . '/icons/map/icon_draw_none.png'),
        );
        $radioButton_drawNoExits->set_label('Draw no exits');
        $radioButton_drawNoExits->set_tooltip_text('Draw no exits');
        $radioButton_drawNoExits->signal_connect('toggled' => sub {

            if (! $self->ignoreMenuUpdateFlag && $radioButton_drawNoExits->get_active()) {

                $self->worldModelObj->switchMode(
                    'drawExitMode',
                    'no_exit',          # New value of ->drawExitMode
                    TRUE,               # Do call $self->redrawRegions
                    'draw_no_exits',
                    'icon_draw_no_exits',
                );
            }
        });

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


            $radioButton_drawSimpleExits->set_active(TRUE);
        }
        $radioButton_drawSimpleExits->set_icon_widget(
            Gtk3::Image->new_from_file($axmud::SHARE_DIR . '/icons/map/icon_draw_simple.png'),
        );
        $radioButton_drawSimpleExits->set_label('Draw simple exits');
        $radioButton_drawSimpleExits->set_tooltip_text('Draw simple exits');
        $radioButton_drawSimpleExits->signal_connect('toggled' => sub {

            if (! $self->ignoreMenuUpdateFlag && $radioButton_drawSimpleExits->get_active()) {

                $self->worldModelObj->switchMode(
                    'drawExitMode',
                    'simple_exit',      # New value of ->drawExitMode
                    TRUE,               # Do call $self->redrawRegions
                    'draw_simple_exits',
                    'icon_draw_simple_exits',
                );
            }
        });

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


            $radioButton_drawComplexExits->set_active(TRUE);
        }
        $radioButton_drawComplexExits->set_icon_widget(
            Gtk3::Image->new_from_file($axmud::SHARE_DIR . '/icons/map/icon_draw_complex.png'),
        );
        $radioButton_drawComplexExits->set_label('Draw complex exits');
        $radioButton_drawComplexExits->set_tooltip_text('Draw complex exits');
        $radioButton_drawComplexExits->signal_connect('toggled' => sub {

            if (! $self->ignoreMenuUpdateFlag && $radioButton_drawComplexExits->get_active()) {

                $self->worldModelObj->switchMode(
                    'drawExitMode',
                    'complex_exit',     # New value of ->drawExitMode
                    TRUE,               # Do call $self->redrawRegions
                    'draw_complex_exits',
                    'icon_draw_complex_exits',
                );
            }
        });

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        # Toggle button for 'obscure unimportant exits'
        my $toggleButton_obscuredExits = Gtk3::ToggleToolButton->new();
        $toggleButton_obscuredExits->set_active($self->worldModelObj->obscuredExitFlag);
        $toggleButton_obscuredExits->set_icon_widget(
            Gtk3::Image->new_from_file($axmud::SHARE_DIR . '/icons/map/icon_obscured_exits.png'),
        );
        $toggleButton_obscuredExits->set_label('Obscure unimportant exits');
        $toggleButton_obscuredExits->set_tooltip_text('Obscure unimportant exits');
        $toggleButton_obscuredExits->signal_connect('toggled' => sub {

            if (! $self->ignoreMenuUpdateFlag) {

                $self->worldModelObj->toggleFlag(
                    'obscuredExitFlag',
                    $toggleButton_obscuredExits->get_active(),
                    TRUE,      # Do call $self->redrawRegions
                    'obscured_exits',
                    'icon_obscured_exits',
                );
            }
        });

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        # Toggle button for 'auto-redraw obscured exits'
        my $toggleButton_autoRedraw = Gtk3::ToggleToolButton->new();
        $toggleButton_autoRedraw->set_active($self->worldModelObj->obscuredExitRedrawFlag);
        $toggleButton_autoRedraw->set_icon_widget(
            Gtk3::Image->new_from_file($axmud::SHARE_DIR . '/icons/map/icon_auto_redraw.png'),
        );
        $toggleButton_autoRedraw->set_label('Auto-redraw obscured exits');
        $toggleButton_autoRedraw->set_tooltip_text('Auto-redraw obscured exits');
        $toggleButton_autoRedraw->signal_connect('toggled' => sub {

            if (! $self->ignoreMenuUpdateFlag) {

                $self->worldModelObj->toggleFlag(
                    'obscuredExitRedrawFlag',
                    $toggleButton_autoRedraw->get_active(),
                    TRUE,      # Do call $self->redrawRegions
                    'auto_redraw_obscured',
                    'icon_auto_redraw_obscured',
                );
            }
        });

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        # Toggle button for 'draw exit ornaments'
        my $toggleButton_drawExitOrnaments = Gtk3::ToggleToolButton->new();
        $toggleButton_drawExitOrnaments->set_active($self->worldModelObj->drawOrnamentsFlag);
        $toggleButton_drawExitOrnaments->set_icon_widget(
            Gtk3::Image->new_from_file($axmud::SHARE_DIR . '/icons/map/icon_draw_ornaments.png'),
        );
        $toggleButton_drawExitOrnaments->set_label('Draw exit ornaments');
        $toggleButton_drawExitOrnaments->set_tooltip_text('Draw exit ornaments');
        $toggleButton_drawExitOrnaments->signal_connect('toggled' => sub {

            if (! $self->ignoreMenuUpdateFlag) {

                $self->worldModelObj->toggleFlag(
                    'drawOrnamentsFlag',
                    $toggleButton_drawExitOrnaments->get_active(),
                    TRUE,      # Do call $self->redrawRegions
                    'draw_ornaments',
                    'icon_draw_ornaments',
                );
            }
        });

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        # Toggle button for 'track current room'
        my $toggleButton_trackCurrentRoom = Gtk3::ToggleToolButton->new();
        $toggleButton_trackCurrentRoom->set_active($self->worldModelObj->trackPosnFlag);
        $toggleButton_trackCurrentRoom->set_icon_widget(
            Gtk3::Image->new_from_file($axmud::SHARE_DIR . '/icons/map/icon_track_room.png'),
        );
        $toggleButton_trackCurrentRoom->set_label('Track current room');
        $toggleButton_trackCurrentRoom->set_tooltip_text('Track current room');
        $toggleButton_trackCurrentRoom->signal_connect('toggled' => sub {

            if (! $self->ignoreMenuUpdateFlag) {

                $self->worldModelObj->toggleFlag(
                    'trackPosnFlag',
                    $toggleButton_trackCurrentRoom->get_active(),
                    FALSE,      # Don't call $self->redrawRegions
                    'track_current_room',
                    'icon_track_current_room',
                );
            }
        });

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

            #   though the IV was set to 0
            $radioButton_trackAlways->set_active(TRUE);
        }
        $radioButton_trackAlways->set_icon_widget(
            Gtk3::Image->new_from_file($axmud::SHARE_DIR . '/icons/map/icon_track_always.png'),
        );
        $radioButton_trackAlways->set_label('Always track position');
        $radioButton_trackAlways->set_tooltip_text('Always track position');
        $radioButton_trackAlways->signal_connect('toggled' => sub {

            if (! $self->ignoreMenuUpdateFlag && $radioButton_trackAlways->get_active()) {

                $self->worldModelObj->setTrackingSensitivity(0);
            }
        });
        push (@buttonList, $radioButton_trackAlways);
        # (Never desensitised)
        $self->ivAdd('menuToolItemHash', 'icon_track_always', $radioButton_trackAlways);

        # Radio button for 'track position near centre'
        my $radioButton_trackNearCentre = Gtk3::RadioToolButton->new_from_widget(

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


            $radioButton_trackNearCentre->set_active(TRUE);
        }
        $radioButton_trackNearCentre->set_icon_widget(
            Gtk3::Image->new_from_file($axmud::SHARE_DIR . '/icons/map/icon_track_centre.png'),
        );
        $radioButton_trackNearCentre->set_label('Track position near centre');
        $radioButton_trackNearCentre->set_tooltip_text('Track position near centre');
        $radioButton_trackNearCentre->signal_connect('toggled' => sub {

            if (! $self->ignoreMenuUpdateFlag && $radioButton_trackNearCentre->get_active()) {

                $self->worldModelObj->setTrackingSensitivity(0.33);
            }
        });
        push (@buttonList, $radioButton_trackNearCentre);
        # (Never desensitised)
        $self->ivAdd('menuToolItemHash', 'icon_track_near_centre', $radioButton_trackNearCentre);

        # Radio button for 'track near edge'
        my $radioButton_trackNearEdge = Gtk3::RadioToolButton->new_from_widget(

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


            $radioButton_trackNearEdge->set_active(TRUE);
        }
        $radioButton_trackNearEdge->set_icon_widget(
            Gtk3::Image->new_from_file($axmud::SHARE_DIR . '/icons/map/icon_track_edge.png'),
        );
        $radioButton_trackNearEdge->set_label('Track position near edge');
        $radioButton_trackNearEdge->set_tooltip_text('Track position near edge');
        $radioButton_trackNearEdge->signal_connect('toggled' => sub {

            if (! $self->ignoreMenuUpdateFlag && $radioButton_trackNearEdge->get_active()) {

                $self->worldModelObj->setTrackingSensitivity(0.66);
            }
        });
        push (@buttonList, $radioButton_trackNearEdge);
        # (Never desensitised)
        $self->ivAdd('menuToolItemHash', 'icon_track_near_edge', $radioButton_trackNearEdge);

        # Radio button for 'track if not visible'
        my $radioButton_trackNotVisible = Gtk3::RadioToolButton->new_from_widget(

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


            $radioButton_trackNotVisible->set_active(TRUE);
        }
        $radioButton_trackNotVisible->set_icon_widget(
            Gtk3::Image->new_from_file($axmud::SHARE_DIR . '/icons/map/icon_track_visible.png'),
        );
        $radioButton_trackNotVisible->set_label('Track if not visible');
        $radioButton_trackNotVisible->set_tooltip_text('Track position if not visible');
        $radioButton_trackNotVisible->signal_connect('toggled' => sub {

            if (! $self->ignoreMenuUpdateFlag && $radioButton_trackNotVisible->get_active()) {

                $self->worldModelObj->setTrackingSensitivity(1);
            }
        });
        push (@buttonList, $radioButton_trackNotVisible);
        # (Never desensitised)
        $self->ivAdd('menuToolItemHash', 'icon_track_not_visible', $radioButton_trackNotVisible);

        return @buttonList;
    }

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        # Toggle button for 'release all filters'
        my $radioButton_releaseAllFilters = Gtk3::ToggleToolButton->new();
        $radioButton_releaseAllFilters->set_active($self->worldModelObj->allRoomFiltersFlag);
        $radioButton_releaseAllFilters->set_icon_widget(
            Gtk3::Image->new_from_file($axmud::SHARE_DIR . '/icons/map/icon_all_filters.png'),
        );
        $radioButton_releaseAllFilters->set_label('Release all filters');
        $radioButton_releaseAllFilters->set_tooltip_text('Release all filters');
        $radioButton_releaseAllFilters->signal_connect('toggled' => sub {

            if (! $self->ignoreMenuUpdateFlag) {

                $self->worldModelObj->toggleFlag(
                    'allRoomFiltersFlag',
                    $radioButton_releaseAllFilters->get_active(),
                    TRUE,      # Do call $self->redrawRegions
                    'release_all_filters',
                    'icon_release_all_filters',
                );
            }
        });

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        # Filter icons
        foreach my $filter ($axmud::CLIENT->constRoomFilterList) {

            # Filter button
            my $toolButton_filter = Gtk3::ToggleToolButton->new();
            $toolButton_filter->set_active(
                $self->worldModelObj->ivShow('roomFilterApplyHash', $filter),
            );
            $toolButton_filter->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag) {

                    $self->worldModelObj->toggleFilter(
                        $filter,
                        $toolButton_filter->get_active(),
                    );
                }
            });

            # If it's one of the standard filters, we can use one of the existing icons;
            #   otherwise, use a spare icon

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

                $radioButton->set_active(TRUE);
            }
            $radioButton->set_icon_widget(
                Gtk3::Image->new_from_file($axmud::SHARE_DIR . '/icons/map/' . $iconHash{$mode}),
            );
            $radioButton->set_label($interiorHash{$mode});
            $radioButton->set_tooltip_text($interiorHash{$mode});

            $radioButton->signal_connect('toggled' => sub {

                if (! $self->ignoreMenuUpdateFlag && $radioButton->get_active()) {

                    $self->worldModelObj->switchRoomInteriorMode($mode);
                }
            });
            push (@buttonList, $radioButton);
            # (Never desensitised)
            $self->ivAdd('menuToolItemHash', 'icon_interior_mode_' . $mode, $radioButton);

            $lastButton = $radioButton;

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        }

        # Compile a hash of existing preferred room flags (we don't want the user to add the same
        #   room flag twice)
        foreach my $roomFlag ($self->worldModelObj->preferRoomFlagList) {

            $checkHash{$roomFlag} = undef;
        }

        # Set up the popup menu
        my $popupMenu = Gtk3::Menu->new();
        if (! $popupMenu) {

            return undef;
        }

        # Add a title menu item, which does nothing
        my $title_item = Gtk3::MenuItem->new('Add preferred room flag:');
        $title_item->signal_connect('activate' => sub {

            return undef;
        });
        $title_item->set_sensitive(FALSE);
        $popupMenu->append($title_item);

        $popupMenu->append(Gtk3::SeparatorMenuItem->new());     # Separator

        # Fill the popup menu with room flags
        foreach my $filter ($axmud::CLIENT->constRoomFilterList) {

            # A sub-sub menu for $filter
            my $subSubMenu_filter = Gtk3::Menu->new();

            my @nameList = $self->worldModelObj->getRoomFlagsInFilter($filter);
            foreach my $name (@nameList) {

                my $obj = $self->worldModelObj->ivShow('roomFlagHash', $name);
                if ($obj) {

                    my $menuItem = Gtk3::MenuItem->new($obj->descrip);
                    $menuItem->signal_connect('activate' => sub {

                        # Add the room flag to the world model's list of preferred room flags...
                        $self->worldModelObj->add_preferRoomFlag($name);
                        # ...then redraw the window component containing the toolbar(s), toggling
                        #   the button for the new room flag
                        $self->redrawWidgets('toolbar');
                    });
                    $subSubMenu_filter->append($menuItem);
                }
            }

            if (! @nameList) {

                my $menuItem = Gtk3::MenuItem->new('(No flags in this filter)');
                $menuItem->set_sensitive(FALSE);
                $subSubMenu_filter->append($menuItem);
            }

            my $menuItem = Gtk3::MenuItem->new(ucfirst($filter));
            $menuItem->set_submenu($subSubMenu_filter);
            $popupMenu->append($menuItem);
        }

        # Also add a 'Cancel' menu item, which does nothing
        $popupMenu->append(Gtk3::SeparatorMenuItem->new());     # Separator

        my $cancel_item = Gtk3::MenuItem->new('Cancel');
        $cancel_item->signal_connect('activate' => sub {

            return undef;
        });
        $popupMenu->append($cancel_item);

        # Display the popup menu
        $popupMenu->popup(
            undef, undef, undef, undef,
            1,                              # Left mouse button
            Gtk3::get_current_event_time(),
        );

        $popupMenu->show_all();

        # Operation complete. Now wait for the user's response
        return 1;
    }

    sub removeRoomFlagButton {

        # Called by a ->signal_connect in $self->drawPaintingButtonSet whenever the user clicks the
        #   'remove room flag' button in the 'painting' button set
        # Removes the specified room flag from the toolbar and updates IVs

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


        my ($self, $check) = @_;

        # Check for improper arguments
        if (defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->removeRoomFlagButton', @_);
        }

        # Set up the popup menu
        my $popupMenu = Gtk3::Menu->new();
        if (! $popupMenu) {

            return undef;
        }

        # Add a title menu item, which does nothing
        my $title_item = Gtk3::MenuItem->new('Remove preferred room flag:');
        $title_item->signal_connect('activate' => sub {

            return undef;
        });
        $title_item->set_sensitive(FALSE);
        $popupMenu->append($title_item);

        $popupMenu->append(Gtk3::SeparatorMenuItem->new());     # Separator

        # Fill the popup menu with room flags
        foreach my $roomFlag ($self->worldModelObj->preferRoomFlagList) {

            my $menu_item = Gtk3::MenuItem->new($roomFlag);
            $menu_item->signal_connect('activate' => sub {

                # Remove the room flag from the world model's list of preferred room flags...
                $self->worldModelObj->del_preferRoomFlag($roomFlag);
                # ...and from the painter object iself...
                $self->worldModelObj->painterObj->ivDelete('roomFlagHash', $roomFlag);
                # ...then redraw the window component containing the toolbar(s)
                $self->redrawWidgets('toolbar');
            });
            $popupMenu->append($menu_item);
        }

        # Add a 'remove all' menu item
        $popupMenu->append(Gtk3::SeparatorMenuItem->new());     # Separator

        my $remove_all_item = Gtk3::MenuItem->new('Remove all');
        $remove_all_item->signal_connect('activate' => sub {

            my ($total, $choice);

            $total = scalar $self->worldModelObj->preferRoomFlagList;

            # If there's more than one colour, prompt the user for confirmation
            if ($total > 1) {

                $choice = $self->showMsgDialogue(

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

                #   tools)
                foreach my $roomFlag ($self->worldModelObj->preferRoomFlagList) {

                    $self->worldModelObj->ivDelete('roomFlagHash', $roomFlag);
                }

                # Then redraw the window component containing the toolbar(s)
                $self->redrawWidgets('toolbar');
            }
        });
        $popupMenu->append($remove_all_item);

        # Also add a 'Cancel' menu item, which does nothing
        my $cancel_item = Gtk3::MenuItem->new('Cancel');
        $cancel_item->signal_connect('activate' => sub {

            return undef;
        });
        $popupMenu->append($cancel_item);

        # Display the popup menu
        $popupMenu->popup(
            undef, undef, undef, undef,
            1,                              # Left mouse button
            Gtk3::get_current_event_time(),
        );

        $popupMenu->show_all();

        # Operation complete. Now wait for the user's response
        return 1;
    }

    sub addBGColourButton {

        # Called by a ->signal_connect in $self->drawBackgroundButtonSet whenever the user clicks
        #   the 'add background colour' button in the 'background' button set
        # Prompts the user for a new RGB colour tag, then implements the user's choice

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


        my ($self, $check) = @_;

        # Check for improper arguments
        if (defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->removeBGColourButton', @_);
        }

        # Set up the popup menu
        my $popupMenu = Gtk3::Menu->new();
        if (! $popupMenu) {

            return undef;
        }

        # Add a title menu item, which does nothing
        my $title_item = Gtk3::MenuItem->new('Remove preferred background colour:');
        $title_item->signal_connect('activate' => sub {

            return undef;
        });
        $title_item->set_sensitive(FALSE);
        $popupMenu->append($title_item);

        $popupMenu->append(Gtk3::SeparatorMenuItem->new());     # Separator

        # Fill the popup menu with colours
        foreach my $colour ($self->worldModelObj->preferBGColourList) {

            my $menu_item = Gtk3::MenuItem->new($colour);
            $menu_item->signal_connect('activate' => sub {

                # Remove the colour from the world model's list of preferred background colours...
                $self->worldModelObj->del_preferBGColour($colour);
                # ...then redraw the window component containing the toolbar(s)
                $self->redrawWidgets('toolbar');
            });
            $popupMenu->append($menu_item);
        }

        # Add a 'remove all' menu item
        $popupMenu->append(Gtk3::SeparatorMenuItem->new());     # Separator

        my $remove_all_item = Gtk3::MenuItem->new('Remove all');
        $remove_all_item->signal_connect('activate' => sub {

            my ($total, $choice);

            $total = scalar $self->worldModelObj->preferBGColourList;

            # If there's more than one colour, prompt the user for confirmation
            if ($total > 1) {

                $choice = $self->showMsgDialogue(

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

            }

            if (defined $choice && $choice eq 'yes') {

                # Reset the world model's list of preferred background colour...
                $self->worldModelObj->reset_preferBGColourList();
                # ...then redraw the window component containing the toolbar(s)
                $self->redrawWidgets('toolbar');
            }
        });
        $popupMenu->append($remove_all_item);

        # Also add a 'Cancel' menu item, which does nothing
        my $cancel_item = Gtk3::MenuItem->new('Cancel');
        $cancel_item->signal_connect('activate' => sub {

            return undef;
        });
        $popupMenu->append($cancel_item);

        # Display the popup menu
        $popupMenu->popup(
            undef, undef, undef, undef,
            1,                              # Left mouse button
            Gtk3::get_current_event_time(),
        );

        $popupMenu->show_all();

        # Operation complete. Now wait for the user's response
        return 1;
    }

    # Treeview widget methods

    sub enableTreeView {

        # Called by $self->drawWidgets

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


            $canvasWidget->set_scale($self->currentRegionmap->magnification);
        }

        # Sensitise/desensitise menu bar/toolbar items, depending on current conditions
        $self->restrictWidgets();

        return 1;
    }

    # Menu bar/toolbar widget sensitisers

    sub restrictWidgets {

        # Many menu bar and toolbar items can be sensitised, or desensitised, depending on
        #   conditions
        # This function can be called by anything, any time one of those conditions changes, so that
        #   every menu bar/toolbar item can be sensitised or desensitised correctly
        #
        # Expected arguments
        #   (none besides $self)

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        if (defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->restrictWidgets', @_);
        }

        # Modified v1.0.150 - anything that requires the current regionmap, also requires
        #   the character to be logged in (with a handful of exceptions)
        # Modified v1.0.363 - we now allow zooming and a few other things from the 'View' menu
        #   when the character isn't logged in

        # Menu items that require a current regionmap AND a logged in character
        @list = (
            'select', 'unselect_all',
            'selected_objs',
            'set_follow_mode', 'icon_set_follow_mode',
            'screenshots', 'icon_visible_screenshot',
            'drag_mode', 'icon_drag_mode',
            'graffiti_mode', 'icon_graffiti_mode',
            'edit_region',
            'edit_regionmap',
            'current_region',

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

            'report_checked_2',
            'reset_locator', 'icon_reset_locator',
        );

        if ($self->currentRegionmap && $self->session->loginFlag) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap BUT NOT a logged in character
        @list = (
            'zoom_sub',
            'level_sub',
            'centre_map_middle_grid', 'icon_centre_map_middle_grid',
            'centre_map_sub',
            'move_up_level', 'icon_move_up_level',
            'move_down_level', 'icon_move_down_level',
            'this_region_scheme',
            'exit_lengths', 'icon_horizontal_lengths', 'icon_vertical_lengths',
        );

        if ($self->currentRegionmap) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap, GA::Obj::WorldModel->disableUpdateModeFlag
        #   set to FALSE and a session not in 'connect offline' mode
        @list = (
            'set_update_mode', 'icon_set_update_mode',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && ! $self->worldModelObj->disableUpdateModeFlag
            && $self->session->status ne 'offline'
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap for a region that doesn't have a parent region
        @list = (
            'move_region_top',
        );

        if ($self->currentRegionmap) {

            $regionObj
                = $self->worldModelObj->ivShow('regionModelHash', $self->currentRegionmap->number);
        }

        if ($regionObj && ! $regionObj->parent) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and a current room
        @list = (
            'centre_map_current_room', 'icon_centre_map_current_room',
            'add_room_contents',
            'add_hidden_object',
            'add_search_result',
            'unset_current_room',
            'update_locator',
            'repaint_current',
            'execute_scripts',
            'add_failed_room',

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

            'add_unspecified_pattern',
            'icon_fail_exit',
        );

        if ($self->currentRegionmap && $self->session->loginFlag && $self->mapObj->currentRoom) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and a single selected room
        @list = (
            'centre_map_selected_room', 'icon_centre_map_selected_room',
            'set_current_room', 'icon_set_current_room',
            'select_exit',
            'increase_set_current',
            'edit_room',
            'set_file_path',
            'add_contents_string',
            'add_hidden_string',
            'add_exclusive_prof',
            'icon_inc_visits_current',
        );

        if ($self->currentRegionmap && $self->session->loginFlag && $self->selectedRoom) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and either a single selected room or a single
        #   selected room tag
        @list = (
            'set_room_tag',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && ($self->selectedRoom || $self->selectedRoomTag)
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap, a current room and a single selected room
        #   (the current room and selected room shouldn't be the same)
        @list = (
            'path_finding_highlight',
            'path_finding_edit',
            'path_finding_go',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && $self->mapObj->currentRoom
            && $self->selectedRoom
            && $self->mapObj->currentRoom ne $self->selectedRoom
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and either a current room or a single selected
        #   room
        @list = (
            'add_to_model',
        );
        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && ($self->mapObj->currentRoom || $self->selectedRoom)
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and a single selected room with one or more
        #   checked directions
        @list = (
            'remove_checked', 'remove_checked_all',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && $self->selectedRoom
            && $self->selectedRoom->checkedDirHash
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and a single selected room with
        #   ->sourceCodePath set, but ->virtualAreaPath not set
        @list = (
            'view_source_code',
            'edit_source_code',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && $self->selectedRoom
            && $self->selectedRoom->sourceCodePath
            && ! $self->selectedRoom->virtualAreaPath
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and a single selected room with
        #   ->virtualAreaPath set
        @list = (
            'view_virtual_area',
            'edit_virtual_area',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && $self->selectedRoom
            && $self->selectedRoom->virtualAreaPath
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and a single selected room whose ->wildMode
        #   is not set to 'wild' (the value 'border' is ok, though)
        @list = (
            'add_normal_exit', 'add_hidden_exit',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && $self->selectedRoom
            && $self->selectedRoom->wildMode ne 'wild'
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap, one or more selected rooms and
        #   $self->graffitiModeFlag set to TRUE
        @list = (
            'toggle_graffiti', 'icon_toggle_graffiti',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && ($self->selectedRoom || $self->selectedRoomHash)
            && $self->graffitiModeFlag
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and one or more selected rooms
        @list = (
            'move_rooms_dir', 'move_rooms_click',
            'icon_move_to_click',
            'toggle_room_flag_sub',
            'reset_positions',
            'room_exclusivity', 'room_exclusivity_sub',
            'set_exits',
            'add_multiple_exits',
            'wilderness_normal',
            'update_visits',

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && ($self->selectedRoom || $self->selectedRoomHash)
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and either one or more selected rooms or one
        #   or more selected room guilds (or a mixture of both)
        @list = (
            'set_room_guild',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && (
                $self->selectedRoom || $self->selectedRoomHash || $self->selectedRoomGuild
                || $self->selectedRoomGuildHash
            )
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and EITHER one or more selected rooms OR a
        #   current room
        @list = (
            'identify_room',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && ($self->selectedRoom || $self->selectedRoomHash || $self->mapObj->currentRoom)
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap, one or more selected rooms and at least two
        #   regions in the world model
        @list = (
            'transfer_to_region',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && ($self->selectedRoom || $self->selectedRoomHash)
            && $self->worldModelObj->ivPairs('regionmapHash') > 1
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap, a current room and the automapper object
        #   being set up to perform a merge operation
        @list = (
            'move_merge_rooms',
        );

        if (
            $self->currentRegionmap
            && $self->mapObj->currentRoom
            && $self->mapObj->currentMatchFlag
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and EITHER one or more selected rooms OR a
        #   current room and the automapper being set up to perform a merge)
        @list = (
            'move_rooms_labels',
        );

        if (
            $self->currentRegionmap
            && (
                $self->selectedRoom
                || $self->selectedRoomHash
                || ($self->mapObj->currentRoom && $self->mapObj->currentMatchFlag)
            )
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and an empty
        #   $self->currentRegionmap->gridRoomHash
        @list = (
            'add_first_room',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && ! $self->currentRegionmap->gridRoomHash
        ) {

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && $self->currentRegionmap->gridRoomHash
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and a single selected exit
        @list = (
            'set_exit_dir',
            'edit_exit',
            'disconnect_exit',
            'delete_exit',
            'set_exit_type',
        );

        if ($self->currentRegionmap && $self->session->loginFlag && $self->selectedExit) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and one or more selected exits
        @list = (
            'set_ornament_sub',
            'icon_no_ornament', 'icon_openable_exit', 'icon_lockable_exit',
            'icon_pickable_exit', 'icon_breakable_exit', 'icon_impassable_exit',
            'icon_mystery_exit',
            'identify_exit',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && ($self->selectedExit || $self->selectedExitHash)
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap, a single selected exit and
        #   $self->selectedExit->drawMode is 'temp_alloc' or 'temp_unalloc'
        @list = (
            'allocate_map_dir',
            'allocate_shadow',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && $self->selectedExit
            && (
                $self->selectedExit->drawMode eq 'temp_alloc'
                || $self->selectedExit->drawMode eq 'temp_unalloc'
            )
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap, a single selected exit and
        #   $self->selectedExit->drawMode is 'primary' or 'perm_alloc'
        @list = (
            'change_direction',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && $self->selectedExit
            && (
                $self->selectedExit->drawMode eq 'primary'
                || $self->selectedExit->drawMode eq 'perm_alloc'
            )
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap, a single selected exit and
        #   $self->selectedExit->drawMode is 'primary', 'temp_unalloc' or 'perm_alloc'
        @list = (
            'connect_to_click',
            'set_assisted_move',
            'icon_connect_click',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && $self->selectedExit
            && $self->selectedExit->drawMode ne 'temp_alloc'
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and a single selected exit which is a broken
        #   exit
        @list = (
            'toggle_bent_exit',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && $self->selectedExit
            && $self->selectedExit->brokenFlag
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and a single selected exit which is a region
        #   exit
        @list = (
            'set_super_sub',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && $self->selectedExit
            && $self->selectedExit->regionFlag
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and either a single selected exit which is a
        #   region exit, or a single selected exit tag
        @list = (
            'toggle_exit_tag',
            'edit_tag_text',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && (
                ($self->selectedExit && $self->selectedExit->regionFlag)
                || $self->selectedExitTag
            )
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and one or more selected exits or selected
        #   exit tags
        @list = (
            'reset_exit_tags',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && (
                $self->selectedExit || $self->selectedExitHash
                || $self->selectedExitTag || $self->selectedExitTagHash
            )
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and a single selected exit which is a
        #   super-region exit
        @list = (
            'recalculate_from_exit',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && $self->selectedExit
            && $self->selectedExit->superFlag
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and a single selected exit which is an
        #   uncertain exit or a one-way exit
        @list = (
            'set_exit_twin',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && $self->selectedExit
            && (

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

                    && ! $self->selectedExit->retraceFlag
                    && $self->selectedExit->randomType eq 'none'
                )
            )
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and a single selected exit which is a one-way
        #   exit
        @list = (
            'set_incoming_dir',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && $self->selectedExit
            && $self->selectedExit->oneWayFlag
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and a single selected label
        @list = (
            'set_label',
            'customise_label',
        );

        if ($self->currentRegionmap && $self->session->loginFlag && $self->selectedLabel) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and one or more selected labels
        @list = (
            'delete_label',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && ($self->selectedLabel || $self->selectedLabelHash)
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a selected region (in the treeview)
        @list = (
            'identify_region',
        );

        if ($self->treeViewSelectedLine) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap, and $self->currentRegionmap->magnification
        #   to be within a certain range of values
        @magList = $self->constMagnifyList;

        @list = (
            'zoom_out',
        );

        # (Don't try to zoom out, if already zoomed out to the maximum extent)
        if (
            $self->currentRegionmap

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        # (Don't try to zoom in, if already zoomed in to the maximum extent)
        if (
            $self->currentRegionmap
            && $self->currentRegionmap->magnification < $magList[-1]
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and $self->worldModelObj->drawExitMode is
        #   'ask_regionmap'
        @list = (
            'draw_region_exits',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && $self->worldModelObj->drawExitMode eq 'ask_regionmap'
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current character profile
        @list = (
            'report_visits_3',
        );

        if ($self->session->currentChar) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and a current character profile
        @list = (
            'report_visits_4',
        );

        if ($self->currentRegionmap && $self->session->loginFlag && $self->session->currentChar) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current guild profile
        @list = (
            'report_guilds_3',
        );

        if ($self->session->currentGuild) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap whose ->gridColourBlockHash and/or
        #   ->gridColourObjHash is not empty)
        @list = (
            'empty_bg_colours',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && (
                $self->currentRegionmap->gridColourBlockHash
                || $self->currentRegionmap->gridColourObjHash
            )
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and a current guild profile
        @list = (
            'report_guilds_4',
        );

        if ($self->currentRegionmap && $self->session->loginFlag && $self->session->currentGuild) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require assisted moves to be turned on
        @list = (
            'allow_protected_moves',
            'allow_super_protected_moves',
        );

        if ($self->worldModelObj->assistedMovesFlag) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require protected moves to be turned off
        @list = (
            'allow_crafty_moves',
        );

        if (! $self->worldModelObj->protectedMovesFlag) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require basic mapping mode to be turned off
        @list = (
            'paint_wild', 'icon_paint_wild',
            'paint_border', 'icon_paint_border',
        );

        if (! $self->session->currentWorld->basicMappingFlag) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap, one or more selected rooms and basic mapping
        #   mode to be turned off
        @list = (
            'wilderness_wild', 'wilderness_border',
        );

        if (
            $self->currentRegionmap
            && $self->session->loginFlag
            && ($self->selectedRoom || $self->selectedRoomHash)
            && ! $self->session->currentWorld->basicMappingFlag
        ) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a non-empty list of preferred room flags
        @list = (
            'icon_remove_room_flag', 'icon_remove_room_flag_2',
        );

        if ($self->worldModelObj->preferRoomFlagList) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a non-empty list of preferred background colours
        @list = (
            'icon_bg_remove',
        );

        if ($self->worldModelObj->preferBGColourList) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap and at least one non-default colour scheme
        @list = (
            'attach_region_scheme',
        );

        if ($self->currentRegionmap && $self->worldModelObj->ivPairs('regionSchemeHash') > 1) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require a current regionmap with a non-default region scheme attached
        @list = (
            'detach_region_scheme',
        );

        if ($self->currentRegionmap && defined $self->currentRegionmap->regionScheme) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

        # Menu items that require at least one map label style
        @list = (
            'edit_style',
        );

        if ($self->worldModelObj->mapLabelStyleHash) {
            push (@sensitiseList, @list);
        } else {
            push (@desensitiseList, @list);
        }

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments
        #   1 otherwise

        my ($self, $check) = @_;

        # Local variables
        my ($radioMenuItem, $toolbarButton);

        # Check for improper arguments
        if (defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->restrictUpdateMode', @_);
        }

        # Mark the radio/toolbar buttons for 'update mode' as sensitive, or not
        $radioMenuItem = $self->ivShow('menuToolItemHash', 'set_update_mode');
        $toolbarButton = $self->ivShow('menuToolItemHash', 'icon_set_update_mode');

        if ($self->worldModelObj->disableUpdateModeFlag || $self->session->status eq 'offline') {

            if ($radioMenuItem) {

                $radioMenuItem->set_sensitive(FALSE);
            }

            if ($toolbarButton) {

                $toolbarButton->set_sensitive(FALSE);
            }

        } else {

            if ($radioMenuItem) {

                $radioMenuItem->set_sensitive(TRUE);
            }

            if ($toolbarButton) {

                $toolbarButton->set_sensitive(TRUE);
            }
        }

        return 1;
    }

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        #   'undef' on improper arguments, if there is no region map or if the signal $event is one
        #       that this function doesn't handle
        #   1 otherwise

        my ($self, $canvasObj, $event, $check) = @_;

        # Local variables
        my (
            $clickXPosPixels, $clickYPosPixels, $clickType, $button, $shiftFlag, $ctrlFlag,
            $clickXPosBlocks, $clickYPosBlocks, $newRoomObj, $roomNum, $roomObj, $exitObj, $listRef,
            $result, $twinExitObj, $result2, $popupMenu,
        );

        # Check for improper arguments
        if (! defined $canvasObj || ! defined $event || defined $check) {

            return $axmud::CLIENT->writeImproper($self->_objClass . '->canvasEventHandler', @_);
        }

        # Don't do anything if there is no current regionmap
        if (! $self->currentRegionmap) {

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        );

        # If $self->freeClickMode and/or $self->bgColourMode aren't set to 'default', left-clicking
        #   on empty space causes something unusual to happen
        if (
            $clickType eq 'single'
            && $button eq 'left'
            && ($self->freeClickMode ne 'default' || $self->bgColourMode ne 'default')
        ) {
            # Free click mode 'add_room' - 'Add room at click' menu option
            # (NB If this code is altered, the equivalent code in ->enableCanvasPopupMenu must also
            #   be altered)
            if ($self->freeClickMode eq 'add_room') {

                # Only add one new room
                $self->reset_freeClickMode();

                $newRoomObj = $self->mapObj->createNewRoom(
                    $self->currentRegionmap,
                    $clickXPosBlocks,
                    $clickYPosBlocks,

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


                    # Select the exit, unselecting all other selected objects
                   $self->setSelectedObj(
                        [$exitObj, 'exit'],
                        FALSE,          # Select this object; unselect all other objects
                    );

                    # Create the popup menu
                    if ($self->selectedExit) {

                        $popupMenu = $self->enableExitsPopupMenu();
                        if ($popupMenu) {

                            $popupMenu->popup(
                                undef, undef, undef, undef,
                                $event->button,
                                $event->time,
                            );
                        }
                    }
                }

                return 1;
            }
        }

        # Otherwise, the user clicked in open space

        # If it was a right-click, open a popup menu
        if ($clickType eq 'single' && $button eq 'right') {

            $popupMenu = $self->enableCanvasPopupMenu(
                $clickXPosPixels,
                $clickYPosPixels,
                $clickXPosBlocks,
                $clickYPosBlocks,
            );

            if ($popupMenu) {

                $popupMenu->popup(
                    undef, undef, undef, undef,
                    $event->button,
                    $event->time,
                );
            }

        # If it was a left-click, it's potentially a selection box operation
        } elsif ($clickType eq 'single' && $button eq 'left') {

            # The selection box isn't actually drawn until the user moves their mouse. If they

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        # Return values
        #   'undef' on improper arguments or if the signal $event is one that this function doesn't
        #       handle
        #   1 otherwise

        my ($self, $objType, $canvasObj, $modelObj, $event, $check) = @_;

        # Local variables
        my (
            $clickType, $button, $shiftFlag, $ctrlFlag, $selectFlag, $clickTime, $otherRoomObj,
            $startX, $stopX, $startY, $stopY, $result, $twinExitObj, $result2, $popupMenu,
        );

        # Check for improper arguments
        if (
            ! defined $objType || ! defined $canvasObj || ! defined $modelObj || ! defined $event
            || defined $check
        ) {
            return $axmud::CLIENT->writeImproper($self->_objClass . '->canvasObjEventHandler', @_);
        }

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


                    $self->setSelectedObj(
                        [$modelObj, $objType],
                        FALSE,          # Select this object; unselect all other objects
                    );
                }
            }

            # Create the popup menu
            if ($objType eq 'room' && $self->selectedRoom) {
                $popupMenu = $self->enableRoomsPopupMenu();
            } elsif ($objType eq 'room_tag' && $self->selectedRoomTag) {
                $popupMenu = $self->enableRoomTagsPopupMenu();
            } elsif ($objType eq 'room_guild' && $self->selectedRoomGuild) {
                $popupMenu = $self->enableRoomGuildsPopupMenu();
            } elsif ($objType eq 'exit_tag' && $self->selectedExitTag) {
                $popupMenu = $self->enableExitTagsPopupMenu();
            } elsif ($objType eq 'exit' && $self->selectedExit) {

                # Store the position of the right-click, in case the user wants to add a bend from
                #   the popup menu
                $self->ivPoke('exitClickXPosn', int($event->x));
                $self->ivPoke('exitClickYPosn', int($event->y));
                # Now we can open the poup menu
                $popupMenu = $self->enableExitsPopupMenu();

            } elsif ($objType eq 'label' && $self->selectedLabel) {

                $popupMenu = $self->enableLabelsPopupMenu();
            }

            if ($popupMenu) {

                $popupMenu->popup(undef, undef, undef, undef, $event->button, $event->time);
            }
        }

        return 1;
    }

    sub deleteCanvasObj {

        # Called by numerous functions
        #

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        }

        return 1;
    }

    sub doMerge {

        # Called by $self->canvasEventHandler when a double-click is detected on the current room
        #   and the automapper object is set up to perform a merge (i.e.
        #   GA::Map::Obj->currentMatchFlag is TRUE)
        # Also called by $self->enableRoomsColumnm ->enableRoomsPopupMenu and
        #   ->canvasObjEventHandler
        #
        # Prepares a call to GA::Obj::WorldModel->mergeMap, then makes the call
        #
        # Expected arguments
        #   $currentRoomObj - The room that is definitely to be merged with another room (at the
        #                       moment, it's always the automapper object's current room)
        #
        # Optional arguments
        #   $targetRoomObj  - When called by $self->canvasObjEventHandler, because

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


        } else {

            # Failsafe: empty string
            $label = "";
        }

        return $label;
    }

    # Menu 'File' column callbacks

    sub importModelCallback {

        # Called by $self->enableFileColumn
        # Imports a world model file specified by the user and (if successful) loads it into memory
        #   (a combination of ';importfiles' and ';load -m')
        #
        # Expected arguments
        #   (none besides $self)
        #

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


        # Export the world model data file
        $self->session->pseudoCmd(
            'exportfiles -m ' . $self->session->currentWorld->name,
            'win_error',
        );

        return 1;
    }

    # Menu 'Edit' column callbacks

    sub selectInRegionCallback {

        # Called by $self->enableEditColumn
        # Selects rooms, exits, room tags, room guilds or labels (or everything) in the current
        #   region
        #
        # Expected arguments
        #   (none besides $self)
        #

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


        # Show confirmation
        return $self->showMsgDialogue(
            'Reset character visits',
            'info',
            'Operation complete (rooms: ' . $roomCount . ', records deleted: ' . $deleteCount . ')',
            'ok',
        );
    }

    # Menu 'View' column callbacks

    sub changeCharDrawnCallback {

        # Called by $self->enableViewColumn
        # In GA::Obj::WorldModel->roomInteriorMode 'visit_count', changes which character's visits
        #   are drawn
        #
        # Expected arguments
        #   (none besides $self)
        #

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

                );
            }

            # Set the new current level, which redraws the map
            $self->setCurrentLevel($level);
        }

        return 1;
    }

    # Menu 'Mode' column callbacks

    sub verboseCharsCallback {

        # Called by $self->enableModeColumn
        # Sets the number of characters at the beginning of a verbose description that are checked
        #   to match a world model room with the Locator's current room
        #
        # Expected arguments
        #   (none besides $self)
        #

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        );

        if ($axmud::CLIENT->intCheck($number, 1)) {

            $self->worldModelObj->set_autoSlideMax($number);
        }

        return 1;
    }

    # Menu 'Regions' column callbacks

    sub newRegionCallback {

        # Called by $self->enableRegionsColumn
        # Adds a new region to the world model
        #
        # Expected arguments
        #   $tempFlag   - If set to TRUE, the new region is a temporary region (that should be
        #                   deleted, the next time the world model is loaded from file)
        #

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

            $self->session,
            TRUE,              # Update Automapper windows now
        );

        # Make the pause window invisible
        $self->hidePauseWin();

        return 1;
    }

    # Menu 'Rooms' column callbacks

    sub resetLocatorCallback {

        # Called by $self->enableRoomsColumn
        # Resets the Locator task, and marks the automapper as lost
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

            # $dir is a custom primary direction; convert it into the standard primary direction
            $standardDir = $dictObj->ivShow('combRevDirHash', $choice);

            # Move the selected room(s)
            return $self->moveRoomsInDir($distance, $standardDir);
        }
    }

    sub transferSelectedRoomsCallback {

        # Called by $self->enableEditColumn and ->enableRoomsPopupMenu
        # Transfers the selected rooms (and any selected labels, if there is at least one selected
        #   room) to the same location in a specified region
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Optional arguments
        #   $regionName     - The name of the region into which the rooms/labels should be
        #                       transferred. All selected rooms/labels must be in the same region,
        #                       and that region must not be the same as $regionName. If 'undef', the

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

                return undef;
            }
        }

        # Move the selected rooms/labels
        return $self->transferRoomsToRegion($regionName);
    }

    sub compareRoomCallback {

        # Called by $self->->enableRoomsPopupMenu
        # Compares the selected room with rooms in the region or the whole world model, and selects
        #   any matching rooms
        #
        # Expected arguments
        #   $wholeFlag  - FALSE to compare rooms in the same region, TRUE to compare rooms in the
        #                   whole world model
        #
        # Return values
        #   'undef' on improper arguments, if the standard callback check fails or if the move
        #       operation fails

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

                'Compare room',
                'info',
                'Found ' . $string . ' matching room #' . $selectObj->number,
                'ok',
            );
        }
    }

    sub executeScriptsCallback {

        # Called by $self->enableRoomsPopupMenu
        # Executes Axbasic scripts for the current room, as if the character had just arrived
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments or if the standard callback check fails
        #   1 otherwise

        my ($self, $check) = @_;

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        # This is a convenient way to deal with it. Adds a new failed exit string to the current
        #   world profile or to the specified room, and empties the Locator's move list
        #
        # Expected arguments
        #   $worldFlag   - If set to TRUE, a failed exit pattern is added to the world profile. If
        #                   set to FALSE, the pattern is added to the room
        #
        # Optional arguments
        #   $roomObj    - If $worldFlag is FALSE, the room to which the pattern should be added.
        #                   When called by $self->enableRoomsColumn, it will be the current room;
        #                   when called by ->enableRoomsPopupMenu, it will be the selected room
        #
        # Return values
        #   'undef' on improper arguments, if the standard callback check fails or if the user
        #       doesn't supply a pattern
        #   1 otherwise

        my ($self, $worldFlag, $roomObj, $check) = @_;

        # Local variables
        my (

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


    sub addInvoluntaryExitCallback {

        # Called by $self->enableRoomsColumn
        # This callback adds an involuntary exit pattern to the specified room and empties the
        #   Locator task's move list
        #
        # Expected arguments
        #   $roomObj    - The room to which the pattern should be added. When called by
        #                   $self->enableRoomsColumn, it will be the current room; when called by
        #                   ->enableRoomsPopupMenu, it will be the selected room
        #
        # Return values
        #   'undef' on improper arguments, if the standard callback check fails or if the user
        #       doesn't supply a pattern
        #   1 otherwise

        my ($self, $roomObj, $check) = @_;

        # Local variables
        my ($pattern, $otherVal, $taskObj);

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN


    sub addRepulseExitCallback {

        # Called by $self->enableRoomsColumn
        # This callback adds a repulse exit pattern to the specified room and empties the Locator
        #   task's move list
        #
        # Expected arguments
        #   $roomObj    - The room to which the pattern should be added. When called by
        #                   $self->enableRoomsColumn, it will be the current room; when called by
        #                   ->enableRoomsPopupMenu, it will be the selected room
        #
        # Return values
        #   'undef' on improper arguments, if the standard callback check fails or if the user
        #       doesn't supply a pattern
        #   1 otherwise

        my ($self, $roomObj, $check) = @_;

        # Local variables
        my ($pattern, $otherVal, $taskObj);

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        # When the character moves using an exit which doesn't send a room statement upon arrival
        #   in the new room - usually after some kind of faller - the pattern sent by the world to
        #   confirm arrival (such as 'You land in a big heap!') should be interpreted by the
        #   Locator task as a special kind of room statement
        # This callback adds a special departure pattern to the specified room and empties the
        #   Locator task's move list
        #
        # Expected arguments
        #   $roomObj    - The room to which the pattern should be added. When called by
        #                   $self->enableRoomsColumn, it will be the current room; when called by
        #                   ->enableRoomsPopupMenu, it will be the selected room
        #
        # Return values
        #   'undef' on improper arguments, if the standard callback check fails or if the user
        #       doesn't supply a pattern
        #   1 otherwise

        my ($self, $roomObj, $check) = @_;

        # Local variables
        my ($pattern, $taskObj);

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        # Called by $self->enableRoomsColumn
        # GA::Profile::World->unspecifiedRoomPatternList provides a list of patterns that match
        #   a line in 'unspecified' rooms (those that don't use a recognisable room statement;
        #   typically a room whose exit list is completely obscured)
        # Each room has its own list of patterns that match a line in 'unspecified' rooms; this
        #   callback adds a pattern to that list
        #
        # Expected arguments
        #   $roomObj    - The room to which the pattern should be added. When called by
        #                   $self->enableRoomsColumn, it will be the current room; when called by
        #                   ->enableRoomsPopupMenu, it will be the selected room
        #
        # Return values
        #   'undef' on improper arguments, if the standard callback check fails or if the user
        #       doesn't supply a pattern
        #   1 otherwise

        my ($self, $roomObj, $check) = @_;

        # Local variables
        my ($pattern, $taskObj);

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

                # Empty the Locator's move list IVs and update its task window
                $taskObj->resetMoveList();
            }
        }

        return 1;
    }

    sub removeCheckedDirCallback {

        # Called by $self->enableRoomsColumn and ->enableRoomsPopupMenu
        # Removes one or all checked directions from the selected room
        #
        # Expected arguments
        #   $allFlag    - If set to TRUE, all checked directions are removed. If set to FALSE, the
        #                   user is prompted to choose an exit
        #
        # Return values
        #   'undef' on improper arguments, if the standard callback check fails or if the user
        #       clicks 'cancel' on the 'dialogue' window
        #   1 otherwise

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        }

        # Redraw the selected room in every window
        $self->worldModelObj->updateMaps('room', $self->selectedRoom);

        return 1;
    }

    sub setWildCallback {

        # Called by $self->enableRoomsColumn and ->enableRoomsPopupMenu
        # Sets the selected room(s)' wilderness mode
        #
        # Expected arguments
        #   $mode   - One of the values for GA::ModelObj::Room->wildMode - 'normal', 'border' or
        #               'wild'
        #
        # Return values
        #   'undef' on improper arguments or if the standard callback check fails
        #   1 otherwise

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

            'ok',
            undef,
            TRUE,           # Preserve newline characters in $msg
        );

        return 1;
    }

    sub updateVisitsCallback {

        # Called by $self->enableRoomsColumn, ->enableRoomsPopupMenu and ->drawMiscButtonSet
        # Adjusts the number of character visits shown in the selected room(s)
        # Normally, the current character's visits are changed. However, if $self->showChar is set,
        #   that character's visits are changed
        #
        # Expected arguments
        #   $mode   - 'increase' to increase the number of visits by one, 'decrease' to decrease the
        #               visits by one, 'manual' to let the user enter a value manually, 'reset' to
        #               reset the number to zero
        #
        # Return values

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

                    'ok',
                );
            }
        }

        return 1;
    }

    sub toggleGraffitiCallback {

        # Called by $self->enableRoomsColumn, ->enableRoomsPopupMenu and ->drawMiscButtonSet
        # Toggles graffiti in the selected room(s)
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments
        #   1 otherwise

        my ($self, $check) = @_;

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        $self->showMsgDialogue(
            'Reset exclusive profiles',
            'info',
            $msg,
            'ok',
        );

        return 1;
    }

    # Menu 'Exits' column callbacks

    sub changeDirCallback {

        # Called by $self->enableExitsColumn
        # Changes an existing exit's direction and/or its map direction, prompting the user for the
        #   new directions
        #
        # Expected arguments
        #   (none besides $self)
        #

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        $self->setSelectedObj(
            [$exitObj, 'exit'],
            FALSE,          # Select this object; unselect all other objects
        );

        return 1;
    }

    sub viewExitDestination {

        # Called by $self->enableExitTagsPopupMenu (only)
        # For a region exit, selects the destination room and changes the currently displayed region
        #   (and level) to show it
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments or if the standard callback check fails
        #   1 otherwise

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

            $self->session,
            TRUE,           # Update Automapper windows now
            @finalList,
        );

        return 1;
    }

    sub addBendCallback {

        # Called by $self->enableExitsPopupMenu (only)
        # After a right-click on an exit, when the user has selected 'add bend' in the popup menu,
        #   add a bend at the same position
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments, if the standard callback check fails or if the bend is
        #       not added
        #   1 otherwise

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

                    'ok',
                );
            }

            return undef;
        }
    }

    sub removeBendCallback {

        # Called by $self->enableExitsPopupMenu (only)
        # After a right-click on an exit, when the user has selected 'remove bend' in the popup
        #   menu, remove the bend closest to the clicked position
        #
        # Expected arguments
        #   (none besides $self)
        #
        # Return values
        #   'undef' on improper arguments, if the standard callback check fails or if the mouse
        #       click was not near a bend
        #   1 otherwise

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

                    TRUE,               # Update Automapper windows now
                    $twinExitObj,
                    ((scalar $self->selectedExit->bendOffsetList / 2) - $index - 1),
                );
            }

            return 1;
        }
    }

    # Menu 'Labels' column callbacks

    sub addLabelAtBlockCallback {

        # Called by $self->enableLabelsColumn
        # Prompts the user to supply a gridblock (via a 'dialogue' window) and creates a label at
        #   that location
        #
        # Expected arguments
        #   (none besides $self)
        #

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

            return 1;

        } else {

            return undef;
        }
    }

    sub addLabelAtClickCallback {

        # Called by $self->enableCanvasPopupMenu and ->canvasEventHandler
        # Adds a label at a specified location on the current level
        #
        # Expected arguments
        #   $xPosPixels, $yPosPixels
        #       - The grid coordinates at which to create the label
        #
        # Return values
        #   'undef' on improper arguments, if the user clicks the 'cancel' button on the 'dialogue'
        #       window or if the new label can't be created
        #   1 otherwise

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

            return 1;

        } else {

            return undef;
        }
    }

    sub setLabelDirectCallback {

        # Called by $self->enableLabelsPopupMenu (only)
        #
        # Sets the selected label's label style, without needing to prompt the user any further
        #
        # Expected arguments
        #   $style      - The name of the label style to use
        #
        # Return values
        #   'undef' on improper arguments or if the standard callback check fails
        #   1 otherwise

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        #
        # Return values
        #   'undef' on improper arguments, or if an attempt to switch to 'update' mode fails because
        #       the Locator task is expecting room descriptions
        #   1 otherwise

        my ($self, $mode, $check) = @_;

        # Local variables
        my (
            $taskObj, $title, $oldMode, $menuItemName, $radioMenuItem, $toolbarButtonName,
            $toolbarButton,
        );

        # Check for improper arguments
        if (
            ! defined $mode || ($mode ne 'wait' && $mode ne 'follow' && $mode ne 'update')
            || defined $check
        ) {
            return $axmud::CLIENT->writeImproper($self->_objClass . '->setMode', @_);
        }

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

            }
        }

        # We need to compare the old/new settings of $self->mode in a moment
        $oldMode = $self->mode;
        # Set the automapper's new operating mode
        $self->ivPoke('mode', $mode);

        # Even if $self->mode hasn't changed, it might not match the menu items and the toolbar
        #   button; so we must make sure the right ones are activated. Use
        #   $self->ignoreMenuUpdateFlag so that toggling a menu item doesn't toggle a toolbar icon
        #   (and vice-versa)
        $self->ivPoke('ignoreMenuUpdateFlag', TRUE);

        # Update radio buttons in the menu (if the menu is visible)
        $menuItemName = 'set_'. $mode . '_mode';
        if ($self->menuBar && $self->ivExists('menuToolItemHash', $menuItemName)) {

            $radioMenuItem = $self->ivShow('menuToolItemHash', $menuItemName);
            $radioMenuItem->set_active(TRUE);
        }

        # Update toolbar buttons in the toolbar (if the toolbar is visible)
        $toolbarButtonName = 'icon_set_'. $mode . '_mode';
        if ($self->toolbarList && $self->ivExists('menuToolItemHash', $toolbarButtonName)) {

            $toolbarButton = $self->ivShow('menuToolItemHash', $toolbarButtonName);
            $toolbarButton->set_active(TRUE);
        }

        # Make sure that the radio/toolbar buttons for 'update mode' are sensitive, or not
        $self->restrictUpdateMode();
        $self->ivPoke('ignoreMenuUpdateFlag', FALSE);

        # In case the automapper object's ghost room gets set to the wrong room, switching to
        #   'wait' mode temporarily must reset it
        if ($self->mode eq 'wait' && $self->mapObj->ghostRoom) {

            $self->mapObj->setGhostRoom();      # Automatically redraws the room

        # If switching from 'wait' to 'follow'/'update' mode and there is a current room set, the
        #   ghost room will not be set, so st it
        } elsif (

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        # Reset the mouse icon
        $gdkWindow = $self->winWidget->get_window();
        if ($gdkWindow) {

            $gdkWindow->set_cursor($axmud::CLIENT->constMapCursor);
        }

        return 1;
    }

    sub set_ignoreMenuUpdateFlag {

        my ($self, $flag, $check) = @_;

        # Check for improper arguments
        if (! defined $flag || defined $check) {

            return $axmud::CLIENT->writeImproper(
                $self->_objClass . '->set_ignoreMenuUpdateFlag',
                @_,
            );
        }

        if ($flag) {
            $self->ivPoke('ignoreMenuUpdateFlag', TRUE);
        } else {
            $self->ivPoke('ignoreMenuUpdateFlag', FALSE);
        }

        return 1;
    }

    sub add_graffiti {

        my ($self, $roomObj, $check) = @_;

        # Check for improper arguments

lib/Games/Axmud/Win/Map.pm  view on Meta::CPAN

        { my $self = shift; return %{$self->{constSpecialVectorHash}}; }
    sub constTriangleCornerHash
        { my $self = shift; return %{$self->{constTriangleCornerHash}}; }
    sub constGtkAnchorHash
        { my $self = shift; return %{$self->{constGtkAnchorHash}}; }

    sub constMagnifyList
        { my $self = shift; return @{$self->{constMagnifyList}}; }
    sub constShortMagnifyList
        { my $self = shift; return @{$self->{constShortMagnifyList}}; }
    sub ignoreMenuUpdateFlag
        { $_[0]->{ignoreMenuUpdateFlag} }

    sub dragModeFlag
        { $_[0]->{dragModeFlag} }
    sub dragFlag
        { $_[0]->{dragFlag} }
    sub dragContinueFlag
        { $_[0]->{dragContinueFlag} }
    sub dragCanvasObj
        { $_[0]->{dragCanvasObj} }
    sub dragCanvasObjList

nsis/axmud_install.nsi  view on Meta::CPAN


    ;Request application privileges for Windows Vista
    RequestExecutionLevel user

    ; Extra stuff here
    BrandingText " "

# Variables
# -------------------------------

#   Var StartMenuFolder

# Interface settings
# -------------------------------

    !define MUI_ABORTWARNING
    !define MUI_ICON "axmud_icon.ico"
    !define MUI_UNICON "axmud_icon.ico"
    !define MUI_HEADERIMAGE
    !define MUI_HEADERIMAGE_BITMAP "axmud_header.bmp"
    !define MUI_HEADERIMAGE_UNBITMAP "axmud_header.bmp"

nsis/axmud_install.nsi  view on Meta::CPAN

Section "Axmud" SecClient

    SectionIn RO
    SetOutPath "$INSTDIR"

    File "axmud_icon.ico"
    File /r msys64

    SetOutPath "$INSTDIR\msys64\home\user\axmud"

    # Start Menu
    CreateDirectory "$SMPROGRAMS\Axmud"
    CreateShortCut "$SMPROGRAMS\Axmud\Axmud (all users).lnk" \
        "$INSTDIR\msys64\home\user\axmud\runaxmud.bat" "" "$INSTDIR\axmud_icon.ico"
    CreateShortCut "$SMPROGRAMS\Axmud\Axmud (visually-impaired users).lnk" \
        "$INSTDIR\msys64\home\user\axmud\blindaxmud.bat" "" "$INSTDIR\axmud_icon.ico"

    # Desktop icon
    CreateShortcut "$DESKTOP\Axmud.lnk" "$INSTDIR\msys64\home\user\axmud\runaxmud.bat" "" \
        "$INSTDIR\axmud_icon.ico"



( run in 0.882 second using v1.01-cache-2.11-cpan-49f99fa48dc )