The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

use strict;
use warnings;

use Prima::Const;
use Prima::Classes;
use Prima::IntUtils;

################################################################################

package Prima::CodeManager::TabSet;

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

{
my %RNT = (
	%{Prima::Widget-> notification_types()},
	DrawTab     => nt::Action,
	MeasureTab  => nt::Action,
);

sub notification_types { return \%RNT; }
}

use constant DefBorderX		=>	10;
use constant DefDeltaX		=>	 3;
use constant DefDeltaY		=>	 3;
use constant DefBookmarkX	=>	30;
use constant DefTabMultiply	=>	1.4;

#my @warpColors = ( 0x50d8f8, 0x80d8a8, 0x8090f8, 0xd0b4a8, 0xf8fca8, 0xa890a8, 0xf89050, 0xf8d850, 0xf8b4a8, 0xf8d8a8, );

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

sub profile_default
{
	my $def = $_[ 0]-> SUPER::profile_default;
	my $font = $_[ 0]-> get_default_font;

	my %prf = (
		colored          => 1,
		firstTab         => 0,
		focusedTab       => 0,
#		height           => $font-> { height} > 14 ? int (2.0 * $font-> { height}) : 28,
		height           => int ( DefTabMultiply * $_[0]-> font-> height ),
		ownerBackColor   => 1,
		selectable       => 1,
		selectingButtons => 0,
		tabStop          => 1,
		topMost          => 1,
		tabIndex         => 0,
		tabs             => [],
	);
	@$def{keys %prf} = values %prf;
	return $def;
}

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

sub init
{
	my $self = shift;

	$self-> {tabIndex} = -1;
	for ( qw( colored firstTab focusedTab topMost lastTab arrows)) { $self-> {$_} = 0; }
	$self-> {tabs}     = [];
	$self-> {widths}   = [];
	my %profile = $self-> SUPER::init(@_);
	for ( qw( colored topMost tabs focusedTab firstTab tabIndex)) { $self-> $_( $profile{ $_}); }
	$self-> recalc_widths;
	$self-> reset;

	return %profile;
}

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

sub reset
{
	my $self = $_[0];
	my @size = $self-> size;
	my $w = 0;
	for ( @{$self-> {widths}}) { $w += $_; }
	$self-> {arrows} = (( $w > $size[0]) and ( scalar( @{$self-> {widths}}) > 1));
	if ( $self-> {arrows}) {
		my $ft = $self-> {firstTab};
		$w  = 0;
#		$w += DefArrowX if $ft > 0;
		my $w2 = $w;
		my $la = $ft > 0;
		my $i;
		my $ra = 0;
		my $ww = $self-> {widths};
		for ( $i = $ft; $i < scalar @{$ww}; $i++) {
			$w += $$ww[$i];
			if ( $w >= $size[0]) {
				$ra = 1;
				$i-- if

					$i > $ft &&

#					$w - $$ww[$i] >= $size[0] - DefArrowX;
					$w - $$ww[$i] >= $size[0];
				last;
			}
		}
		$i = scalar @{$self-> {widths}} - 1

			if $i >= scalar @{$self-> {widths}};
		$self-> {lastTab} = $i;
		$self-> {arrows} = ( $la ? 1 : 0) | ( $ra ? 2 : 0);
	} else {
		$self-> {lastTab} = scalar @{$self-> {widths}} - 1;
	}
}

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

sub recalc_widths
{
	my $self = $_[0];

	my @w;
	my $i;
	my ( $notifier, @notifyParms) = $self-> get_notify_sub(q(MeasureTab));
	$self-> begin_paint_info;
	$self-> push_event;

	for ( $i = 0; $i < scalar @{$self-> {tabs}}; $i++) {
		my $iw = 0;
		$notifier-> ( @notifyParms, $i, \$iw);
		push ( @w, $iw);
	}

	$self-> pop_event;
	$self-> end_paint_info;
	$self-> {widths}    = [@w];
}

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

sub on_mousedown
{
	my ( $self, $btn, $mod, $x, $y) = @_;
	return if $self-> {mouseTransaction};
	$self-> clear_event;
	my ( $a, $ww, $ft, $lt) = (
		$self-> {arrows}, $self-> {widths}, $self-> {firstTab}, $self-> {lastTab}
	);

	if (( $a & 1) and ( $x < 0 )) {
		$self-> firstTab( $self-> firstTab - 1);
		$self-> capture(1);
		$self-> {mouseTransaction} = -1;
		$self-> scroll_timer_start;
		$self-> scroll_timer_semaphore(0);
		return;
	}

	my @size = $self-> size;
	if (( $a & 2) and ( $x >= $size[0] )) {
		$self-> firstTab( $self-> firstTab + 1);
		$self-> capture(1);
		$self-> {mouseTransaction} = 1;
		$self-> scroll_timer_start;
		$self-> scroll_timer_semaphore(0);
		return;
	}

	my $w = 0;
	my $i;
	my $found = undef;
	for ( $i = $ft; $i <= $lt; $i++) {
		$found = $i, last if $x < $w + $$ww[$i];
		$w += $$ww[$i];
	}
	return unless defined $found;

	if ( $found == $self-> {tabIndex}) {
		$self-> focusedTab( $found);
		$self-> focus;
	} else {
		$self-> tabIndex( $found);
	}
}

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

sub on_mousewheel
{
	my ( $self, $mod, $x, $y, $z) = @_;
	$self-> tabIndex( $self-> tabIndex + (( $z < 0) ? -1 : 1));
	$self-> clear_event;
}

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

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

	$self-> capture(0);
	$self-> scroll_timer_stop;
	$self-> {mouseTransaction} = undef;
}

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

sub on_mousemove
{
	my ( $self, $mod, $x, $y) = @_;
	return unless $self-> {mouseTransaction};
	return unless $self-> scroll_timer_semaphore;

	$self-> scroll_timer_semaphore(0);
	my $ft = $self-> firstTab;
	$self-> firstTab( $ft + $self-> {mouseTransaction});
	$self-> notify(q(MouseUp),1,0,0,0) if $ft == $self-> firstTab;
}

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

