Prima

 view release on metacpan or  search on metacpan

Prima/MDI.pm  view on Meta::CPAN

use constant All        => bi::All | Close;

package Prima::MDI;
use vars qw(@ISA);
@ISA = qw(Prima::Widget);

use Prima::StdBitmap;

{
my %RNT = (
	%{Prima::Widget-> notification_types()},
	Activate      => nt::Default,
	Deactivate    => nt::Default,
	WindowState   => nt::Default,
);

sub notification_types { return \%RNT; }
}

use constant cMIN        => 0;
use constant cMAX        => 1;
use constant cCLOSE      => 2;
use constant cRESTORE    => 3;
use constant pMIN        => 4;
use constant pMAX        => 5;
use constant pCLOSE      => 6;
use constant pRESTORE    => 7;


sub profile_default
{
	my $def = $_[ 0]-> SUPER::profile_default;
	my %prf = (
		width                 => 150,
		heigth                => 150,
		selectable            => 1,
		borderIcons           => mbi::All,
		borderStyle           => bs::Sizeable,
		font                  => Prima::Application-> get_caption_font,
		selectingButtons      => 0,
		icon                  => 0,
		iconMin               => Prima::StdBitmap::image( sbmp::Min),
		iconMax               => Prima::StdBitmap::image( sbmp::Max),
		iconClose             => Prima::StdBitmap::image( sbmp::Close),
		iconRestore           => Prima::StdBitmap::image( sbmp::Restore),
		iconMinPressed        => Prima::StdBitmap::image( sbmp::MinPressed),
		iconMaxPressed        => Prima::StdBitmap::image( sbmp::MaxPressed),
		iconClosePressed      => Prima::StdBitmap::image( sbmp::ClosePressed),
		iconRestorePressed    => Prima::StdBitmap::image( sbmp::RestorePressed),
		ownerFont             => 0,
		dragMode              => undef,
		tabStop               => 0,
		tileable              => 1,
		titleHeight           => 0, # use system-default
		transparent           => 0,
		widgetClass           => wc::Window,
		windowState           => ws::Normal,
		clientClass           => 'Prima::Widget',
		clientProfile         => {},
		firstClick            => 1,
		popupItems            => [
			[ restore => '~Restore'  => 'Ctrl+F5' => '^F5' => q(restore)],
			[ min     => 'Mi~nimize' => q(minimize)],
			[ max     => 'Ma~ximize' => 'Ctrl+F10' => '^F10' => q(maximize)],
			[ move    => '~Move' => q(keyMove)],
			[ size    => '~Size' => q(keySize)],
			[],
			[ close   => '~Close' => 'Ctrl+F4' => '^F4' => sub { $_[0]-> close; } ],
		],
	);
	@$def{keys %prf} = values %prf;
	return $def;
}

sub init
{
	my $self = shift;
	for ( qw( borderStyle borderIcons icon windowState))
		{ $self-> {$_} = -1; }
	for ( qw( pressState iconsAtRight border tileable titleHeight titleY))
		{ $self-> {$_} = 0; }
	my %profile = $self-> SUPER::init(@_);
	$self-> {zoomGrowMode} = $profile{growMode};
	for ( qw( titleHeight borderStyle borderIcons icon tileable windowState dragMode
		iconMin iconMax iconClose iconRestore iconMinPressed iconMaxPressed
		iconClosePressed iconRestorePressed
		))
		{ $self-> $_( $profile{ $_}); }
	$self-> {zoomRect} = [ $self-> rect];
	$self-> {miniRect} = [ 0, 0, $self-> sizeMin];
	$self-> popup-> autoPopup(0) if $self-> popup;
	$self-> {client} = $self-> insert( $profile{clientClass},
		rect         => [ $self-> get_client_rect],
		growMode     => gm::Client,
		pointerType  => cr::Arrow,
		name         => 'MDIClient',
		delegations  => ['Destroy'],
		%{$profile{clientProfile}},
	);
	$self-> update_popup_commands;
	return %profile;
}

