Games-Axmud
view release on metacpan or search on metacpan
lib/Games/Axmud/Obj/WorkspaceGrid.pm view on Meta::CPAN
# Return values
# 'undef' on improper arguments
# 1 otherwise
my ($self, $session, $check) = @_;
# Local variables
my ($count, $msg);
# Check for improper arguments
if (defined $check) {
return $axmud::CLIENT->writeImproper($self->_objClass . '->stop', @_);
}
# Tell any remaining 'grid' window objects to close their windows. If $session is
# defined, 'main' windows merely remove themselves from the workspace grid, but the
# window itself is not closed (exception: when Axmud is shutting down, all windows are
# closed)
# Do this in the reverse order they were created, in the expectation that 'main' windows
# will be closed last
foreach my $winObj (sort {$b->number <=> $a->number} ($self->ivValues('gridWinHash'))) {
if (! $axmud::CLIENT->shutdownFlag && $session && $session->mainWin eq $winObj) {
# (The ->winDisengage function calls $self->del_gridWin in turn)
$winObj->winDisengage($session);
} else {
# (The ->winDestroy function calls $self->del_gridWin in turn)
$winObj->winDestroy();
}
}
# Check there are no 'grid' windows left (for error-detection purposes)
$count = $self->ivPairs('gridWinHash');
if ($count) {
if ($count == 1) {
$msg = 'There was 1';
} else {
$msg = 'There were ' . $count;
}
$msg .= ' un-closed \'grid\' window when the parent workspace grid closed';
$axmud::CLIENT->writeWarning($msg, $self->_objClass . '->stop');
}
return 1;
}
sub fineTuneWinSize {
# Called by GA::Obj::Workspace->chooseWinPosn, $self->changeWinzone,
# GA::Obj::Zone->adjustMultipleWin and ->replaceAreaSpace
# Makes small adjustments to a window's size and position to close any gaps on the right and
# bottom edges of the workspace grid (because of an arkwardly-sized available workspace)
# Makes more small adjustments to correct for window controls, usually before a call to
# GA::Obj::Workspace->moveResizeWin. (If the desktop theme uses window controls, we have
# to take them into account, changing the size of the window accordingly; $widthPixels and
# $heightPixels must now refer to the client area, not the whole window including the
# window controls)
#
# Expected arguments
# $winType - The window type; one of the 'grid' window types specified by
# GA::Client->constGridWinTypeHash
# $xPosPixels, $yPosPixels
# - The position of the window to be fine-tuned
# $widthPixels, $heightPixels
# - The size of the window to be fine-tuned
#
# Return values
# An empty list on improper arguments
# Otherwise returns the adjusted list, in the form
# ($xPosPixels, $yPosPixels, $widthPixels, $heightPixels)
my ($self, $winType, $xPosPixels, $yPosPixels, $widthPixels, $heightPixels, $check) = @_;
# Local variables
my (
$gridRightEdge, $winRightEdge, $gridBottomEdge, $winBottomEdge, $rightGap, $bottomGap,
@emptyList,
);
# Check for improper arguments
if (
! defined $winType || ! defined $xPosPixels || ! defined $yPosPixels
|| ! defined $widthPixels || ! defined $heightPixels || defined $check
) {
$axmud::CLIENT->writeImproper($self->_objClass . '->fineTuneWinSize', @_);
return @emptyList;
}
# Close the gap between the workspace grid and the right and bottom edges of the available
# workspace, if there is one, and if the global flag is set
if ($axmud::CLIENT->gridEdgeCorrectionFlag) {
# Get the position of the right boundary of the workspace grid, and the right edge of
# the window, in pixels
$gridRightEdge
= $self->xPosPixels + ($self->widthBlocks * $axmud::CLIENT->gridBlockSize) - 1;
$winRightEdge = $xPosPixels + $widthPixels - 1;
$gridBottomEdge
= $self->yPosPixels + ($self->heightBlocks * $axmud::CLIENT->gridBlockSize) -1;
$winBottomEdge = $yPosPixels + $heightPixels - 1;
# For windows on the right edge of the workspace grid, look for a gap between that edge
# and the edge of the available workspace that's smaller than a gridblock
if ($gridRightEdge == $winRightEdge) {
$rightGap = $self->workspaceObj->currentWidth
- $self->workspaceObj->panelRightSize - 1 - $gridRightEdge;
if ($rightGap > 0 && $rightGap < $axmud::CLIENT->gridBlockSize) {
# Increase the width of the window, therefore closing the gap
$widthPixels += $rightGap;
}
lib/Games/Axmud/Obj/WorkspaceGrid.pm view on Meta::CPAN
}
for (my $num = ($layer - 1); $num >= 0; $num--) {
push (@layerList, $num);
}
}
return @layerList;
}
sub changeWinzone {
# Called by GA::Session->setMainWin, and also by GA::Cmd::MoveWindow->do, FixWindow->do
# Moves a window from one zone into any available space in another zone, the latter being
# a zone in this workspace grid
# If the new zone is the same as the old one, moves the window to the space it would have
# occupied, if it were being moved into this zone from a different one
#
# Expected arguments
# $winObj - Blessed reference to the window object to be moved (inheriting
# from GA::Generic::GridWin)
# $zoneObj - Blessed reference to the zone object (GA::Obj::Zone) into which
# the window should be moved
#
# Optional arguments
# $defaultSizeFlag - If TRUE, the window is resized to fit the zone's default size. If
# FALSE or 'undef', the window keeps its current size (subject to
# small adjustments to fill small gaps)
# $fixWidthPixels, $fixHeightPixels
# - Only specified when called by GA::Cmd::FixWindow->do. If the
# user has changed the window's size, these variables specify that
# size. Both must be specified or both must be set to 'undef'
#
# Return values
# 'undef' on improper arguments or if there's an error
# 1 otherwise
my (
$self, $winObj, $zoneObj, $defaultSizeFlag, $fixWidthPixels, $fixHeightPixels, $check,
) = @_;
# Local variables
my (
$blockSize, $widthPixels, $heightPixels, $widthBlocks, $heightBlocks, $xPosBlocks,
$yPosBlocks, $successFlag, $layer, $oldZoneObj, $xPosPixels, $yPosPixels, $areaObj,
);
# Check for improper arguments
if (
! defined $winObj || ! defined $zoneObj || defined $check
|| (defined $fixWidthPixels && ! defined $fixHeightPixels)
|| (! defined $fixWidthPixels && defined $fixHeightPixels)
) {
return $axmud::CLIENT->writeImproper($self->_objClass . '->changeWinzone', @_);
}
# Check that the window is a 'grid' window
if (
$winObj->winCategory ne 'grid'
|| ! $axmud::CLIENT->desktopObj->ivExists('gridWinHash', $winObj->number)
|| ! $winObj->areaObj
|| ! $winObj->areaObj->zoneObj
) {
return $axmud::CLIENT->writeError(
'Can\'t move the window - window is not a grid window',
$self->_objClass . '->changeWinzone',
);
}
# Check that the window is allowed in the new zone
if (
! $zoneObj->checkWinAllowed(
$winObj->winType,
$winObj->winName,
$winObj->session,
)
) {
return $axmud::CLIENT->writeError(
'Can\'t move the window - window is not allowed in zone #' . $zoneObj->number,
$self->_objClass . '->changeWinzone',
);
}
# Set the provisional size of the window in its new zone
# If called by GA::Cmd::FixWindow->do after the user manually changed the window's size,
# use that size
# If the default flag has been set, use the new zone's default size, otherwise use the
# window's current size
$blockSize = $axmud::CLIENT->gridBlockSize;
if ($fixWidthPixels) {
$widthPixels = $fixWidthPixels;
$heightPixels = $fixHeightPixels;
# When the window object was first created, the call to $self->fineTuneWinSize modified
# the size of the window due to window controls. We must reverse those changes (if
# they were applied), so that our call to $zoneObj->placeWin() will have the same
# initial window size as it would have had, if GA::Obj::Workspace->chooseWinPosn had
# been calling it
if ($winObj->winType ne 'external') {
$widthPixels += (
$winObj->workspaceObj->controlsLeftSize
+ $winObj->workspaceObj->controlsRightSize
);
$heightPixels += (
$winObj->workspaceObj->controlsTopSize
+ $winObj->workspaceObj->controlsBottomSize
);
}
} elsif ($defaultSizeFlag) {
$widthPixels = $zoneObj->defaultAreaWidth * $blockSize;
$heightPixels = $zoneObj->defaultAreaHeight * $blockSize;
} else {
$widthPixels = $winObj->areaObj->widthBlocks * $blockSize;
$heightPixels = $winObj->areaObj->heightBlocks * $blockSize;
}
# Try to find room for the window in the new zone
# First define a provisional position for the window at the zone's start corner
($widthBlocks, $heightBlocks, $xPosBlocks, $yPosBlocks)
= $zoneObj->findProvWinPosn($widthPixels, $heightPixels);
# Try to find room for the window in the new zone. Start at the default layer, then check
# other layers
($successFlag, $layer, $xPosBlocks, $yPosBlocks) = $zoneObj->placeWin(
$self->defaultLayer,
$xPosBlocks,
$yPosBlocks,
$widthBlocks,
$heightBlocks,
# In case the window already exists in the zone, any space it currently occupies is
# available
$winObj,
);
if (!$successFlag) {
# There is no room for the window in this zone
return $axmud::CLIENT->writeError(
'Can\'t move the window - ouldn\'t find room for the \'' . $winObj->winType
. '\' window anywhere in zone #' . $zoneObj->number,
$self->_objClass . '->changeWinzone',
);
}
# If the window position on the grid puts it rather close to the edge (or edges) of the
# zone, and if the gaps between the window and the zone's edge are empty, adjust the size
# of the window to fill the gap (this prevents small areas of the zone from always being
# empty: makes the desktop look nice). If the maximum allowable gap size is 0, don't fill
# gaps at all
if ($axmud::CLIENT->gridGapMaxSize) {
($xPosBlocks, $yPosBlocks, $widthBlocks, $heightBlocks)
= $zoneObj->adjustSingleWin(
$layer,
$xPosBlocks,
$yPosBlocks,
$widthBlocks,
$heightBlocks,
);
}
# There is room for the window in the specified zone, at layer $layer and grid coordinates
# $xPosBlocks, $yPosBlocks
$oldZoneObj = $winObj->areaObj->zoneObj;
if ($oldZoneObj) {
if ($oldZoneObj ne $zoneObj) {
$successFlag = $oldZoneObj->removeArea($winObj->areaObj);
} else {
# The original and destination zones are the same, but the window's old and new size
# and position on the workspace won't necessarily be the same. Don't call
# $oldZoneObj->replaceAreaSpace to reshuffle window positions yet, because that
# will mess up everything
$successFlag = $oldZoneObj->removeArea(
$winObj->areaObj,
TRUE,
);
}
if (! $successFlag) {
return $axmud::CLIENT->writeError(
'Can\'t move the window - attempt to move it from its current zone failed',
$self->_objClass . '->changeWinzone',
);
}
}
# Work out the window object's size and position on the desktop in pixels
$xPosPixels = $self->xPosPixels + (($zoneObj->xPosBlocks + $xPosBlocks) * $blockSize);
$yPosPixels = $self->yPosPixels + (($zoneObj->yPosBlocks + $yPosBlocks) * $blockSize);
$widthPixels = ($widthBlocks * $blockSize);
$heightPixels = ($heightBlocks * $blockSize);
# Correct for small gaps in the grid and for window controls
($xPosPixels, $yPosPixels, $widthPixels, $heightPixels) = $self->fineTuneWinSize(
$winObj->winType,
$xPosPixels,
$yPosPixels,
$widthPixels,
$heightPixels,
);
# Mark the window as added to the new zone
$areaObj = $zoneObj->addArea(
$layer,
$xPosBlocks,
$yPosBlocks,
$widthBlocks,
$heightBlocks,
$xPosPixels,
$yPosPixels,
$widthPixels,
$heightPixels,
$winObj->session,
);
if (! $areaObj) {
return $axmud::CLIENT->writeError(
'Can\'t move the window - attempt to move it to its new zone failed',
$self->_objClass . '->changeWinzone',
);
}
# Update the window object's own IVs
$winObj->set_workspaceGridObj($self);
$winObj->set_workspaceObj($self->workspaceObj);
$winObj->set_areaObj($areaObj);
# If the new zone is different from the old one, update the workspace grid object's IVs too
if ($oldZoneObj && $oldZoneObj->workspaceGridObj ne $zoneObj->workspaceGridObj) {
$oldZoneObj->workspaceGridObj->ivDelete('gridWinHash', $winObj->number);
$zoneObj->workspaceGridObj->add_gridWin($winObj);
}
# Resize the window and move it to the correct location
$self->workspaceObj->moveResizeWin(
$winObj,
$xPosPixels,
$yPosPixels,
$widthPixels,
$heightPixels,
);
# Reshuffle the positions of all windows in the zone, if necessary, in order to fill smaller
# gaps to fill up the zone, or expand larger ones to make room for another window
# If the global flag isn't set allowing these adjustments, or if the zone has a maximum of
( run in 1.262 second using v1.01-cache-2.11-cpan-f56aa216473 )