sub on_mouseclick
{
	my $self = shift;
	$self-> clear_event;
	return unless pop;

	$self-> clear_event unless $self-> notify( "MouseDown", @_);
}

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

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

	if ( $key == kb::Left || $key == kb::Right) {
		$self-> focusedTab( $self-> focusedTab + (( $key == kb::Left) ? -1 : 1));
		$self-> clear_event;
		return;
	}

	if ( $key == kb::PgUp || $key == kb::PgDn) {
		$self-> tabIndex( $self-> tabIndex + (( $key == kb::PgUp) ? -1 : 1));
		$self-> clear_event;
		return;
	}

	if ( $key == kb::Home || $key == kb::End) {
		$self-> tabIndex(( $key == kb::Home) ? 0 : scalar @{$self-> {tabs}});
		$self-> clear_event;
		return;
	}
	if ( $key == kb::Space || $key == kb::Enter) {
		$self-> tabIndex( $self-> focusedTab);
		$self-> clear_event;
		return;
	}
}

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

sub on_paint
{
	my ($self,$canvas) = @_;

	my $DefBorderX	=	DefBorderX - DefDeltaX;

	my @clr  = ( $self-> color, $self-> backColor);
	   @clr  = ( $self-> disabledColor, $self-> disabledBackColor) if ( !$self-> enabled);
	my @c3d  = ( $self-> dark3DColor, $self-> light3DColor);
	my @size = $canvas-> size;

	$canvas-> color( $clr[1]);
	$canvas-> bar( 0, 0, @size );

	my ( $ft, $lt, $a, $ti, $ww, $tm) =
		( $self-> {firstTab}, $self-> {lastTab}, $self-> {arrows}, $self-> {tabIndex},
		$self-> {widths}, $self-> {topMost}
	);
	my ( $notifier, @notifyParms) = $self-> get_notify_sub(q(DrawTab));
	$self-> push_event;

	my $atX = 0;
	my $atXti = undef;
	my $i;
	for ( $i = $ft; $i <= $lt; $i++) {
		$atX += $$ww[$i];
	}

#	$canvas-> clipRect( 0, 0, $size[0], $size[1]) if $a & 2;

# zwykle - niezaznaczone taby:
	my @colorSet = ( @clr, @c3d);
	for ( $i = $lt; $i >= $ft; $i--) {
		$atX -= $$ww[$i];
		$atXti = $atX, next if $i == $ti;

		my @poly = (
			$atX + DefBorderX,								$size[1] - 1 - int (DefTabMultiply * $self-> font-> height),

			$atX + DefBorderX,								$size[1] - 1,
			$atX + DefBorderX + $$ww[$i] - 2 * DefDeltaX,	$size[1] - 1,
			$atX + DefBorderX + $$ww[$i] - 2 * DefDeltaX,	$size[1] - 1 - int (DefTabMultiply * $self-> font-> height)
		);
		$notifier-> ( @notifyParms, $canvas, $i, \@colorSet, \@poly);
	}

	my $swapDraw = ( $ti == $lt) && ( $a & 2);

	goto PaintSelTabBefore if $swapDraw;
PaintEarsThen:
	$canvas-> clipRect( 0, 0, @size) if $a & 2;
	if ( $a & 1) {
		my $x = 0;
		my @poly = (
			$x + DefBorderX,	$size[1] - 1 - int (DefTabMultiply * $self-> font-> height),

			$x + DefBorderX, 	$size[1] - 1,
			$x + DefBorderX,	$size[1] - 1,
			$x + DefBorderX,	$size[1] - 1 - int (DefTabMultiply * $self-> font-> height)
		);
		$notifier-> ( @notifyParms, $canvas, -1, \@colorSet, \@poly);
	}
	if ( $a & 2) {
		my $x = $size[0];
		my @poly = (
			$x + DefBorderX,	$size[1] - 1 - int (DefTabMultiply * $self-> font-> height),

			$x + DefBorderX, 	$size[1] - 1,
			$x + DefBorderX,	$size[1] - 1,
			$x + DefBorderX,	$size[1] - 1 - int (DefTabMultiply * $self-> font-> height)
		);
		$notifier-> ( @notifyParms, $canvas, -2, \@colorSet, \@poly);
	}
	$canvas-> color( $c3d[0]);
	$canvas-> line( $size[0] - 1,	0,	$size[0] - 1,	0 );
	$canvas-> line( $size[0] - 1,	0, 	$size[0] - 1,	int (DefTabMultiply * $self-> font-> height) );

	$canvas-> color( $c3d[1]);
	$canvas-> line( 0, int (DefTabMultiply * $self-> font-> height) - 1,	$size[0] - 1,	int (DefTabMultiply * $self-> font-> height) - 1);
	$canvas-> line( 0, int (DefTabMultiply * $self-> font-> height) - 1,	0, 				int (DefTabMultiply * $self-> font-> height) - 1);
	$canvas-> line( 0, 0, 													0,				int (DefTabMultiply * $self-> font-> height) - 1);

#	$canvas-> color( $clr[1]);
#	$canvas-> bar( 1, 0, $size[0] - 2, $self-> font-> height + 2 - 9);

	$canvas-> color( $clr[0]);

	goto EndOfSwappedPaint if $swapDraw;

PaintSelTabBefore:
	if ( defined $atXti) {
		my @poly = (
			$atXti + DefBorderX,								$size[1] - 2 * int (DefTabMultiply * $self-> font-> height),

			$atXti + DefBorderX,								$size[1] - 1,
			$atXti + DefBorderX + $$ww[$ti] - 2 * DefDeltaX, 	$size[1] - 1,
			$atXti + DefBorderX + $$ww[$ti] - 2 * DefDeltaX, 	$size[1] - 2 * int (DefTabMultiply * $self-> font-> height)
		);

		$notifier-> (

			@notifyParms, $canvas, $ti, \@colorSet, \@poly, undef

		);
	}
	goto PaintEarsThen if $swapDraw;

EndOfSwappedPaint:
	$self-> pop_event;
}

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

sub on_size
{
	my ( $self, $ox, $oy, $x, $y) = @_;

	if ( $x > $ox && (( $self-> {arrows} & 2) == 0)) {
		my $w  = 0;
		my $ww = $self-> {widths};
		my $i;
		my $set = 0;

		for ( $i = scalar @{$ww} - 1; $i >= 0; $i--) {
			$w += $$ww[$i];
			$set = 1, $self-> firstTab( $i + 1), last if $w >= $x;
		}
		$self-> firstTab(0) unless $set;
	}
	$self-> reset;
}

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

sub on_fontchanged { $_[0]-> reset; $_[0]-> recalc_widths; }
sub on_enter       { $_[0]-> repaint; }
sub on_leave       { $_[0]-> repaint; }

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