sub on_paint
{
	my ( $self, $canvas) = @_;
	my @cl  = ( $self-> color, $self-> backColor);
	my @c3d   = ( $self-> light3DColor, $self-> dark3DColor);
	my @size  = $canvas-> size;
	my @csize = @size;
	my $dy    = $self-> {titleY};
	my ( $bs, $bi, $bb, $bp) =
		( $self-> {borderStyle}, $self-> {borderIcons},$self-> {border},$self-> {pressState});
	my @ct = ($self-> hiliteColor, $self-> hiliteBackColor);

	$bi = 0 unless $bi & mbi::TitleBar;

	$canvas-> rect3d( 0, 0, $size[0]-1, $size[1]-1, 1, $c3d[1], cl::Black) if $bb > 0;
	$canvas-> rect3d( 1, 1, $size[0]-2, $size[1]-2, 1, $c3d[0], $c3d[1]) if $bb > 1;
	$canvas-> rect3d( 2, 2, $size[0]-3, $size[1]-3, $bb - 2,
		cl::Back|wc::Window, cl::Back|wc::Window) if $bb > 2;

	$csize[0] -= $bb * 2;
	$csize[1] -= $bb * 2;
	$csize[1] -= $dy if $bi & mbi::TitleBar;

	my $ico = $self-> {icon} ?
		$self-> {icon} :
		Prima::StdBitmap::image( sbmp::SysMenu);

	my $dicon = 4;
	my $icos = $self-> { iconsAtRight};

	my $tyStart = $size[1] - $bb - $dy;

	if ( $bi & mbi::TitleBar) {
		my $xAt  = $bb + 4;
		$xAt += $dy if $bi & mbi::SystemMenu;
		my $tx = $self-> text;
		my $w  = $size[0] - $bb - $icos * $dy - 1 - $xAt;
		if ( $canvas-> get_text_width( $tx) > $w) {
			$w -= $canvas-> get_text_width( '...');
			$tx = $canvas-> text_wrap( $tx, $w, 0)-> [0].'...';
		}

		my $dbmw =  $size[0] - $bb * 2 - $icos * $dy;
		if ( $dbmw > 0 && $dy > 0) {
			my $dbm = Prima::DeviceBitmap-> create(
				width  => $dbmw,
				height => $dy,
				font   => $canvas-> font,
			);
			my $x = $canvas-> font;
			$dbm-> color( $ct[1]);
			$dbm-> bar( 0, 0, $dbm-> size);
			$dbm-> color( $ct[0]);
			$dbm-> text_shape_out( $tx, $xAt, ( $dy - $canvas-> font-> height) / 2);
			$dbm-> stretch_image( 0, 0, $dy, $dy, $ico) if $bi & mbi::SystemMenu;
			$canvas-> put_image( $bb, $tyStart, $dbm);
			$dbm-> destroy;

Prima/MDI.pm  view on Meta::CPAN

	$self-> check_drag;

	unless ($self-> {fullDrag}) {
		$self-> {prevRect} = [$self-> client_to_screen(0,0,$self-> size)];
		$self-> xorrect($self-> client_to_screen(0,0,$self-> size));
	};
}


sub on_postmessage
{
	my ( $self, $cm, $cm2) = @_;
	return if $cm ne q(cmMDI);

	if ( $cm2 eq q(min)) {
		$self-> windowState( ws::Minimized);
	} elsif ( $cm2 eq q(max)) {
		$self-> windowState( ws::Maximized);
	} elsif ( $cm2 eq q(restore)) {
		$self-> windowState( ws::Normal);
	} elsif ( $cm2 eq q(close)) {
		$self-> close;
	}
}

sub xorrect
{
	my ( $self, @r) = @_;
	if ( @r ) {
		$r[2]--;
		$r[3]--;
	}
	my $o = $::application;
	my $oo = $self-> clipOwner ? $self-> owner : $::application;
	$o-> clipRect( $oo-> client_to_screen( 0,0,$oo-> size));
	$o-> rubberband( @r ? (
			rect    => \@r,
			breadth => $self-> {border}
		) : (
			destroy => 1
		)
	);
}

sub on_mousedown
{
	my ( $self, $btn, $mod, $x, $y) = @_;
	$self-> clear_event;
	return if $self-> {mouseTransaction};

	my $part = $self-> xy2part( $x, $y);
	$self-> bring_to_front;
	$self-> select;
	return if
		$part eq q(client) or
		$part eq q(border) or
		$btn != mb::Left;

	if ( $part eq q(menu)) {
		# Win32 test results - we won't get on_click( double=1) after 'cancelling'
		# on_mousedown with popup - the system says it's no more a double click,
		# just a single click to popup. Moreover, in general this is correct. We could
		# catch second on_mousedown in system-defined timeout interval, but
		# this popup-canceling on_mousedown won't come to us either.
		my $delay = Prima::Application-> get_system_value( sv::DblClickDelay);
		$delay = 250 if $delay > 250;
		$self-> {exTimer} = Prima::Timer-> create(
			owner   => $self,
			timeout => $delay,
			onTick  => sub {
				my $self = $_[0]-> owner;
				$_[0]-> destroy;
				delete $self-> {exTimer};
				return unless $self-> alive || ! defined ( $self-> popup);

				my ( $w, $y, $bw)  = ( $self-> height, $self-> {titleY}, $self-> {border});
				$self-> popup-> popup(
					$bw, $w - $y - $bw,
					$bw, $w - $y - $bw, $bw + $y, $w - $bw
				);
			},
		);
		$self-> {exTimer}-> start;
		return;
	}

	if ( $part eq q(caption)) {
		$self-> {mouseTransaction} = $part;
		$self-> {spotX} = $x;
		$self-> {spotY} = $y;
		$self-> {trackSaveData} = [$self-> origin];
		$self-> capture(1, $self-> clipOwner ? $self-> owner : ());
		$self-> check_drag;
		unless ($self-> {fullDrag}) {
			$self-> {prevRect} = [$self-> client_to_screen(0,0,$self-> size)];
			$self-> xorrect($self-> client_to_screen(0,0,$self-> size));
		};
		return;
	}

	if ( $part =~ /Size/) {
		$self-> {mouseTransaction} = $part;
		$self-> {mouseTransactionArea} = 'size';
		$self-> {spotX} = $x;
		$self-> {spotY} = $y;
		$self-> {trackSaveData} = [$self-> rect];
		$part =~ s/Size//;
		my ( $xa, $ya);

		if    ( $part eq q(S))   { ( $xa, $ya) = ( 0,-1); }
		elsif ( $part eq q(N))   { ( $xa, $ya) = ( 0, 1); }
		elsif ( $part eq q(W))   { ( $xa, $ya) = (-1, 0); }
		elsif ( $part eq q(E))   { ( $xa, $ya) = ( 1, 0); }
		elsif ( $part eq q(SW)) { ( $xa, $ya) = (-1,-1); }
		elsif ( $part eq q(NE)) { ( $xa, $ya) = ( 1, 1); }
		elsif ( $part eq q(NW)) { ( $xa, $ya) = (-1, 1); }
		elsif ( $part eq q(SE)) { ( $xa, $ya) = ( 1,-1); }

		$self-> {dirData} = [$xa, $ya];
		$self-> capture(1, $self-> clipOwner ? $self-> owner : ());
		$self-> check_drag;

		unless ($self-> {fullDrag}) {
			$self-> {prevRect} = [$self-> client_to_screen(0,0,$self-> size)];
			$self-> xorrect($self-> client_to_screen(0,0,$self-> size));
		};
		return;
	}

	$self-> {mouseTransaction} = $part;
	$self-> {mouseTransactionArea} = 'right';
	$self-> {pressState} = 0 |
		( $part eq q(min)     ? mbi::Minimize : 0)  |
		( $part eq q(max)     ? mbi::Maximize : 0)  |
		( $part eq q(close)   ? mbi::Close    : 0)|
		( $part eq q(restore) ? (
			($self-> {windowState} == ws::Minimized) ? mbi::Minimize : mbi::Maximize
		) : 0)
	;
	$self-> {lastMouseOver} = 1;
	$self-> repaint_title(q(right));
	$self-> capture(1, $self-> clipOwner ? $self-> owner : ());
}

sub on_mouseclick
{
	my ( $self, $btn, $mod, $x, $y, $dbl) = @_;
	$self-> clear_event;
	return if $self-> {mouseTransaction} or !$dbl;
	my $part = $self-> xy2part( $x, $y);

	if ( $part eq q(caption)) {
		$self-> post_action(( $self-> {windowState} == ws::Normal) ? q(max) : q(restore));
		return;
	}

	if ( $part eq q(title)) {
		$self-> post_action( q(restore));
		return;
	}

	if ( $part eq q(menu)) {
		if ( $self-> {exTimer}) {
			$self-> {exTimer}-> destroy;
			delete $self-> {exTimer};
		}
		$self-> post_action(q(close));
		return;
	}
}

sub on_translateaccel
{
	my ( $self, $code, $key, $mod) = @_;
	if ( !$self-> {mouseTransaction}) {
		if (( $key == kb::Tab || $key == kb::BackTab) && ( $mod & km::Ctrl)) {
			my $back = ($key == kb::BackTab);
			my $x = $self-> first;
			my @mdis = ( $x );
			push @mdis, $x while $x = $x-> next;
			@mdis = grep { $_-> isa('Prima::MDI') } @mdis;
			$x = $mdis[ $back ? 1 : -1];
			if ( $x) {
				$back ? $mdis[0]-> send_to_back : $x-> bring_to_front;
				$x-> select;
			}
			$self-> clear_event;
		} if (
			( $key == kb::Space) &&
			( $mod & km::Ctrl) &&
			( $self-> { borderIcons} & mbi::SystemMenu)
		) {
			my ( $w, $y, $bw)  = ( $self-> height, $self-> {titleY}, $self-> {border});
			$self-> popup-> popup(
				$bw, $w - $y - $bw,
				$bw, $w - $y - $bw, $bw + $y, $w - $bw
			);
			$self-> clear_event;
		}
	}
}

sub on_keydown
{
	my ( $self, $code, $key, $mod) = @_;

	if ( $self-> {mouseTransaction} and ( $key == kb::Esc)) {
		$self-> sizemove_cancel;
		$self-> clear_event;
		return;
	}

	return unless $self-> {mouseTransaction};

	if ( $self-> {mouseTransaction} eq q(keyMove)) {
		my ( $dx, $dy) = (0,0);

		if
		( $key == kb::Down)  { $dy -= 5; } elsif
		( $key == kb::Up)    { $dy += 5; } elsif
		( $key == kb::Left)  { $dx -= 5; } elsif
		( $key == kb::Right) { $dx += 5; } elsif
		( $key == kb::Enter) {
			$self-> pointer( cr::Default);
			$self-> capture(0);
			$self-> clear_event;
			unless ( $self-> {fullDrag}) {
				$self-> xorrect;
				my $oo = $self-> clipOwner ? $self-> owner : $::application;
				$self-> origin(
					$oo-> screen_to_client(@{$self-> {prevRect}}[0,1])
				);
			}
			$self-> {mouseTransaction} =
				$self-> {mouseTransactionArea} =
				$self-> {dirData} =
				$self-> {spotX} =
				$self-> {spotY} = undef;
			return;
		}

		if ( $dx or $dy) {
			my @p = $self-> pointerPos;
			my @o = $self-> origin;
			$self-> pointerPos( $p[0] + $dx, $p[1] + $dy);
			$self-> clear_event;
			if ( $self-> {fullDrag}) {
				$self-> origin( $o[0] + $dx, $o[1] + $dy);
			} else {
				${$self-> {prevRect}}[0] += $dx;
				${$self-> {prevRect}}[1] += $dy;
				${$self-> {prevRect}}[2] += $dx;
				${$self-> {prevRect}}[3] += $dy;
				$self-> xorrect( @{$self-> {prevRect}});

Prima/MDI.pm  view on Meta::CPAN

				if ( $self-> {fullDrag}) {
					$self-> rect( @new)
				} else {
					my $oo = $self-> clipOwner ? $self-> owner : $::application;
					$self-> {prevRect} = [$oo-> client_to_screen( @new)];
					$self-> xorrect( @{$self-> {prevRect}});
				}
			}
			return;
		}
	} else {
		if (
			$self-> {borderStyle} == bs::Sizeable and
			$self-> {windowState} == ws::Normal
		) {
			return if !$self-> enabled;
			my $part = $self-> xy2part( $x, $y);
			$self-> pointer( $part =~ /^Size/ ? &{$cr::{$part}} : cr::Arrow);
		} else {
			$self-> pointer( cr::Arrow);
		}
	}
}

sub on_enable { $_[0]-> repaint; }
sub on_disable { $_[0]-> repaint; }

sub set_text
{
	$_[0]-> SUPER::set_text( $_[1]);
	$_[0]-> repaint_title(q(title));
}

sub update_size_min
{
	my $self = $_[0];
	my @a = Prima::Application-> get_default_window_borders( $self-> {borderStyle});
	my $ic = $self-> { iconsAtRight} +
		1 +
		(($self-> {borderIcons} & mbi::SystemMenu) ? 1 : 0);
	$self-> sizeMin(
		$self-> {titleY} * $ic + $a[0] * 2,
		$self-> {titleY} + $a[1] * 2
	);
}

sub set_border_icons
{
	my ( $self, $bi) = @_;
	$bi &= mbi::All;
	return if $bi == $self-> {borderIcons};
	$self-> {borderIcons} = $bi;

	my $icos = 0;
	$icos++ if $bi & mbi::Minimize;
	$icos++ if $bi & mbi::Maximize;
	$icos++ if $bi & mbi::Close;

	$self-> { iconsAtRight} = $icos;

	$self-> update_popup_commands;
	$self-> update_size_min;
	$self-> sync_client;
	$self-> repaint;
}

sub set_border_style
{
	my ( $self, $bs) = @_;
	return if $bs == $self-> {borderStyle} or $bs < bs::None or $bs > bs::Dialog;

	$self-> {borderStyle} = $bs;
	my ( $bbx, $bby) = Prima::Application-> get_default_window_borders( $bs);
	$bbx = $bbx > 1 ? $bbx : (( $bbx > 0) ? 1 : 0);
	$bby = $bby > 1 ? $bby : (( $bby > 0) ? 1 : 0);
	$self-> {border} = $bbx > $bby ? $bby : $bbx;

	$self-> update_popup_commands;
	$self-> update_size_min;
	$self-> sync_client;
	$self-> repaint;
}

sub update_popup_commands
{
	my $self = $_[0];
	my $popup = $self-> popup;

	my ( $bi, $bs, $ws) = ( $self-> {borderIcons}, $self-> {borderStyle}, $self-> {windowState});

	$popup-> max-> enabled(( $bi & mbi::Maximize) && ( $ws != ws::Maximized));
	$popup-> min-> enabled(( $bi & mbi::Minimize) && ( $ws != ws::Minimized));
	$popup-> restore-> enabled(( $bi & (mbi::Minimize|mbi::Maximize)) && ( $ws != ws::Normal));
	$popup-> move-> enabled( $ws == ws::Normal);
	$popup-> size-> enabled(( $ws == ws::Normal) && ( $bs == bs::Sizeable));
}

sub set_window_state
{
	my ( $self, $ws) = @_;
	return if $ws == $self-> {windowState} or $ws < ws::Normal or $ws > ws::Maximized;
	my $ows = $self-> {windowState};

	my $popup = $self-> popup;
	if ( $ws == ws::Minimized) {
		return unless $self-> {borderIcons} & mbi::Minimize;
		$self-> {zoomRect} = [ $self-> rect] if $ows == ws::Normal;
		$self-> growMode( $self-> {zoomGrowMode}) if $ows == ws::Maximized;
		my @szMin = $self-> sizeMin;
		my ($x, $y) = ( $self-> {miniRect}-> [0], $self-> {miniRect}-> [1]);
		$self-> clipOwner(1) unless ($self-> {saveClipOwner} = $self-> clipOwner);

		# start calculating position for min-widnow
		my @sz = $self-> clipOwner ? $self-> owner-> size : $::application-> size;
		$x = $sz[0] - $szMin[0] if $x > $sz[0] - $szMin[0];
		$y = $sz[1] - $szMin[1] if $y > $sz[1] - $szMin[1];

		my @mdis = grep {
			(( $_ ne $self) and ( $_-> windowState == ws::Minimized)) ?
				$_ :
				0
		} $self-> mdis;

		my @maps;
		my @szmaxids = ( int($sz[0] / $szMin[0]), int($sz[1] / $szMin[1]));
		$szmaxids[0] = 1 unless $szmaxids[0];
		$szmaxids[1] = 1 unless $szmaxids[1];

		for ( @mdis) {
			my ( $ax, $ay) = ( $_-> left / $szMin[0], $_-> bottom / $szMin[1]);
			my $id = int( $ay) * $szmaxids[0] + int( $ax);
			push ( @maps, $id);
			push ( @maps, $id + 1) if $ax > int( $ax);
			push ( @maps, $id + $szmaxids[0]) if $ay > int( $ay);
			push ( @maps, $id + $szmaxids[0] + 1) if $ay > int( $ay) and $ax > int( $ax);
		}

		my $id = int( $y / $szMin[1]) * $szmaxids[0] + int( $x / $szMin[0]);
		if ( scalar grep { $_ == $id ? 1 : 0} @maps) {
			my $i;
			my %hh = map {$_=>1} @maps;
			@maps = sort { $a <=> $b} keys %hh;
			my $newID = scalar @maps;
			for ( $i = 0; $i < scalar @maps; $i++) {
				$newID = $i, last if $i != $maps[ $i];
			}
			$x = ( $newID % $szmaxids[0]) * $szMin[0];
			$y = int ( $newID / $szmaxids[0]) * $szMin[1];
		}
		# end calculating position for min-widnow

		($self-> {miniRect}-> [0], $self-> {miniRect}-> [1]) = ( $x, $y);
		$self-> {miniRect}-> [2] = $self-> {miniRect}-> [0] + $szMin[0];
		$self-> {miniRect}-> [3] = $self-> {miniRect}-> [1] + $szMin[1];
		$self-> rect( @{$self-> {miniRect}});

		$popup-> enable( $_)  for ( qw( max restore move));
		$popup-> disable( $_) for ( qw( min size));
	} elsif ( $ws == ws::Maximized) {
		return unless $self-> {borderIcons} & mbi::Maximize;

		$self-> clipOwner(0)
			if $ows == ws::Minimized && !$self-> {saveClipOwner};
		delete $self-> {saveClipOwner};

		$self-> {miniRect} = [ $self-> rect] if $ows == ws::Minimized;
		$self-> {zoomRect} = [ $self-> rect] if $ows == ws::Normal;
		$self-> rect( 0, 0, $self-> clipOwner ? $self-> owner-> size : $::application-> size);
		$self-> {zoomGrowMode} = $self-> growMode;
		$self-> growMode( gm::Client);

		$popup-> enable( $_)  for ( qw( min restore));
		$popup-> disable( $_) for ( qw( max move size));
	} else {
		$self-> {windowState} = ws::Normal;
		return unless $self-> {borderIcons} & (mbi::Maximize|mbi::Minimize);

		$self-> clipOwner(0)
			if $ows == ws::Minimized && !$self-> {saveClipOwner};

		delete $self-> {saveClipOwner};
		$self-> {miniRect} = [ $self-> rect] if $ows == ws::Minimized;
		$self-> growMode( $self-> {zoomGrowMode}) if $ows == ws::Maximized;
		$self-> rect( @{$self-> {zoomRect}});
		$popup-> enable( $_)  for ( qw( max min move size));
		$popup-> disable( $_) for ( qw( restore));
	}
	$self-> {windowState} = $ws;
	$self-> update_popup_commands;
	$self-> notify(q(WindowState));
}


sub set_icon
{
	my ( $self, $icon) = @_;
	$self-> {icon} = $icon;
	$self-> repaint_title(q('left'));
}

sub on_windowstate
{
#	my $self = $_[0];
}

sub on_activate
{
#	my $self = $_[0];
}

sub on_deactivate
{
#	my $self = $_[0];
}

sub MDIClient_Destroy
{
	$_[0]-> destroy;
}

sub titleHeight
{
	return $_[0]-> {titleHeight} unless $#_;
	my ( $self, $th) = @_;
	$self-> {titleHeight} = $th;
	$th = Prima::Application-> get_system_value( sv::YTitleBar) unless $th;
	return if $self-> {titleY} == $th;
	$self-> {titleY} = $th;
	$self-> sync_client;
	$self-> repaint;
}

sub __icon
{
	my ( $self, $id) = ( shift, shift);
	return $self-> {icons}-> [$id] unless @_;
	$self-> {icons}-> [$id] = shift;
	$self-> repaint_title;
}

sub iconMin            { return shift-> __icon( cMIN,     @_)};
sub iconMax            { return shift-> __icon( cMAX,     @_)};
sub iconClose          { return shift-> __icon( cCLOSE,   @_)};
sub iconRestore        { return shift-> __icon( cRESTORE, @_)};
sub iconMinPressed     { return shift-> __icon( pMIN,     @_)};
sub iconMaxPressed     { return shift-> __icon( pMAX,     @_)};
sub iconClosePressed   { return shift-> __icon( pCLOSE,   @_)};
sub iconRestorePressed { return shift-> __icon( pRESTORE, @_)};

Prima/MDI.pm  view on Meta::CPAN

sub borderStyle {($#_)?$_[0]-> set_border_style($_[1])   :return $_[0]-> {borderStyle}}
sub dragMode    {($#_)?($_[0]-> {dragMode} = $_[1])      :return $_[0]-> {dragMode}   }
sub frameOrigin {return shift-> origin( @_);}
sub frameSize   {return shift-> size( @_);}
sub frameWidth  {return shift-> width( @_);}
sub frameHeight {return shift-> height( @_);}
sub tileable    {($#_)?$_[0]-> {tileable}=$_[1]          :return $_[0]-> {tileable}   }
sub windowState {($#_)?$_[0]-> set_window_state($_[1])   :return $_[0]-> {windowState}}
sub icon        {($#_)?$_[0]-> set_icon        ($_[1])   :return $_[0]-> {icon}       }

1;

=pod

=head1 NAME

Prima::MDI - top-level windows emulation classes

=head1 DESCRIPTION

MDI stands for Multiple Document Interface, and is a Microsoft Windows user
interface, that consists of multiple non-toplevel windows belonging to an
application window. The module contains classes that provide similar
functionality; sub-window widgets realize a set of operations, close to those
of the real top-level windows, - iconize, maximize, cascade etc.

The basic classes required to use the MDI are C<Prima::MDIOwner> and
C<Prima::MDI>, which are, correspondingly, sub-window owner class and
sub-window class. C<Prima::MDIWindowOwner> is exactly the same as
C<Prima::MDIOwner> but is a C<Prima::Window> descendant: the both owner classes
are different only in their first ascendants. Their second ascendant is
C<Prima::MDIMethods> package, that contains all the owner class functionality.

Usage of C<Prima::MDI> class extends beyond the multi-document paradigm.
C<Prima::DockManager> module uses the class as a base of a dockable toolbar
window class ( see L<Prima::DockManager>.

=head1 SYNOPSIS

	use Prima qw(Application MDI Buttons);

	my $owner = Prima::MDIWindowOwner-> new;
	my $mdi   = $owner-> insert( 'Prima::MDI');
	$mdi-> client-> insert( 'Prima::Button' => centered => 1 );

	run Prima;

=for podview <img src="mdi.gif">

=for html <p><img src="https://raw.githubusercontent.com/dk/Prima/master/pod/Prima/mdi.gif">


=head1 Prima::MDI

Implements MDI window functionality. A subwindow widget consists of a titlebar,
titlebar buttons, and a client widget. The latter must be used as an insertion
target for all children widgets.

A subwindow can be moved and resized, both by mouse and keyboard.  These
functions, along with maximize, minimize, and restore commands are accessible
via the toolbar-anchored popup menu. The default set of commands is as follows:

	Close window              - Ctrl+F4
	Restore window            - Ctrl+F5 or a double click on the titlebar
	Maximize window           - Ctrl+F10 or a double click on the titlebar
	Go to next MDI window     - Ctrl+Tab
	Go to previous MDI window - Ctrl+Shift+Tab
	Invoke popup menu         - Ctrl+Space

The class mimics API of C<Prima::Window> class, and in some extent
L<Prima::Window> and this page share the same information.

=head2 Properties

=over

=item borderIcons INTEGER

Selects window decorations, which are buttons on titlebar and the titlebar itself.
Can be 0 or a combination of the following C<mbi::XXX> constants, which are supreset
of C<bi::XXX> constants ( see L<Prima::Window/borderIcons> ) and are interchangeable.

	mbi::SystemMenu  - system menu button with icon is shown
	mbi::Minimize    - minimize button
	mbi::Maximize    - maximize ( and eventual restore )
	mbi::TitleBar    - window title
	mbi::Close       - close button
	mbi::All         - all of the above

Default value: C<mbi::All>

=item borderStyle INTEGER

One of C<bs::XXX> constants, selecting the window border style.
The constants are:

	bs::None      - no border
	bs::Single    - thin border
	bs::Dialog    - thick border
	bs::Sizeable  - thick border with interactive resize capabilities

C<bs::Sizeable> is an unique mode. If selected, the user
can resize the window interactively. The other border styles
disallow resizing and affect the border width and design only.

Default value: C<bs::Sizeable>

=item client OBJECT

Selects the client widget at runtime. When changing the client, the old client
children are not reparented to the new client. The property cannot be used to
set the client during the MDI window creation; use
C<clientClass> and C<clientProfile> properties instead.

When setting new client object, note that is has to be named C<MDIClient>
and the window is automatically destroyed after the client is destroyed.

=item clientClass STRING

Assigns client widget class.

Create-only property.

Default value: C<Prima::Widget>

=item clientProfile HASH

Assigns hash of properties, passed to the client during the creation.



( run in 1.463 second using v1.01-cache-2.11-cpan-364913b4093 )