Games-Axmud
view release on metacpan or search on metacpan
lib/Games/Axmud/Table.pm view on Meta::CPAN
# Use TRUE or FALSE flags
if (! $expandFlag) {
$expandFlag = FALSE;
} else {
$expandFlag = TRUE;
}
if (! $fillFlag) {
$fillFlag = FALSE;
} else {
$fillFlag = TRUE;
}
# Check $spacing is an integer, or use a default value
if (! defined $spacing || ! $axmud::CLIENT->intCheck($spacing, 0)) {
$spacing = 0;
}
$self->packingBox2->pack_end($widget, $expandFlag, $fillFlag, $spacing);
return 1;
} else {
# Can't pack the widget if the main container widget already contains something
if ($self->packingBox2->get_children()) {
return undef;
}
if ($self->type eq 'scroll') {
$self->packingBox2->add_with_viewport($widget);
} else {
$self->packingBox2->add($widget);
}
return 1;
}
}
sub remove {
# Can be called by anything to remove a widget from the main container widget
#
# Expected arguments
# $widget - The Gtk3 widget to remove from the main container widget
#
# Return values
# 'undef' on improper arguments
# 1 otherwise
my ($self, $widget, $check) = @_;
# Check for improper arguments
if (! defined $widget || defined $check) {
return $axmud::CLIENT->writeImproper($self->_objClass . '->remove', @_);
}
return $axmud::CLIENT->desktopObj->removeWidget($self->packingBox2, $widget);
}
sub empty {
# Can be called by anything to remove all widgets from the main container widget
#
# 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 . '->empty', @_);
}
foreach my $child ($self->packingBox2->get_children()) {
$self->packingBox2->remove($child);
}
return 1;
}
##################
# Accessors - set
sub set_equal {
my ($self, $flag, $check) = @_;
# Check for improper arguments
if (! defined $flag || defined $check) {
return $axmud::CLIENT->writeImproper($self->_objClass . '->set_equal', @_);
}
if ($self->type ne 'horizontal' && $self->type ne 'vertical') {
return undef;
}
if (! $flag) {
$self->packingBox2->set_column_homogeneous(FALSE);
$self->packingBox2->set_row_homogeneous(FALSE);
} else {
$self->packingBox2->set_column_homogeneous(TRUE);
$self->packingBox2->set_row_homogeneous(TRUE);
}
return 1;
}
lib/Games/Axmud/Table.pm view on Meta::CPAN
# sub setWidgetsIfSession {} # Inherited from GA::Generic::Table
# sub setWidgetsChangeSession {} # Inherited from GA::Generic::Table
# sub setWidgetsOnResize {} # Inherited from GA::Generic::Table
# ->signal_connects
# Other functions
sub pack {
# Can be called by anything to add a widget to the mini-table
# Unlike GA::Strip::Table, this code doesn't perform any checks; the widget is added
# regardless of any existing widgets that are already on the table
#
# Expected arguments
# $widget - The Gtk3 widget to add to the main container widget
# $left, Right, $top, $bottom
# - The table coordinates to use
#
# Return values
# 'undef' on improper arguments
# 1 on success
my ($self, $widget, $left, $right, $top, $bottom, $check) = @_;
# Check for improper arguments
if (
! defined $widget || ! defined $left || ! defined $right || ! defined $top
|| ! defined $bottom || defined $check
) {
return $axmud::CLIENT->writeImproper($self->_objClass . '->pack', @_);
}
$self->packingBox2->attach($widget, $left, $right, $top, $bottom);
return 1;
}
sub remove {
# Can be called by anything to remove a widget from the mini-table
#
# Expected arguments
# $widget - The Gtk3 widget to remove from the mini-table
#
# Return values
# 'undef' on improper arguments
# 1 otherwise
my ($self, $widget, $check) = @_;
# Check for improper arguments
if (! defined $widget || defined $check) {
return $axmud::CLIENT->writeImproper($self->_objClass . '->remove', @_);
}
return $axmud::CLIENT->desktopObj->removeWidget($self->packingBox2, $widget);
}
sub empty {
# Can be called by anything to remove all widgets from the mini-table
#
# 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 . '->empty', @_);
}
foreach my $child ($self->packingBox2->get_children()) {
$self->packingBox2->remove($child);
}
return 1;
}
##################
# Accessors - set
sub set_equal {
my ($self, $colFlag, $rowFlag, $check) = @_;
# Check for improper arguments
if (defined $check) {
return $axmud::CLIENT->writeImproper($self->_objClass . '->set_homo', @_);
}
if ($self->type ne 'horizontal' && $self->type ne 'vertical') {
return undef;
}
if (! $colFlag) {
$self->packingBox2->set_column_homogeneous(FALSE);
} else {
$self->packingBox2->set_column_homogeneous(TRUE);
}
if (! $rowFlag) {
$self->packingBox2->set_row_homogeneous(FALSE);
} else {
$self->packingBox2->set_row_homogeneous(TRUE);
}
return 1;
lib/Games/Axmud/Table.pm view on Meta::CPAN
if (! defined $text) {
$text = '';
}
$editFlag = $self->testFlag($self->ivShow('initHash', 'edit_flag'));
$systemFlag = $self->testFlag($self->ivShow('initHash', 'system_flag'));
$colourScheme = $self->ivShow('initHash', 'colour_scheme');
$spacing = $self->testInt($self->ivShow('initHash', 'spacing'), 0, 0);
$hExpandFlag = $self->testFlag($self->ivShow('initHash', 'expand_horizontal_flag'));
$vExpandFlag = $self->testFlag($self->ivShow('initHash', 'expand_vertical_flag'));
# Create packing box(es)
my ($packingBox, $packingBox2) = $self->setupPackingBoxes(Gtk3::Grid->new());
# Create the Gtk3::TextView inside a Gtk3::Frame and Gtk3::ScrolledWindow. However, if
# $packingBox is itself a Gtk3::Frame, don't create a second one
my ($frame, $scroll);
if (! $packingBox->isa('Gtk3::Frame')) {
$frame = Gtk3::Frame->new(undef);
$packingBox2->attach($frame, 0, 0, 1, 1);
$frame->set_border_width($spacing);
$scroll = Gtk3::ScrolledWindow->new(undef, undef);
$frame->add($scroll);
} else {
$scroll = Gtk3::ScrolledWindow->new(undef, undef);
$packingBox2->attach($scroll, 0, 0, 1, 1);
}
$scroll->set_shadow_type($axmud::CLIENT->constShadowType);
$scroll->set_policy('automatic', 'automatic');
$scroll->set_border_width($spacing);
# Create a textview
my $textView = Gtk3::TextView->new();
$scroll->add($textView);
my $buffer = Gtk3::TextBuffer->new();
$textView->set_buffer($buffer);
if (! $editFlag) {
$textView->set_editable(FALSE);
$textView->set_cursor_visible(FALSE);
$textView->set_can_focus(FALSE);
} else {
$textView->set_editable(TRUE);
$textView->set_cursor_visible(TRUE);
$textView->set_can_focus(TRUE);
}
$textView->set_wrap_mode('word-char'); # Wrap words if possible, characters if not
$textView->set_justification('left');
if ($systemFlag && $axmud::CLIENT->ivExists('colourSchemeHash', $colourScheme)) {
$axmud::CLIENT->desktopObj->setTextViewStyle($colourScheme, $textView);
} else {
$axmud::CLIENT->desktopObj->setTextViewStyle($self->winObj->winType, $textView);
}
$buffer->set_text($text);
# Set expansion
$textView->set_hexpand($hExpandFlag);
$textView->set_vexpand($vExpandFlag);
# Update IVs
$self->ivPoke('funcRef', $funcRef);
$self->ivPoke('funcID', $funcID);
$self->ivPoke('packingBox', $packingBox);
$self->ivPoke('packingBox2', $packingBox2);
$self->ivPoke('frame', $frame);
$self->ivPoke('scroll', $scroll);
$self->ivPoke('textView', $textView);
$self->ivPoke('buffer', $buffer);
# Set up ->signal_connects
$self->setChangedEvent();
return 1;
}
# sub objDestroy { # Inherited from GA::Generic::Table
# sub setWidgetsIfSession {} # Inherited from GA::Generic::Table
# sub setWidgetsChangeSession {} # Inherited from GA::Generic::Table
# sub setWidgetsOnResize {} # Inherited from GA::Generic::Table
# ->signal_connects
sub setChangedEvent {
# Called by $self->objEnable
#
# 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 . '->setChangedEvent', @_);
}
$self->buffer->signal_connect('changed' => sub {
my $currentFuncRef = $self->funcRef;
if ($currentFuncRef) {
&$currentFuncRef(
$self,
$self->textView,
$self->buffer,
$self->funcID,
$axmud::CLIENT->desktopObj->bufferGetText($self->buffer),
);
}
});
return 1;
}
# Other functions
##################
# Accessors - set
sub set_editable {
my ($self, $flag, $check) = @_;
# Check for improper arguments
if (defined $check) {
return $axmud::CLIENT->writeImproper($self->_objClass . '->set_editable', @_);
}
if (! $flag) {
$self->textView->set_editable(FALSE);
$self->textView->set_cursor_visible(FALSE);
$self->textView->set_can_focus(FALSE);
} else {
$self->textView->set_editable(TRUE);
$self->textView->set_cursor_visible(TRUE);
$self->textView->set_can_focus(TRUE);
}
return 1;
}
# sub set_func {} # Inherited from GA::Generic::Table
# sub set_id {} # Inherited from GA::Generic::Table
sub set_text {
my ($self, $text, $check) = @_;
# Check for improper arguments
if (defined $check) {
return $axmud::CLIENT->writeImproper($self->_objClass . '->set_text', @_);
}
if (! defined $text) {
$text = '';
}
$self->buffer->set_text($text);
return 1;
}
sub insert_text {
my ($self, $text, $check) = @_;
# Check for improper arguments
if (defined $check) {
return $axmud::CLIENT->writeImproper($self->_objClass . '->insert_text_at_cursor', @_);
}
if (! defined $text) {
$text = '';
}
$self->buffer->insert_at_cursor ($text);
return 1;
}
# (Get equivalents)
sub get_editable {
my ($self, $check) = @_;
# Check for improper arguments
if (defined $check) {
return $axmud::CLIENT->writeImproper($self->_objClass . '->get_editable', @_);
}
if ($self->textView->get_editable()) {
return TRUE;
} else {
return FALSE;
}
}
sub get_text {
my ($self, $check) = @_;
# Check for improper arguments
if (defined $check) {
return $axmud::CLIENT->writeImproper($self->_objClass . '->get_text', @_);
}
return $axmud::CLIENT->desktopObj->bufferGetText($self->buffer);
}
##################
# Accessors - get
sub frame
{ $_[0]->{frame} }
sub scroll
{ $_[0]->{scroll} }
sub textView
{ $_[0]->{textView} }
sub buffer
{ $_[0]->{buffer} }
}
# Complex table objects
{ package Games::Axmud::Table::Pane;
use strict;
use warnings;
# use diagnostics;
use Glib qw(TRUE FALSE);
our @ISA = qw(Games::Axmud::Generic::Table Games::Axmud);
##################
# Constructors
sub new {
# Called by GA::Strip::Table->addTableObj
# Creates the GA::Table::Pane, which contains one or more Gtk3::TextViews sharing a single
# Gtk3::TextBuffer
#
# Expected arguments
# $number - The table object's number within the parent strip object (matches
# GA::Strip::Table->tableObjCount, or -1 for a temporary table object
# created to access its default IVs)
# $name - A name for the table object. Can be any string or, if no name was
# specified in the call to the calling function, $name is the same as
# $number. (No part of the code checks that table object names are unique;
# if two or more table objects share the same ->name, usually the one with
# the lowest ->number 'wins'. 'temp' for temporary table objects. Max 16
# chars)
# $stripObj - The parent strip object (GA::Strip::Table). 'temp' for temporary table
# objects
# $zoneObj - The tablezone object (GA::Obj::Tablezone) which marks out an area of the
# parent strip object's Gtk3::Grid for use exclusively by this table
# object. 'temp' for temporary table objects
#
# Optional arguments
# %initHash - A hash containing arbitrary data to use as the table object's
# initialisation settings. The table object should use default
# initialisation settings unless it can succesfully interpret one or more
# of the key-value pairs in the hash, if there are any
# - This type of table object recognises these initialisation settings:
#
# 'frame_title' - If specified, the table object is drawn inside a frame
lib/Games/Axmud/Table.pm view on Meta::CPAN
# anything else
# $defaultFlag - Flag set to TRUE if this tab will be $session's default tab (where
# text received from the world is usually displayed), FALSE (or
# 'undef') otherwise (might be TRUE even if $sessionFlag is FALSE)
# $labelText - The text to use in the tab label, ignored if specified (exists for
# compatibility with other functions in this group)
# $oldBuffer - If a Gtk3::Notebook with a single tab is being replaced by a
# standalone textview object, the old textview object's
# Gtk3::TextBuffer, which is transferred to the new textview object
# ('undef' otherwise)
#
# Return values
# 'undef' on improper arguments or if the simple tab can't be drawn
# Otherwise returns the tab object (GA::Obj::Tab) created, which stores (among other
# things) the textview object created
my (
$self, $session, $colourScheme, $sessionFlag, $defaultFlag, $labelText, $oldBuffer,
$check,
) = @_;
# Local variables
my ($textViewObj, $packedObj, $tabObj);
# Check for improper arguments
if (! defined $session || defined $check) {
return $axmud::CLIENT->writeImproper($self->_objClass . '->addSimpleTab', @_);
}
# If this pane object has drawn a notebook, not a simple container (a Gtk3::ScrolledWindow
# or Gtk3::VPaned), $self->addTab should have been called instead. Show a warning, then
# redirect the function call
if ($self->notebook) {
$self->winObj->session->writeWarning(
'Tried to add a simple tab to a notebook; code should call ->addTab, not'
. ' ->addSimpleTab',
$self->_objClass . '->addSimpleTab',
);
return $self->addTab(
$session,
$colourScheme,
$sessionFlag,
$defaultFlag,
$labelText,
$oldBuffer,
);
# If there is already a simple tab, don't create another one
} elsif ($self->tabObjHash) {
return $self->writeError(
'Tried to add a simple tab, but one or more tabs already exist',
$self->_objClass . '->addSimpleTab',
);
}
# Create a new GA::Obj::Textview object to handle the Gtk3::Textview(s)
$textViewObj = $axmud::CLIENT->desktopObj->add_textView(
$session,
$self->winObj,
$self,
);
if (! $textViewObj) {
return undef;
}
# Set the colour scheme to use
if (
! defined $colourScheme
|| ! $axmud::CLIENT->ivExists('colourSchemeHash', $colourScheme)
) {
$colourScheme = $self->ivShow('initHash', 'colour_scheme');
}
# Create the Gtk3::TextView(s) themselves. The function call returns a Gtk3::ScrolledWindow
# or a Gtk3::VPaned containing the textview(s)
$packedObj = $textViewObj->objEnable(
$self->ivShow('initHash', 'split_mode'),
$colourScheme,
$self->ivShow('initHash', 'max_lines'),
$self->ivShow('initHash', 'new_line'),
$oldBuffer,
);
if (! $packedObj) {
$textViewObj->objDestroy();
return undef;
}
# Pack the Gtk3::ScrolledWindow/Gtk3::VPaned into our main Gtk3::VBox
$self->packingBox2->pack_start($packedObj, TRUE, TRUE, 0);
# Create a tab object to store details about the tab
$tabObj = Games::Axmud::Obj::Tab->new(
0, # ->number
$self,
$session,
$defaultFlag,
$textViewObj,
$self->packingBox2, # ->packableObj
$packedObj, # ->packedObj
);
# Update IVs. The code above has already checked that $self->tabObjHash is empty
$self->ivAdd('tabObjHash', $tabObj->number, $tabObj);
$self->ivIncrement('tabObjCount');
$self->ivPoke('simpleTabFlag', TRUE);
# Make the changes visible
$self->winObj->winShowAll($self->_objClass . '->addSimpleTab');
# The new tab is the visible tab
$self->respondVisibleTab($tabObj, $sessionFlag);
return $tabObj;
lib/Games/Axmud/Table.pm view on Meta::CPAN
# Local variables
my ($textViewObj, $packedObj, $tabObj);
# Check for improper arguments
if (! defined $session || defined $check) {
return $axmud::CLIENT->writeImproper($self->_objClass . '->addTab', @_);
}
# If this table object isn't using a notebook, but a simple container (a
# Gtk3::ScrolledWindow or a Gtk3::VPaned), convert from the latter to the former
if (! $self->notebook) {
if ($self->tabObjHash) {
# Convert the existing single tab to a normal tab
if (! $self->convertSimpleTab()) {
# (Error message displayed by called function)
return undef;
}
} else {
# No tabs exist, so create the notebook, then we can continue creating the first
# tab in it
if (! $self->drawNotebook()) {
return $self->writeWarning(
'General error adding a tab',
$self->_objClass . '->addTab',
);
}
}
}
# Create the tab
# The tab contains a vertical packing box, which contains everything else
my $vBox = Gtk3::VBox->new(FALSE, 0);
$vBox->set_border_width(0);
# A horizontal packing box is used as the tab's label (in place of a Gtk3::Label)
my $hBox = Gtk3::HBox->new(FALSE, 0);
my $label = Gtk3::Label->new();
$hBox->pack_start($label, FALSE, FALSE, 0);
$label->show();
# Add an 'X' button to close the tab, if required
my $button;
if ($self->canCloseFlag) {
$button = Gtk3::Button->new();
$hBox->pack_start($button, FALSE, FALSE, 0);
$button->set_image(Gtk3::Image->new_from_stock('gtk-close', 'menu'));
$button->set_relief('none');
$button->show();
}
# Create a new GA::Obj::Textview object to handle the Gtk3::Textview(s)
$textViewObj = $axmud::CLIENT->desktopObj->add_textView(
$session,
$self->winObj,
$self,
);
if (! $textViewObj) {
return undef;
}
# Set the colour scheme to use
if (
! defined $colourScheme
|| ! $axmud::CLIENT->ivExists('colourSchemeHash', $colourScheme)
) {
$colourScheme = $self->ivShow('initHash', 'colour_scheme');
}
# Create the Gtk3::TextView(s) themselves. The function call returns a Gtk3::ScrolledWindow
# or a Gtk3::VPaned containing the textview(s)
$packedObj = $textViewObj->objEnable(
$self->ivShow('initHash', 'split_mode'),
$colourScheme,
$self->ivShow('initHash', 'max_lines'),
$self->ivShow('initHash', 'new_line'),
$oldBuffer,
);
if (! $packedObj) {
$textViewObj->objDestroy();
return undef;
}
# Pack the Gtk3::ScrolledWindow/Gtk3::VPaned into this tab's Gtk3::VBox
$vBox->pack_start($packedObj, TRUE, TRUE, 0);
# From Gtk documentation: 'Note that due to historical reasons, GtkNotebook refuses to
# switch to a page unless the child widget is visible. Therefore, it is recommended to
# show child widgets before adding them to a notebook.'
$vBox->show();
$hBox->show();
# Add the tab to the notebook
my $tabNum = $self->notebook->append_page($vBox, $hBox);
# Make the tab re-orderable
my $tabWidget = $self->notebook->get_nth_page($tabNum);
$self->notebook->set_tab_reorderable($tabWidget, TRUE);
# If no label text was specified, use the default text
if (! defined $labelText) {
$labelText = 'Tab #' . $tabNum;
}
$label->set_markup($labelText);
# Create a tab object to store details about the tab
$tabObj = Games::Axmud::Obj::Tab->new(
$self->tabObjCount, # ->number
$self,
$session,
$defaultFlag,
$textViewObj,
$vBox, # ->packableObj
$packedObj, # ->packedObj
$vBox, # ->tabWidget
$label, # ->tabLabel
);
# Update IVs
$self->ivAdd('tabObjHash', $tabObj->number, $tabObj);
$self->ivIncrement('tabObjCount');
# The new tab should be the visible (current) one
# NB When replacing a standalone textview object with a Gtk3::Notebook, adding the old
# textview object's buffer to the new notebook's first tab, we don't set the first tab as
# the current page - because the calling function wants to set the (new) second tab as the
# current page
if (! $oldBuffer) {
$self->notebook->set_current_page($tabNum);
}
# After replacing a standalone textview object with a Gtk3::Notebook, the original session's
# textview(s) don't scroll to the bottom (as it should) without this code (and placing the
# code anywhere else doesn't work, either)
if ($oldBuffer) {
$axmud::CLIENT->desktopObj->updateWidgets($self->_objClass . '->addTab');
}
# Set up ->signal_connects for the close button, if it was created
if ($button) {
if (! $defaultFlag) {
$self->setButtonClicked($button, $tabObj);
} else {
$self->setButtonClicked($button, $tabObj, $session);
}
}
# Make the changes visible
$self->winObj->winShowAll($self->_objClass . '->addTab');
# The new tab is the visible tab. The call above to ->set_current_page ought to have
# caused a call to $self->respondVisibleTab, but if $sessionFlag is set, call it again,
# forcing it to call GA::Win::Internal->setVisibleSession at least once
if ($sessionFlag) {
$self->respondVisibleTab($tabObj, $sessionFlag);
}
return $tabObj;
}
sub removeSessionTab {
# Called by GA::Session->stop (only)
# Removes the tab containing the default textview object for the calling session (if other
# parts of the code want to remove a non-default tab, they should call
# $self->removeTabNum)
# After removing the tab, if there is then only a single session open, and if the
# initialisation setting demands that we use a simple tab rather than a Gtk3::Notebook
# tab, replace the notebook with a simple tab
#
# Expected arguments
# $session - The GA::Session for the tab to be removed
#
# Return values
# 'undef' on improper arguments, or if the tab widgets can't be removed or if the
# session's default tab can't be found
# 1 on success
my ($self, $session, $check) = @_;
# Local variables
my ($tabObj, $count, $newTabObj);
# Check for improper arguments
if (! defined $session || defined $check) {
return $axmud::CLIENT->writeImproper($self->_objClass . '->removeTab', @_);
}
if (! $self->notebook) {
# A simple tab, containing a standalone textview object
$tabObj = $self->ivShow('tabObjHash', 0);
if (! $tabObj || ! $tabObj->defaultFlag || $tabObj->session ne $session) {
# (Error message displayed by calling function)
return undef;
}
# Remove the simple tab by removing everything from the main packing box
$axmud::CLIENT->desktopObj->removeWidget($self->packingBox2, $tabObj->packedObj);
# Inform the textview object (if any) of its demise
if ($tabObj->textViewObj) {
$tabObj->textViewObj->objDestroy();
}
# Update IVs
$self->ivEmpty('tabObjHash');
$self->ivPoke('tabObjCount', 0);
} else {
# A tab in a Gtk3::Notebook. Find which one corresponds to the session
$tabObj = $self->findSession($session);
if (! defined $tabObj) {
# (Error message displayed by calling function)
return undef;
}
# Remove the tab from its Gtk3::Notebook
$self->notebook->remove_page($self->notebook->page_num($tabObj->tabWidget));
# Inform the textview object (if any) of its demise
if ($tabObj->textViewObj) {
$tabObj->textViewObj->objDestroy();
}
# Update IVs
$self->ivDelete('tabObjHash', $tabObj->number);
# If there is only one tab left, and the first tab created (since the pane was last
# empty of tabs) was a simple tab, convert a normal tab into a simple tab
$count = $self->ivPairs('tabObjHash');
if ($count == 1 && $self->simpleTabFlag) {
if (! $self->convertTab()) {
# (Error message already displayed)
return undef;
}
# If there are no tabs left, remove the notebook itself, so the next tab to be added can
# be a simple or normal tab
} elsif (! $count) {
$axmud::CLIENT->desktopObj->removeWidget($self->packingBox2, $self->notebook);
$self->ivUndef('notebook');
}
}
# If there are no tabs left, the calling code can create a simple tab or a normal tab
if (! $self->tabObjHash) {
$self->ivPoke('simpleTabFlag', FALSE);
}
# Make the changes visible
$self->winObj->winShowAll($self->_objClass . '->removeTab');
return 1;
}
sub removeTab {
# Called by callback in $self->setButtonClicked (only)
# Removes the specified tab
#
# Expected arguments
# $tabObj - The GA::Obj::Tab to remove
#
# Return values
# 'undef' on improper arguments, or if the specified tab doesn't exist
# 1 on success
my ($self, $tabObj, $check) = @_;
# Local variables
my ($count, $funcRef);
# Check for improper arguments
if (! defined $tabObj || defined $check) {
return $axmud::CLIENT->writeImproper($self->_objClass . '->removeTab', @_);
}
# Check the tab exists
if (! $self->ivExists('tabObjHash', $tabObj->number)) {
return undef;
}
# Remove the tab
if (! $self->notebook) {
# A simple tab, containing a standalone textview object
# Remove the simple tab by removing everything from the main packing box
$axmud::CLIENT->desktopObj->removeWidget($self->packingBox2, $tabObj->packedObj);
# Inform the textview object (if any) of its demise
if ($tabObj->textViewObj) {
$tabObj->textViewObj->objDestroy();
}
# Update IVs
$self->ivEmpty('tabObjHash');
$self->ivPoke('tabObjCount', 0);
} else {
# A tab in a Gtk3::Notebook
# Remove the tab from its Gtk3::Notebook
$self->notebook->remove_page($self->notebook->page_num($tabObj->tabWidget));
# Inform the textview object (if any) of its demise
if ($tabObj->textViewObj) {
$tabObj->textViewObj->objDestroy();
}
# Update IVs
$self->ivDelete('tabObjHash', $tabObj->number);
# If there is only one tab left, and the first tab created (since the pane was last
# empty of tabs) was a simple tab, convert a normal tab into a simple tab
$count = $self->ivPairs('tabObjHash');
if ($count == 1 && $self->simpleTabFlag) {
if (! $self->convertTab()) {
# (Error message already displayed)
return undef;
}
# If there are no tabs left, remove the notebook itself, so the next tab to be added can
# be a simple or normal tab
} elsif (! $count) {
$axmud::CLIENT->desktopObj->removeWidget($self->packingBox2, $self->notebook);
$self->ivUndef('notebook');
}
}
# If there are no tabs left, the calling code can create a simple tab or a normal tab
if (! $self->tabObjHash) {
$self->ivPoke('simpleTabFlag', FALSE);
}
# Inform any code that wants to be informed when the tab changes
if ($self->closeFuncRef) {
$funcRef = $self->closeFuncRef;
&$funcRef($self, $tabObj, $self->closeFuncID);
}
# Make the changes visible
$self->winObj->winShowAll($self->_objClass . '->removeTab');
return 1;
}
sub convertSimpleTab {
# Called by $self->addTab, when a simple tab is currently visible
#
# Converts the standalone textview object (a simple tab) into a new tab on a Gtk3::Notebook,
# preserving the Gtk3::TextBuffer
#
# Expected arguments
# (none besides $self)
#
# Return values
# 'undef' on improper arguments or if there's an error
# 1 on success
my ($self, $check) = @_;
# Local variables
my ($oldTabObj, $newTabObj, $notebook, $oldLabelText);
# Check for improper arguments
if (defined $check) {
return $axmud::CLIENT->writeImproper($self->_objClass . '->convertSimpleTab', @_);
}
# Set a flag that various ->signal_connects can use to avoid responding when a tab
# conversion operation is in progress
$self->ivPoke('tabConvertFlag', TRUE);
# Get the single existing tab
$oldTabObj = $self->ivShow('tabObjHash', 0);
# Remove the standalone textview object
$axmud::CLIENT->desktopObj->removeWidget($self->packingBox2, $oldTabObj->packedObj);
# Add a Gtk3::Notebook in its place
$notebook = $self->drawNotebook();
if (! $notebook) {
# Emergency fallback - put the old textview back, as if nothing had happened (but show a
# warning)
$self->packingBox2->pack_start($oldTabObj->packedObj, TRUE, TRUE, 0);
return $self->writeWarning(
'General error converting simple tab',
$self->_objClass . '->convertSimpleTab',
);
}
# Update IVs
$self->ivEmpty('tabObjHash');
$self->ivPoke('tabObjCount', 0);
# Add a tab in its place, using the old textview object's buffer and the old session number
if ($oldTabObj->defaultFlag) {
$oldLabelText = $oldTabObj->session->getTabLabelText();
}
$newTabObj = $self->addTab(
$oldTabObj->session,
$oldTabObj->textViewObj->colourScheme,
undef, # Not called by GA::Session->setDefaultTab
$oldTabObj->defaultFlag,
$oldLabelText,
$oldTabObj->textViewObj->buffer,
);
# Restore the scroll lock, if it was enabled in the old single textview
if ($oldTabObj->textViewObj->scrollLockFlag) {
$newTabObj->textViewObj->toggleScrollLock();
}
# Restore the old single textview's split screen mode
$newTabObj->textViewObj->setSplitScreenMode($oldTabObj->textViewObj->splitScreenMode);
# Update the GA::Session's tab IVs, as required
if (
$oldTabObj->session->defaultTabObj
&& $oldTabObj->session->defaultTabObj eq $oldTabObj
) {
$oldTabObj->session->set_defaultTabObj($newTabObj);
}
if (
$oldTabObj->session->currentTabObj
&& $oldTabObj->session->currentTabObj eq $oldTabObj
) {
$oldTabObj->session->set_currentTabObj($newTabObj);
}
# Operation complete
$self->ivPoke('tabConvertFlag', FALSE);
return 1;
}
sub convertTab {
# Called by $self->removeSessionTab or ->removeTab when there's only a single Gtk3::Notebook
# tab left, and the initialisation setting specifies that a tab label shouldn't be visible
# Converts the Gtk3::Notebook containing a single remaining tab into a standalone textview
# object, preserving its Gtk3::TextBuffer (a simple tab)
#
# Expected arguments
# (none besides $self)
#
# Return values
# 'undef' on improper arguments or if there's an error
# 1 on success
my ($self, $tabObj, $check) = @_;
# Local variables
my ($oldTabObj, $scroll, $newTabObj, $oldLabelText);
# Check for improper arguments
if (defined $check) {
return $axmud::CLIENT->writeImproper($self->_objClass . '->convertTab', @_);
}
# Set a flag that various ->signal_connects can use to avoid responding when a tab
# conversion operation is in progress
$self->ivPoke('tabConvertFlag', TRUE);
# Get the single remaining tab (the calling function has already checked there is only one)
($oldTabObj) = $self->ivValues('tabObjHash');
if (! $oldTabObj) {
return $self->writeWarning(
'General error converting tab',
$self->_objClass . '->convertTab',
);
}
# Remove the Gtk3::Notebook
$axmud::CLIENT->desktopObj->removeWidget($self->packingBox2, $self->notebook);
# v1.1.128 This is not necessary, and in fact messes up everything
# # Replace it with a standalone textview object
# $axmud::CLIENT->desktopObj->removeWidget($oldTabObj->packableObj, $oldTabObj->packedObj);
# $self->packingBox2->pack_start($oldTabObj->packedObj, TRUE, TRUE, 0);
# Update IVs
$self->ivUndef('notebook');
$self->ivEmpty('tabObjHash');
$self->ivPoke('tabObjCount', 0);
# Add a simple tab, using the old tab's buffer and the old session
if ($oldTabObj->defaultFlag) {
$oldLabelText = $oldTabObj->session->getTabLabelText();
}
$newTabObj = $self->addSimpleTab(
$oldTabObj->session,
$oldTabObj->textViewObj->colourScheme,
undef, # Not called by GA::Session->setDefaultTab
$oldTabObj->defaultFlag,
$oldLabelText,
$oldTabObj->textViewObj->buffer,
);
# Restore the scroll lock, if it was enabled in the old single textview
if ($oldTabObj->textViewObj->scrollLockFlag) {
$newTabObj->textViewObj->toggleScrollLock();
}
# Restore the old single textview's split screen mode
$newTabObj->textViewObj->setSplitScreenMode($oldTabObj->textViewObj->splitScreenMode);
# Update the GA::Session's tab IVs, as required
if (
$oldTabObj->session->defaultTabObj
&& $oldTabObj->session->defaultTabObj eq $oldTabObj
) {
$oldTabObj->session->set_defaultTabObj($newTabObj);
}
if (
$oldTabObj->session->currentTabObj
&& $oldTabObj->session->currentTabObj eq $oldTabObj
) {
$oldTabObj->session->set_currentTabObj($newTabObj);
}
# Operation complete
$self->ivPoke('tabConvertFlag', FALSE);
return 1;
}
sub updateColourScheme {
# Called by GA::Win::Internal->updateColourScheme (only)
# When a colour scheme is modified, checks all textview objects in this pane object and
# updates any that use the modified colour scheme. Alternatively, when no colour scheme is
# specified, updates all textview objects
#
# Expected arguments
lib/Games/Axmud/Table.pm view on Meta::CPAN
#
# Before v1.0.905, textview objects had two split screen modes, 'on' and 'off'. Since then,
# textview objects have had three modes, but pane objects continue to distinguish only
# between 'on' and 'off'
# The textview object modes 'single' and 'hidden' are considered 'off', and this function
# converts them to 'split'
# The textview object mode 'split' is considered 'off', and this function converts it to
# 'hidden'
# In this way, for textview objects created by a pane object, split screen mode is only
# 'single' when the textview object is created with that mode set. Once the mode is
# changed (by this function), it cannot be restored to 'single' (by this function)
#
# This change has been made because of Gtk3 performance issues, particularly with
# Gtk3::TextViews with large buffers. In general, any pane in which split screen mode
# might be turned 'on' should probably create the textview object using the mode 'hidden'
# rather than 'single'
#
# Expected arguments
# (none besides $self)
#
# Return values
# 'undef' on improper arguments or if the toggle operation fails
# 1 on success
my ($self, $check) = @_;
# Local variables
my ($tabObj, $packedObj, $viewport, $entryObj);
# Check for improper arguments
if (defined $check) {
return $axmud::CLIENT->writeImproper($self->_objClass . '->toggleSplitScreen', @_);
}
# Get the visible tab's tab object
if (! $self->notebook) {
$tabObj = $self->ivShow('tabObjHash', 0);
} else {
$tabObj = $self->ivShow('tabObjHash', $self->notebook->get_current_page());
}
if (! $tabObj || ! $tabObj->textViewObj) {
return undef;
}
# Get a new packable widget
if (
$tabObj->textViewObj->splitScreenMode eq 'single'
|| $tabObj->textViewObj->splitScreenMode eq 'hidden'
) {
$packedObj = $tabObj->textViewObj->setSplitScreenMode('split');
} else {
$packedObj = $tabObj->textViewObj->setSplitScreenMode('hidden');
}
# If $packedObj is defined, it must be re-packed, replacing the old packable widget
if ($packedObj) {
$axmud::CLIENT->desktopObj->removeWidget($tabObj->packableObj, $tabObj->packedObj);
$tabObj->packableObj->pack_start($packedObj, TRUE, TRUE, 0);
$tabObj->ivPoke('packedObj', $packedObj);
}
# Find the entry strip object (if it exists)
$entryObj = $self->winObj->ivShow('firstStripHash', 'Games::Axmud::Strip::Entry');
if ($entryObj) {
# Update the toolbutton icon for its scroll lock button
if ($tabObj->textViewObj->splitScreenMode eq 'split') {
$entryObj->updateSplitButton(TRUE);
} else {
$entryObj->updateSplitButton(FALSE);
}
}
if ($packedObj) {
# (If we try to scroll the textviews before they've been re-packed, we get an
# uncomfortable flash, so the scrolling function is called last)
$self->winObj->winShowAll($self->_objClass . '->toggleSplitScreen');
$axmud::CLIENT->desktopObj->updateWidgets($self->_objClass . '->toggleSplitScreen');
$tabObj->textViewObj->scrollToLock();
}
return 1;
}
sub findPage {
# Can be called by anything
# Finds the tab object (GA::Obj::Tab) corresponding to a specified page in the
# Gtk3::Notebook, when normal tabs (not simple tabs) are visible
# If there is a simple tab visible and the specified page is 0, return it
#
# Expected arguments
# $page - The tab's current page number in the notebook (0 for the first tab, 1
# for the second, etc)
#
# Return values
# 'undef' on improper arguments or if a matching tab object doesn't exist
# Otherwise, returns the tab object
my ($self, $page, $check) = @_;
# Check for improper arguments
if (! defined $page || defined $check) {
return $axmud::CLIENT->writeImproper($self->_objClass . '->findPage', @_);
}
# If there is a simple tab visible and the specified page is 0, return it
if (! $self->notebook) {
if ($page == 0) {
return $self->ivShow('tabObjHash', 0);
} else {
return undef;
}
}
# Otherwise, check each tab in turn until we find the right page number
foreach my $tabObj ($self->ivValues('tabObjHash')) {
my $num = $self->notebook->page_num($tabObj->tabWidget);
if ($num == $page) {
return $tabObj;
}
}
# Corresponding tab object not found
return undef;
}
sub findSession {
# Can be called by anything
# Finds the tab object (GA::Obj::Tab) for the tab/simple tab which contains the specified
# session's default textview object (GA::Obj::TextView)
#
# Expected arguments
( run in 0.700 second using v1.01-cache-2.11-cpan-f56aa216473 )