sub on_measuretab
{
	my ( $self, $index, $sref) = @_;

	my $outtext = $self-> {tabs}-> [$index];
	my $star = '';
	$star    = '*' if $outtext =~ /^\*/;
	$outtext =~  s/^.*?([^\\\/]*)$/$1/;
	$outtext = $star.$outtext;

	$$sref = $self-> get_text_width( $outtext) + 4 *( int ( DefTabMultiply * $self-> font-> height ) - $self-> font-> height);
}

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

# see L<DrawTab> below for more info
sub on_drawtab
{
	my ( $self, $canvas, $i, $clr, $poly, $poly2) = @_;

	my $name  = $self-> {tabs}-> [$i];
	$name =~ s/^\*+(.*)$/$1/;

	my $color = $Prima::CodeManager::info_of_files{$name}->{backColor};

	$canvas-> color(( $self-> {colored} && ( $i >= 0)) ? $color : $$clr[1]);
#	$canvas-> color(( $self-> {colored} && ( $i >= 0)) ?
#		( $warpColors[ $i % scalar @warpColors]) : $$clr[1]);

	$canvas-> fillpoly( $poly);
#	$canvas-> fillpoly( $poly2) if $poly2;

	$canvas-> color( $$clr[3]);
	$canvas-> polyline([
		$$poly[0], $$poly[1],
		$$poly[2], $$poly[3],
		$$poly[4], $$poly[5],
	]);

	$canvas-> color( $$clr[2]);
	$canvas-> polyline([
		$$poly[0] + 1,	$$poly[1],
		$$poly[6],		$$poly[7],
		$$poly[4],		$$poly[5],
	]);

	$canvas-> color( $$clr[0]);
	if ( $i >= 0) {

		my  @tx = (
			$$poly[0] + ( $$poly[6] - $$poly[0] - $self-> {widths}-> [$i]) / 2 + 2 * ( int ( DefTabMultiply * $self-> font-> height ) - $self-> font-> height ),
			$$poly[1] + ( $$poly[3] - $$poly[1] - $self-> font-> height ) / 2 + 1
		);
		my $outtext = $self-> {tabs}-> [$i];
		my $star = '';
		$star    = '*' if $outtext =~ /^\*/;
		$outtext =~  s/^.*?([^\\\/]*)$/$1/;
		$outtext = $star.$outtext;
		$canvas-> text_out( $outtext, @tx);
	}
}

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

sub get_item_width
{
	return $_[0]-> {widths}-> [$_[1]];
}

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

sub tab2firstTab
{
	my ( $self, $ti) = @_;
return;#wb
	if (
		( $ti >= $self-> {lastTab}) and

		( $self-> {arrows} & 2) and

		( $ti != $self-> {firstTab})
	) {
		my $w = 0;
#		$w += DefArrowX if $self-> {arrows} & 1;
		my $i;
		my $W = $self-> width;
		my $ww = $self-> {widths};
		my $moreThanOne = ( $ti - $self-> {firstTab}) > 0;

		for ( $i = $self-> {firstTab}; $i <= $ti; $i++) {
			$w += $$ww[$i];
		}

#		my $lim = $W - DefArrowX;
		my $lim = $W;
		if ( $w >= $lim) {
			my $leftw = 0; #DefArrowX;
#			$leftw += DefArrowX if $self-> {arrows} & 1;
			$leftw = $W - $leftw;
			$leftw -= $$ww[$ti] if $moreThanOne;
			$w = 0;
			for ( $i = $ti; $i >= 0; $i--) {
				$w += $$ww[$i];
				last if $w > $leftw;
			}
			return $i + 1;
		}
	} elsif ( $ti < $self-> {firstTab}) {
		return $ti;
	}
	return undef;
}

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

sub set_tab_index
{
	my ( $self, $ti) = @_;

	$ti = 0 if $ti < 0;
	my $mx = scalar @{$self-> {tabs}} - 1;
	$ti = $mx if $ti > $mx;
	return if $ti == $self-> {tabIndex};

	$self-> {tabIndex} = $ti;
	$self-> {focusedTab} = $ti;
	my $newFirstTab = $self-> tab2firstTab( $ti);

	defined $newFirstTab ?
		$self-> firstTab( $newFirstTab) :
		$self-> repaint;
	$self-> notify(q(Change));
}

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

sub set_first_tab
{
	my ( $self, $ft) = @_;
return;#wb
	$ft = 0 if $ft < 0;
	unless ( $self-> {arrows}) {
		$ft = 0;
	} else {
		my $w = 0;
#		$w += DefArrowX if $ft > 0;
		my $haveRight = 0;
		my $i;
		my @size = $self-> size;
		for ( $i = $ft; $i < scalar @{$self-> {widths}}; $i++) {
			$w += $self-> {widths}-> [$i];
			$haveRight = 1, last if $w >= $size[0];
		}
		unless ( $haveRight) {
			$w += 0;
			for ( $i = $ft - 1; $i >= 0; $i--) {
				$w += $self-> {widths}-> [$i];
				if ( $w >= $size[0]) {
					$i++;
					$ft = $i if $ft > $i;
					last;
				}
			}
		}
	}
	return if $self-> {firstTab} == $ft;
	$self-> {firstTab} = $ft;
	$self-> reset;
	$self-> repaint;
}

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

sub set_focused_tab
{
	my ( $self, $ft) = @_;
	$ft = 0 if $ft < 0;
	my $mx = scalar @{$self-> {tabs}} - 1;
	$ft = $mx if $ft > $mx;
	$self-> {focusedTab} = $ft;

	my $newFirstTab = $self-> tab2firstTab( $ft);
	defined $newFirstTab ?
		$self-> firstTab( $newFirstTab) :
		( $self-> focused ? $self-> repaint : 0);
}

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

sub set_tabs
{
	my $self = shift;
	my @tabs = ( scalar @_ == 1 && ref( $_[0]) eq q(ARRAY)) ? @{$_[0]} : @_;
	$self-> {tabs} = \@tabs;
	$self-> recalc_widths;
	$self-> reset;
	$self-> lock;
	$self-> firstTab( $self-> firstTab);
	$self-> tabIndex( $self-> tabIndex);
	$self-> unlock;
	$self-> update_view;
}

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

sub set_top_most
{
	my ( $self, $tm) = @_;
	return if $tm == $self-> {topMost};
	$self-> {topMost} = $tm;
	$self-> repaint;
}

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

sub colored      {($#_)?($_[0]-> {colored}=$_[1],$_[0]-> repaint)        :return $_[0]-> {colored}}
sub focusedTab   {($#_)?($_[0]-> set_focused_tab(    $_[1]))             :return $_[0]-> {focusedTab}}
sub firstTab     {($#_)?($_[0]-> set_first_tab(    $_[1]))               :return $_[0]-> {firstTab}}
sub tabIndex     {($#_)?($_[0]-> set_tab_index(    $_[1]))               :return $_[0]-> {tabIndex}}
sub topMost      {($#_)?($_[0]-> set_top_most (    $_[1]))               :return $_[0]-> {topMost}}
sub tabs         {($#_)?(shift-> set_tabs     (    @_   ))               :return $_[0]-> {tabs}}

################################################################################

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

sub profile_default
{
	my $def = $_[ 0]-> SUPER::profile_default;
	my %prf = (
		defaultInsertPage => undef,
		pageCount         => 0,
		pageIndex         => 0,
		tabStop           => 0,
		ownerBackColor    => 1,
	);
	@$def{keys %prf} = values %prf;
	return $def;
}

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

sub init
{
	my $self = shift;
	$self-> {pageIndex} = -1;
	$self-> {pageCount} = 0;

	my %profile = $self-> SUPER::init(@_);

	$self-> {pageCount} = $profile{pageCount};
	$self-> {pageCount} = 0 if $self-> {pageCount} < 0;
	my $j = $profile{pageCount};
	push (@{$self-> {widgets}},[]) while $j--;
	for ( qw( pageIndex defaultInsertPage)) { $self-> $_( $profile{ $_}); }
	return %profile;
}

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

sub set_page_index
{
	my ( $self, $pi) = @_;
	$pi = 0 if $pi < 0;
	$pi = $self-> {pageCount} - 1 if $pi > $self-> {pageCount} - 1;
	my $sel = $self-> selected;
	return if $pi == $self-> {pageIndex};

	$self-> lock;

	my $cp = $self-> {widgets}-> [$self-> {pageIndex}];
	if ( defined $cp) {
		for ( @$cp) {
			$$_[1] = $$_[0]-> enabled;
			$$_[2] = $$_[0]-> visible;
			$$_[3] = $$_[0]-> current;
			$$_[4] = $$_[0]-> geometry;
			$$_[0]-> visible(0);
			$$_[0]-> enabled(0);
			$$_[0]-> geometry(gt::Default);
		}
	}

	$cp = $self-> {widgets}-> [$pi];
	if ( defined $cp) {
		my $hasSel;
		for ( @$cp) {
			$$_[0]-> geometry($$_[4]);
			$$_[0]-> enabled($$_[1]);
			$$_[0]-> visible($$_[2]);
			if ( !defined $hasSel && $$_[3]) {
				$hasSel = 1;
				$$_[0]-> select if $sel;
			}
			$$_[0]-> current($$_[3]);
		}
	}

	my $i = $self-> {pageIndex};
	$self-> {pageIndex} = $pi;
	$self-> notify(q(Change), $i, $pi);
	$self-> unlock;
	$self-> update_view;
}

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

sub insert_page
{
	my ( $self, $at) = @_;

	$at = -1 unless defined $at;
	$self-> {pageCount} = 0 unless $self-> {pageCount};
	$at = $self-> {pageCount} if $at < 0 || $at > $self-> {pageCount};

	splice( @{$self-> {widgets}}, $at, 0, []);
	$self-> {pageCount}++;
	$self-> pageIndex(0) if $self-> {pageCount} == 1;
}

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

sub delete_page
{
	my ( $self, $at, $removeChildren) = @_;

	$removeChildren = 1 unless defined $removeChildren;
	$at = -1 unless defined $at;
	$at = $self-> {pageCount} - 1 if $at < 0 || $at >= $self-> {pageCount};

	my @r = splice( @{$self-> {widgets}}, $at, 1);

	$self-> {pageCount}--;
	$self-> pageIndex( $self-> pageIndex);

	if ( $removeChildren) {
		$$_[0]-> destroy for @{$r[0]};
	}
}

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

sub attach_to_page
{
	my $self  = shift;
	my $page  = shift;

	$self-> insert_page if $self-> {pageCount} == 0;
	$page = $self-> {pageCount} - 1 if $page > $self-> {pageCount} - 1 || $page < 0;
	my $cp = $self-> {widgets}-> [$page];

	for ( @_) {
		next unless $_-> isa('Prima::Widget');
		# $_->add_notification( Enable  => \&_enable  => $self);
		# $_->add_notification( Disable => \&_disable => $self);
		# $_->add_notification( Show    => \&_show    => $self);
		# $_->add_notification( Hide    => \&_hide    => $self);
		my @rec = ( $_, $_-> enabled, $_-> visible, $_-> current, $_-> geometry);
		push( @{$cp}, [@rec]);
		next if $page == $self-> {pageIndex};
		$_-> visible(0);
		$_-> autoEnableChildren(0);
		$_-> enabled(0);
		$_-> geometry(gt::Default);
	}
}

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

sub insert
{
	my $self = shift;
	my $page = defined $self-> {defaultInsertPage} ?

		$self-> {defaultInsertPage} :

		$self-> pageIndex;

	return $self-> insert_to_page( $page, @_);
}

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

sub insert_to_page
{
	my $self  = shift;
	my $page  = shift;
	my $sel   = $self-> selected;
	$page = $self-> {pageCount} - 1 if $page > $self-> {pageCount} - 1 || $page < 0;

	$self-> lock;
	my @ctrls = $self-> SUPER::insert( @_);

	$self-> attach_to_page( $page, @ctrls);
	$ctrls[0]-> select if $sel && scalar @ctrls && $page == $self-> {pageIndex} &&

		$ctrls[0]-> isa('Prima::Widget');
	$self-> unlock;

	return wantarray ? @ctrls : $ctrls[0];
}

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

sub insert_transparent
{
	shift-> SUPER::insert( @_);
}

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

sub contains_widget
{
	my ( $self, $ctrl) = @_;
	my $i;
	my $j;
	my $cptr = $self-> {widgets};

	for ( $i = 0; $i < $self-> {pageCount}; $i++) {
		my $cp = $$cptr[$i];
		my $j = 0;
		for ( @$cp) {
			return ( $i, $j) if $$_[0] == $ctrl;
			$j++;
		}
	}
	return;
}

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

sub widgets_from_page
{
	my ( $self, $page) = @_;
	return if $page < 0 or $page >= $self-> {pageCount};

	my @r;
	push( @r, $$_[0]) for @{$self-> {widgets}-> [$page]};
	return @r;
}

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

sub on_childleave
{
	my ( $self, $widget) = @_;
	$self-> detach_from_page( $widget);
}

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

sub detach_from_page
{
	my ( $self, $ctrl)   = @_;
	my ( $page, $number) = $self-> contains_widget( $ctrl);
	return unless defined $page;
	splice( @{$self-> {widgets}-> [$page]}, $number, 1);
}

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

sub delete_widget
{
	my ( $self, $ctrl)   = @_;
	my ( $page, $number) = $self-> contains_widget( $ctrl);
	return unless defined $page;
	$ctrl-> destroy;
}

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

sub move_widget
{
	my ( $self, $widget, $newPage) = @_;
	my ( $page, $number) = $self-> contains_widget( $widget);
	return unless defined $page;

	my @prev_widgets = @{$self-> {widgets}-> [$newPage]};

	@{$self-> {widgets}-> [$newPage]} = ( @prev_widgets, splice( @{$self-> {widgets}-> [$page]}, $number, 1));

#	@{$self-> {widgets}-> [$newPage]} = splice( @{$self-> {widgets}-> [$page]}, $number, 1);
	$self-> repaint if $self-> {pageIndex} == $page || $self-> {pageIndex} == $newPage;
}

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

sub replace_pages
{
	my ( $self, $oldPage, $newPage) = @_;
	$oldPage = 0 unless $oldPage; $oldPage = $self-> {pageCount} - 1 if $oldPage >= $self-> {pageCount};

	$newPage = 0 unless $newPage; $newPage = $self-> {pageCount} - 1 if $newPage >= $self-> {pageCount};

	return if $oldPage == $newPage;

	if ( $oldPage > $newPage ) { my $tmp = $newPage; $newPage = $oldPage; $oldPage = $tmp; }

	my @r = splice( @{$self-> {widgets}}, $oldPage, 1, $self-> {widgets}-> [$newPage]);

#	$self-> delete_widget ( $_ ) for $self-> widgets_from_page($oldPage);
#	$self-> move_widget ( $_,$oldPage ) for $self-> widgets_from_page($newPage);

#	my @tmp_widgets = @{$self-> {widgets}-> [$oldPage]};
#	@{$self-> {widgets}-> [$oldPage]} = @{$self-> {widgets}-> [$newPage]};
#	@{$self-> {widgets}-> [$newPage]} = @tmp_widgets;

#	$self-> delete_widget ( $_ ) for $self-> widgets_from_page($newPage);
#	for ( my $i = 0; $i < scalar @tmp_widgets; $i++ ) {
#		${$self-> {widgets}-> [$newPage]}[0] = $tmp_widgets[$i];
#	}

#	for ( $self-> widgets_from_page( $oldPage ) ) {
#		$self-> widget_set ( $_, visible => 1, autoEnableChildren => 1, enabled => 1, geometry => gt::Default, );
#	}
#	for ( $self-> widgets_from_page( $newPage ) ) {
#		$self-> widget_set ( $_, visible => 1, autoEnableChildren => 1, enabled => 1, geometry => gt::Default, );
#	}

	$self-> repaint if $self-> {pageIndex} == $oldPage || $self-> {pageIndex} == $newPage;
}

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

sub set_page_count
{
	my ( $self, $pageCount) = @_;
	$pageCount = 0 if $pageCount < 0;
	return if $pageCount == $self-> {pageCount};

	if ( $pageCount < $self-> {pageCount}) {
		splice(@{$self-> {widgets}}, $pageCount);
		$self-> {pageCount} = $pageCount;
		$self-> pageIndex($pageCount - 1) if $self-> {pageIndex} < $pageCount - 1;
	} else {
		my $i = $pageCount - $self-> {pageCount};
		push (@{$self-> {widgets}},[]) while $i--;
		$self-> {pageCount} = $pageCount;
		$self-> pageIndex(0) if $self-> {pageIndex} < 0;
	}
}

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

my %virtual_properties = (
	enabled => 1,
	visible => 2,
	current => 3,
	geometry => 4,
);

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

sub widget_get
{
	my ( $self, $widget, $property) = @_;
	return $widget-> $property() if ! $virtual_properties{$property};

	my ( $page, $number) = $self-> contains_widget( $widget);
	return $widget-> $property()

		if ! defined $page || $page == $self-> {pageIndex};

	return $self-> {widgets}-> [$page]-> [$number]-> [$virtual_properties{$property}];
}

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

sub widget_set
{
	my ( $self, $widget) = ( shift, shift );
	my ( $page, $number) = $self-> contains_widget( $widget);

	if ( ! defined $page || $page == $self-> {pageIndex} ) {
		$widget-> set( @_ );
		return;
	}
	$number = $self-> {widgets}-> [$page]-> [$number];
	my %profile;
	my $clear_current_flag = 0;

	while ( @_ ) {
		my ( $property, $value) = ( shift, shift );
		if ( $virtual_properties{$property} ) {
			$number-> [ $virtual_properties{ $property } ] = ( $value ? 1 : 0 );
			$clear_current_flag = 1 if $property eq 'current' && $value;
		} else {
			$profile{$property} = $value;
		}
	}

	if ( $clear_current_flag) {
		for ( @{$self-> {widgets}-> [$page]} ) {
			$$_[3] = 0 if $$_[0] != $widget;
		}
	}
	$widget-> set( %profile ) if scalar keys %profile;
}

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

sub defaultInsertPage
{
	$_[0]-> {defaultInsertPage} = $_[1];
}

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

sub pageIndex     {($#_)?($_[0]-> set_page_index   ( $_[1]))    :return $_[0]-> {pageIndex}}
sub pageCount     {($#_)?($_[0]-> set_page_count   ( $_[1]))    :return $_[0]-> {pageCount}}

################################################################################
# TabbedNotebook styles
package tns;
use constant Simple   => 0;
use constant Standard => 1;

################################################################################
# TabbedNotebook orientations
package tno;
use constant Top    => 0;
use constant Bottom => 1;

################################################################################
package Prima::CodeManager::TabbedNotebook;
use vars qw(@ISA %notebookProps);
@ISA = qw(Prima::Widget Prima::CodeManager::Notebook);

use constant DefBorderX		=>	10;
use constant DefBookmarkX	=>	30;
use constant DefTabMultiply	=>	1.4;

%notebookProps = (
	pageCount      => 1, defaultInsertPage=> 1,
	attach_to_page => 1, insert_to_page   => 1, insert         => 1, insert_transparent => 1,
	delete_widget  => 1, detach_from_page => 1, move_widget    => 1, contains_widget    => 1,
	widget_get     => 1, widget_set       => 1, widgets_from_page => 1,
);

for ( keys %notebookProps) {
	eval <<GENPROC;
   sub $_ { return shift-> {notebook}-> $_(\@_); }
GENPROC
}

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

sub profile_default
{
	return {
		%{Prima::CodeManager::Notebook-> profile_default},
		%{$_[ 0]-> SUPER::profile_default},
#		ownerBackColor      => 0,
		ownerBackColor      => 1,
		tabs                => [],
		tabIndex            => 0,
		style               => tns::Standard,
		orientation         => tno::Top,
		tabsetClass         => 'Prima::CodeManager::TabSet',
		tabsetProfile       => {},
		tabsetDelegations   => ['Change'],
		notebookClass       => 'Prima::CodeManager::Notebook',
		notebookProfile     => {},
		notebookDelegations => ['Change'],
	}
}

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

sub init
{
	my $self = shift;
	my %profile = @_;

	my $visible       = $profile{visible};
	my $scaleChildren = $profile{scaleChildren};
	$profile{visible} = 0;
	$self-> {style}    = tns::Standard;
	$self-> {orientation} = tno::Top;
	$self-> {tabs}     = [];

	%profile = $self-> SUPER::init(%profile);

	my @size = $self-> size;
	my $maxh = $self-> font-> height * 2;

	$self-> {tabSet} = $profile{tabsetClass}-> create(
		owner     => $self,
		name      => 'TabSet',
		left      => 0,
		width     => $size[0],
		top       => $size[1],
		growMode  => gm::Ceiling,
		height    => 2 * int (DefTabMultiply * $self-> font-> height),
		buffered  => 1,
#		backColor=>0xff0000,
		designScale => undef,
		delegations => $profile{tabsetDelegations},
		%{$profile{tabsetProfile}},
	);

	$self-> {notebook} = $profile{notebookClass}-> create(
		owner      => $self,
		name       => 'Notebook',
		origin     => [ DefBorderX + 1, DefBorderX + 1],
		size       => [
			$size[0] - DefBorderX * 2 - 1,
			$size[1] - DefBorderX * 2 - $self-> {tabSet}-> height - DefBookmarkX - 4
		],
		growMode   => gm::Client,
#		backColor=>0xff0000,
		scaleChildren => $scaleChildren,
		(map { $_  => $profile{$_}} keys %notebookProps),
		designScale => undef,
		pageCount  => scalar @{$profile{tabs}},
		delegations => $profile{notebookDelegations},
		%{$profile{notebookProfile}},
	);
	$self-> {notebook}-> designScale( $self-> designScale); # propagate designScale
	$self-> tabs( $profile{tabs});
	$self-> pageIndex( $profile{pageIndex});
	$self-> style($profile{style});
	$self-> orientation($profile{orientation});
	$self-> visible( $visible);

	return %profile;
}

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

sub Notebook_Change
{
	my ( $self, $book) = @_;
	return if $self-> {changeLock};
	$self-> pageIndex( $book-> pageIndex);
}

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

sub on_paint
{
	my ($self,$canvas)	=	@_;

	my @clr  = ( $self-> color, $self-> backColor);
	   @clr  = ( $self-> disabledColor, $self-> disabledBackColor) if ( !$self-> enabled);
	my @c3d  = ( $self-> dark3DColor, $self-> light3DColor);
	my @size = $canvas-> size;
	my $on_top = ($self-> {orientation} == tno::Top);
	$canvas-> color( $clr[1]);
	$canvas-> bar( 0, 0, @size);

	if ($self-> {style} == tns::Standard) {

		$size[1] -= $self-> {tabSet}-> height;

		$canvas-> rect3d(
			0,				0,
			$size[0] - 1,	$size[1],
			1,
			reverse @c3d
		);
		$canvas-> rect3d(
			DefBorderX,					DefBorderX,
			$size[0] - 1 - DefBorderX,	$size[1] - 1 - DefBorderX,
			1,
			@c3d
		);

		my $y = $size[1] - DefBorderX;
		my $x = $size[0] - DefBorderX - DefBookmarkX;
		return if $y < DefBorderX * 2 + DefBookmarkX;

		$canvas-> color( $c3d[0]);

		$canvas-> line( DefBorderX+1, $y - DefBookmarkX - 3, $size[0] - 2 - DefBorderX, $y - DefBookmarkX - 3 );

		my $fh = 24;
		my $a  = 0;
		my ($pi, $mpi) = (
			$self-> {notebook}-> pageIndex,
			$self-> {notebook}-> pageCount - 1
		);

		$a |= 1 if $pi > 0;
		$a |= 2 if $pi < $mpi;

		my $t = $self-> {tabs};
		if ( scalar @{$t}) {

			my $tx = $self-> {tabSet}-> tabIndex;
			my $t1 = $$t[ $tx * 2];
			my $yh = $y - $fh * 0.8 - $self-> font-> height / 2;
#			$canvas-> clipRect( DefBorderX + 1, $y - $fh * 1.6 + 1, $x - 4 + 10, $y - 2);

			$canvas-> color( $clr[0]);
			$canvas-> set( font => { size   => 1.2 * $self-> font->size });
			$canvas-> text_out( ' '.$t1, DefBorderX + 4, $yh );

			if ( $$t[ $tx * 2 + 1] > 0 ) {
				$t1 = sprintf( "Page %d of %d ", $self-> pageIndex + 1, $self-> pageCount );
				my $tl1 = $size[0] - DefBorderX - 3 - DefBookmarkX - $self-> get_text_width( $t1);
				$canvas-> text_out( $t1, $tl1, $yh ) if $tl1 > 4 + DefBorderX + $fh * 3;
			}
		}

#--------------
		$canvas-> color ($c3d[0]);
		my $dx = DefBookmarkX / 2;
		my ( $x1, $y1) = ( $x + $dx, $y - $dx);

		if ( $a & 1 ) {
			$canvas-> polyline([
				$x - 1,					$y - 4,
				$x - 1,					$y - DefBookmarkX,
				$x - 5 + DefBookmarkX,	$y - DefBookmarkX,
				$x - 1,					$y - 4,
			]);
			$canvas-> polyline([
				$x +  3, $y - DefBookmarkX +  7,
				$x + 13, $y - DefBookmarkX +  7,
				$x + 13, $y - DefBookmarkX +  9,
				$x +  3, $y - DefBookmarkX +  9,
				$x +  3, $y - DefBookmarkX +  7,
			]);
		}

		if ( $a & 2 ) {
			$canvas-> polyline([
				$x - 5 + DefBookmarkX,	$y - DefBookmarkX,
				$x - 1,					$y - 4,
				$x - 5 + DefBookmarkX,	$y - 4,
				$x - 5 + DefBookmarkX,	$y - DefBookmarkX,
			]);
			$canvas-> polyline([
				$x1 - 2, $y1 + 3,

				$x1 - 2, $y1 + 5,
				$x1 + 2, $y1 + 5,

				$x1 + 2, $y1 + 9,

				$x1 + 4, $y1 + 9,
				$x1 + 4, $y1 + 5,
				$x1 + 8, $y1 + 5,
				$x1 + 8, $y1 + 3,
				$x1 + 4, $y1 + 3,
				$x1 + 4, $y1 - 1,
				$x1 + 2, $y1 - 1,
				$x1 + 2, $y1 + 3,
				$x1 - 2, $y1 + 3,
			]);
		}

	} else {

		# tns::Simple
#		$canvas-> rect3d(0, 0, $size[0]-1, $size[1]-1, 1, reverse @c3d);
	}
}

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

sub event_in_page_flipper
{
	my ( $self, $x, $y) = @_;
	return if $self-> {style} != tns::Standard;
#return;

	my @size = $self-> size;
#	my $th = ($self-> {orientation} == tno::Top) ? $self-> {tabSet}-> height : 5;
	my $th = $self-> {tabSet}-> height;

	$x -= $size[0] - DefBorderX - DefBookmarkX - 1 - 8;
	$y -= $size[1] - DefBorderX - $th - DefBookmarkX + 4 - 10;
#	$y -= $size[1] - DefBorderX - 4;

	return if $x < 0 || $x > DefBookmarkX || $y < 0 || $y > DefBookmarkX;

	return ( $x, $y);
}

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

sub on_mousedown
{
	my ( $self, $btn, $mod, $x, $y) = @_;
	$self-> clear_event;
	return unless ( $x, $y) = $self-> event_in_page_flipper( $x, $y);
	$self-> pageIndex( $self-> pageIndex + (( -$x + DefBookmarkX < $y) ? 1 : -1));
}

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

sub on_mousewheel
{
	my ( $self, $mod, $x, $y, $z) = @_;
	$self-> clear_event;
	return unless ( $x, $y) = $self-> event_in_page_flipper( $x, $y);
	$self-> pageIndex( $self-> pageIndex + (( $z < 0) ? -1 : 1));
}

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

sub on_mouseclick
{
	my $self = shift;
	$self-> clear_event;
	return unless pop;
	$self-> clear_event unless $self-> notify( "MouseDown", @_);
}

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

sub page2tab
{
	my ( $self, $index) = @_;
	my $t = $self-> {tabs};
	return 0 unless scalar @$t;
	my $i = $$t[1] - 1;
	my $j = 0;
	while( $i < $index) {
		$j++;
		$i += $$t[ $j*2 + 1];
	}
	return $j;
}

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

sub tab2page
{
	my ( $self, $index) = @_;
	my $t = $self-> {tabs};
	my $i;
	my $j = 0;
	for ( $i = 0; $i < $index; $i++) { $j += $$t[ $i * 2 + 1]; }
	return $j;
}

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

sub TabSet_Change
{
	my ( $self, $tabset) = @_;
	return if $self-> {changeLock};
	$self-> pageIndex( $self-> tab2page( $tabset-> tabIndex));
}

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

sub set_tabs
{
	my $self = shift;
	my @tabs = ( scalar @_ == 1 && ref( $_[0]) eq q(ARRAY)) ? @{$_[0]} : @_;
	my @nTabs;
	my @loc;
	my $prev  = undef;
	for ( @tabs) {
		if ( defined $prev && $_ eq $prev) {
			$loc[-1]++;
		} else {
			push( @loc,   $_);
			push( @loc,   1);
			push( @nTabs, $_);
		}
		$prev = $_;
	}
	my $pages = $self-> {notebook}-> pageCount;
	$self-> {tabs} = \@loc;
	$self-> {tabSet}-> tabs( \@nTabs);
	my $i;
	if ( $pages > scalar @tabs) {
		for ( $i = scalar @tabs; $i < $pages; $i++) {
			$self-> {notebook}-> delete_page( $i);
		}
	} elsif ( $pages < scalar @tabs) {
		for ( $i = $pages; $i < scalar @tabs; $i++) {
			$self-> {notebook}-> insert_page;
		}
	}
}

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

sub get_tabs
{
	my $self = $_[0];
	my $i;
	my $t = $self-> {tabs};
	my @ret;
	for ( $i = 0; $i < scalar @{$t} / 2; $i++) {
		my $j;
		for ( $j = 0; $j < $$t[$i*2+1]; $j++) { push( @ret, $$t[$i*2]); }
	}
	return \@ret;
}

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

sub set_page_index
{
	my ( $self, $pi) = @_;

	my ($pix, $mpi) = ( $self-> {notebook}-> pageIndex, $self-> {notebook}-> pageCount - 1);
	$self-> {changeLock} = 1;
	$self-> {notebook}-> pageIndex( $pi);
	$self-> {tabSet}-> tabIndex( $self-> page2tab( $self-> {notebook}-> pageIndex));
	delete $self-> {changeLock};

	my @size = $self-> size;
	my $th   = $self-> {tabSet}-> height;
	my $a  = 0;
	$a |= 1 if $pix > 0;
	$a |= 2 if $pix < $mpi;
	my $newA = 0;
	$pi = $self-> {notebook}-> pageIndex;
	$newA |= 1 if $pi > 0;
	$newA |= 2 if $pi < $mpi;

	$self-> invalidate_rect (
		DefBorderX + 1,

		$size[1] - DefBorderX - $th - DefBookmarkX - 1,
		$size[0] - DefBorderX - (( $a == $newA) ? DefBookmarkX + 2 : 0),
		$size[1] - DefBorderX - $th + 3
	);

	$self-> notify(q(Change), $pix, $pi);
}

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

sub orientation

{
	my ($self, $tno) = @_;
	return $self-> {orientation} unless (defined $tno);

	$self-> {orientation} = $tno;
	$self-> {tabSet}-> topMost($tno == tno::Top);
	$self-> {tabSet}-> growMode(($tno == tno::Top) ? gm::Ceiling : gm::Floor);
	$self-> adjust_widgets;

	return $tno;
}

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

sub style

{
	my ($self, $style) = @_;
	return $self-> {style} unless (defined $style);

	$self-> {style} = $style;
	$self-> adjust_widgets;

	return $style;
}

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

sub adjust_widgets

{
	my ($self) = @_;
	my $nb = $self-> {notebook};
	my $ts = $self-> {tabSet};

	my @size = $self-> size;
	my @pos = (0,0);

	$size[1] -= $ts-> height;
	if ($self-> {style} == tns::Standard) {

		$size[0] -= 2 * DefBorderX + 2;
		$size[1] -= 2 * DefBorderX + DefBookmarkX + 4;
		$pos[0] += DefBorderX + 1;
		$pos[1] += DefBorderX + 1;

	} else {

		$size[0] -= 2;
		$size[1] -= 2;
		$pos[0]++;
		$pos[1]++;
	}

	if ($self-> {orientation} == tno::Top) {

		$ts-> top($self-> height);

	} else {

		$ts-> bottom(0);
		$pos[1] += $ts-> height - 5;
	}

	$nb-> size(@size);
	$nb-> origin(@pos);

	$self-> repaint;
}

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

sub tabIndex     {($#_)?($_[0]-> {tabSet}-> tabIndex( $_[1]))  :return $_[0]-> {tabSet}-> tabIndex}
sub pageIndex    {($#_)?($_[0]-> set_page_index   ( $_[1]))    :return $_[0]-> {notebook}-> pageIndex}
sub tabs         {($#_)?(shift-> set_tabs     (    @_   ))     :return $_[0]-> get_tabs}

################################################################################
package Prima::CodeManager::ScrollNotebook::Client;
use vars qw(@ISA);
@ISA = qw(Prima::CodeManager::Notebook);

sub profile_default
{
	my $def = $_[0]-> SUPER::profile_default;
	my %prf = (
		geometry  => gt::Pack,
		packInfo  => { expand => 1, fill => 'both'},
	);
	@$def{keys %prf} = values %prf;

	return $def;
}

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

sub geomSize
{
	return $_[0]-> SUPER::geomSize unless $#_;

	my $self = shift;
	$self-> SUPER::geomSize( @_);
	$self-> owner-> owner-> ClientWindow_geomSize( $self, @_);
}

################################################################################
package Prima::CodeManager::ScrollNotebook;
use vars qw(@ISA);
@ISA = qw(Prima::ScrollGroup);

for ( qw(pageIndex insert_page delete_page),

		keys %Prima::CodeManager::TabbedNotebook::notebookProps) {
		eval <<GENPROC;
	sub $_ { return shift-> {client}-> $_(\@_); }
GENPROC
}

sub profile_default
{
	return {
		%{Prima::CodeManager::Notebook-> profile_default},
		%{$_[ 0]-> SUPER::profile_default},
		clientClass  => 'Prima::CodeManager::ScrollNotebook::Client',
	}
}

################################################################################
package Prima::CodeManager::TabbedScrollNotebook::Client;
use vars qw(@ISA);
@ISA = qw(Prima::CodeManager::ScrollNotebook);

sub update_geom_size
{
	my ( $self, $x, $y) = @_;
	my $owner = $self-> owner;
	return unless $owner-> packPropagate;
	my @o = $owner-> size;
	my @s = $self-> get_virtual_size;
	$owner-> geomSize( $o[0] - $s[0] + $x, $o[1] - $s[1] + $y);
}

################################################################################
package Prima::CodeManager::TabbedScrollNotebook;
use vars qw(@ISA);
@ISA = qw(Prima::CodeManager::TabbedNotebook);

sub profile_default
{
	return {
		%{$_[ 0]-> SUPER::profile_default},

		notebookClass => 'Prima::CodeManager::TabbedScrollNotebook::Client',
		clientProfile => {},
		clientDelegations => [],
		clientSize    => [ 100, 100],
	}
}

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

sub profile_check_in
{
	my ( $self, $p, $default) = @_;
	$self-> SUPER::profile_check_in( $p, $default);
	$p-> {notebookProfile}-> {clientSize} = $p-> {clientSize}
		if exists $p-> {clientSize} and not exists $p-> {notebookProfile}-> {clientSize};
	if ( exists $p-> {clientProfile}) {
		%{$p-> {notebookProfile}-> {clientProfile}} = (
			($default-> {notebookProfile}-> {clientProfile} ?
				%{$default-> {notebookProfile}-> {clientProfile}} : ()),
			%{$p-> {clientProfile}},
		);
	}
	if ( exists $p-> {clientDelegations}) {
		@{$p-> {notebookProfile}-> {clientDelegations}} = (
			( $default-> {notebookProfile}-> {clientDelegations} ?
				@{$default-> {notebookProfile}-> {clientDelegations}} : ()),
			@{$p-> {clientDelegations}},
		);
	}
}

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

sub client { shift-> {notebook}-> client }

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

sub packPropagate
{
	return shift-> SUPER::packPropagate unless $#_;
	my ( $self, $pack_propagate) = @_;
	$self-> SUPER::packPropagate( $pack_propagate);
	$self-> propagate_size if $pack_propagate;
}

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

sub propagate_size
{
	my $self = $_[0];
	$self-> {notebook}-> propagate_size
		if $self-> {notebook};
}

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

sub clientSize
{
	return $_[0]-> {notebook}-> clientSize unless $#_;
	shift-> {notebook}-> clientSize(@_);
}

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

sub use_current_size
{
	$_[0]-> {notebook}-> use_current_size;
}

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

1;

__END__

=pod

=head1 NAME

Prima::CodeManager::Notebooks - multipage widgets

=head1 DESCRIPTION

This is intesively modified the original Prima::Notebooks module.
Please see details there: L<Prima::Notebooks>.

=head1 AUTHOR OF MODIFICATIONS

Waldemar Biernacki, E<lt>wb@sao.plE<gt>

=head1 COPYRIGHT AND LICENSE OF THE FILE MODIFICATIONS

Copyright 2009-2012 by Waldemar Biernacki.

L<http://CodeManager.sao.pl>

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

=cut