Commits

Herbert Breunung committed f68a8f0

new sizer mechanism finally arrived

  • Participants
  • Parent commits b08eb08

Comments (0)

Files changed (2)

File lib/Kephra/App/Panel.pm

 
 package Kephra::App::Panel;
 our @ISA = 'Wx::Panel';
-my $is_widget = Kephra::App::Util::get('is_widget');
+
+my ($is_widget, $is_sizer) = Kephra::App::Util::get('is_widget', 'is_sizer');
 
 
 sub new {
 	my $class = shift;
 	my $parent = shift;
-	my @children = @_;
 	$parent = Kephra::API::main_window() unless defined $parent and $is_widget->($parent);
 
 	my $self = $class->SUPER::new( $parent );
-	my $sizer = $self->{'sizer'} = Wx::BoxSizer->new( &Wx::wxVERTICAL );
-	$self->SetSizer($sizer);
-
-	$self->{'widgets'} = [];
-	for my $child (@_) {
-		$self->append($child);
-	}
+	$self->{'sizer'} = Kephra::App::Sizer->new('vertical');
+	$self->SetSizer( $self->{'sizer'}->bare_sizer );
+	$self->append(@_);
 	$self;
 }
 
-sub prepend {
-	my ($self, @widgets) = @_;
-	$self->_insert({widget => $_, position => 0}) for @widgets;
-}
-sub append {
-	my ($self, @widgets) = @_;
-	$self->_insert({widget => $_, 
-	                position => $self->{'sizer'}->GetChildren || 0}) for @widgets;
-}
-sub append_expanded {
-	my ($self, @widgets) = @_;
-	$self->_insert({
-		widget => $_, 
-		position => $self->{'sizer'}->GetChildren || 0, 
-		proportion => 1                               }) for @widgets;
-}
-sub insert {
-	my ($self, $widget, $position ) = @_;
-	$self->_insert( $widget) if ref $widget eq 'HASH';
-	$self->_insert({widget => $widget, position => $position})
-		if ref $widget and $is_widget->($widget) 
-		or ref $widget eq 'REF'and ref $$widget and $is_widget->( $$widget );
+sub sizer { shift->{'sizer'} }
+
+sub prepend         { shift->insert(  0, 0, @_ ) }
+sub append          { shift->insert( -1, 0, @_ ) }
+sub append_expanded { shift->insert( -1, 1, @_ ) }
+sub insert_before   { my($self)=shift; $self->insert( $self->get_position(shift)  , 1, @_ ) }
+sub insert_after    { my($self)=shift; $self->insert( $self->get_position(shift)+1, 1, @_ ) }
+sub insert          { 
+	my ($self) = shift; 
+	my ($position) = shift;
+	my ($proportion)  = shift;
+	$self->adopt(@_);
+	$self->sizer->insert($position, $proportion, @_);
+	$self
 }
 
-sub _insert { # only one item
-	my ($self, $item) = @_;
-	return Kephra::Log::error('got no hash as item def') unless ref $item eq 'HASH';
-	return Kephra::Log::error('got no proper widget, but '.$item->{'widget'})
-		unless $is_widget->( $item->{'widget'} )
-		or $is_widget->( ${$item->{'widget'}} );
-	# ref to widget ref can signal to expand that widget
-	if (ref $item->{'widget'} eq 'REF'){
-		$item->{'widget'} = ${ $item->{'widget'} };
-		$item->{'proportion'} = 1;
+sub adopt {
+	my ($self) = shift;
+	for my $item (@_) {
+		$self->adopt( @$item ) if ref $item eq 'ARRAY';
+		$item = $item->{'child'} if ref $item eq 'HASH';
+		next unless $is_widget->($item);
+		$item->Reparent($self) unless $item->GetParent eq $self;
 	}
-	my %presets = (
-		position => $self->{'sizer'}->GetChildren || 0,
-		proportion => 0,
-		style => &Wx::wxGROW,
-		border => 0,
-	);
-	for (qw/position proportion style border/)
-		{ $item->{$_} = $presets{$_} unless exists $item->{$_} }
-
-	splice @{$self->{'widgets'}}, $item->{'position'}, 0, $item->{'widget'};
-	$self->{'sizer'}->Insert(
-		$item->{'position'}, $item->{'widget'}, $item->{'proportion'},
-		$item->{'style'},    $item->{'border'}
-	);
-	$item->{'widget'}->Reparent($self) unless $item->{'widget'}->GetParent eq $self;
-	$item->{'position'};
 }
 
 sub remove {}
 sub detach {}
-sub show {
-	my ($self, $widget) = @_;
-	$self->{'sizer'}->Show($widget, 1);
-}
-sub hide {
-	my ($self, $widget) = @_;
-	$self->{'sizer'}->Hide($widget);
-}
-
-sub all_widgets { shift->{'widgets'} }
-sub widget_by_nr {
-	my ($self, $nr) = @_;
-	$self->{'widgets'}[$nr]
+sub show {}
+sub hide {}
+sub all_widgets {  }
+sub widget_by_nr { }
+sub get_position {
+	my ($self) = shift; 
+	my ($child) = shift;
+	$self->sizer->get_position($child);
 }
 
 1;

File lib/Kephra/App/Sizer.pm

 use Kephra::API;
 use Kephra::App::Util;
 
+
 package Kephra::App::Sizer;
-#our @ISA = 'Wx::Sizer';
-use base 'Wx::Sizer';
 my ($is_widget, $is_sizer) = Kephra::App::Util::get('is_widget', 'is_sizer');
-use Scalar::Util qw(blessed looks_like_number);
+use Scalar::Util qw(looks_like_number);
 
 
 sub new {
 	my $class = shift;
 	my $orient = shift;
+
 	if    (lc substr($orient, 0, 1) eq 'v') { $orient = &Wx::wxVERTICAL }
 	elsif (lc substr($orient, 0, 1) eq 'h') { $orient = &Wx::wxHORIZONTAL }
 	#elsif (not defined $orient)             { $orient = &Wx::wxHORIZONTAL }
 		return Kephra::Log::error
 			("need h|horizontal or v|vertical as first parameter, not $orient", 1)
 	}
-	my $self = $class->SUPER::new( $orient );
+	my $self = bless {
+		'sizer'       => Wx::BoxSizer->new( $orient ),
+		'child_sizer' => [] 
+	}, $class;
 	$self->append(@_);
 	$self;
 }
 
+sub bare_sizer      { shift->{'sizer'} }
+sub child_sizer     { @{ shift->{'child_sizer'} } }
 
 # syntax sugar for insert method, unless insert can take list of child items
 # all these methods are ment to be chained, thatswhy the $self at the end
 		$self->_insert( $self->_build_item($position, $proportion, $_) );
 		$position++ unless $position == -1;
 	}
-	$self->Layout;
+	$self->bare_sizer->Layout;
 	$self;
 }
 
 	while (ref $child eq 'REF'){ $refcount++; $child = $$child; }
 
 	if (ref $child eq 'ARRAY'){
+		my $orient = $self->bare_sizer->GetOrientation;
 		my $child_orient = 
-			$refcount % 2                              ? $self->GetOrientation
-		  : $self->GetOrientation == &Wx::wxHORIZONTAL ? &Wx::wxVERTICAL
-		  :                                              &Wx::wxHORIZONTAL;
+			$refcount % 2                ? $orient
+		  : $orient == &Wx::wxHORIZONTAL ? &Wx::wxVERTICAL
+		  :                                &Wx::wxHORIZONTAL;
 		my @subsizer_children = @$child;
 		$child = __PACKAGE__->new( $child_orient, @subsizer_children );
 	}
 	# fill with default settings (presets)
 	for (qw/position proportion style border/)
 		{ $item{$_} = $presets{$_} unless exists $item{$_} }
-	$item{position} = $self->GetChildren || 0 if $item{position} == -1;
+	$item{position} = $self->bare_sizer->GetChildren || 0 if $item{position} == -1;
 
 	return \%item;
 }
 
 	if ($item->{'child'} eq 'space'){
 		if ($item->{'proportion'}){
-			$self->InsertStretchSpacer( $item->{'position'},  $item->{'proportion'} )
+			$self->bare_sizer->InsertStretchSpacer( $item->{'position'}, $item->{'proportion'} )
 		} else {
-			$self->InsertSpacer(        $item->{'position'},  $item->{'border'} )
+			$self->bare_sizer->InsertSpacer(        $item->{'position'}, $item->{'border'} )
 		}
-	} else {
-		$self->Insert(
+	} 
+	elsif (ref $item->{'child'} eq __PACKAGE__){
+		push @{ $self->{'subsizer'} }, $item->{'child'};
+		$self->bare_sizer->Insert(
+			$item->{'position'},  $item->{'child'}->bare_sizer,  $item->{'proportion'},
+			$item->{'style'},     $item->{'border'}
+		);
+	}
+	else {
+		$self->bare_sizer->Insert(
 			$item->{'position'},  $item->{'child'},  $item->{'proportion'},
 			$item->{'style'},     $item->{'border'}
 		);
 	my ($self) = shift;
 	my ($call) = shift;
 	return Kephra::Log::error('need a coderef, not $call', 2) unless ref $call eq 'CODE';
-	$call->($self, $_) for @_;
-	$self->Layout;
+	for (@_){
+		$_ = $_->bare_sizer if ref $_ eq __PACKAGE__;
+		$call->( $self->bare_sizer, $_ );
+	}
+	$self->bare_sizer->Layout;
+	$self->_remove_gone_subsizer;
 	$self;
 }
+sub _remove_gone_subsizer {
+	my ($self) = shift;
+	my @child_sizer = $self->child_sizer();
+	return unless @child_sizer;
+	for my $nr (reverse 0 .. scalar @child_sizer ) {
+		next if $self->is_child( $child_sizer[$nr]->bare_sizer );
+		splice @child_sizer, $nr, 1;
+	}
+	$self->{'child_sizer'} = \@child_sizer;
+}
 
 
 # getter
-sub get_position {                                      # number of that child
+sub get_position {                                        # number of that child
 	my ($self, $child) = @_;
 	my $pos = 0;
 	if ($is_widget->($child)){
-		for ($self->GetChildren){
+		for ($self->bare_sizer->GetChildren){
 			return $pos if $_->IsWindow and $_->GetWindow eq $child;
 			$pos++;
 		}
 	}
 	elsif ($is_sizer->($child)){
-		for ($self->GetChildren){
+		for ($self->bare_sizer->GetChildren){
 			return $pos if $_->IsSizer and $_->GetSizer eq $child;
 			$pos++;
 		}
 	Kephra::Log::error("$child is no child of $self", 1);
 	return -1;
 }
-sub is_child   { $_[0]->get_position( $_[1] ) > -1 ? 1 : 0 }
-sub child_item { $_[0]->GetItem($_[1]) }                # child with that number
-sub childsizer { 
-	my ($self) = shift;
-	my @sizer;
-	for ($self->GetChildren){ push @sizer, $_->GetSizer if $_->IsSizer }
-	@sizer;
-}
-sub widgets    {
+sub is_child     { 1 if $_[0]->child_item( $_[1] )   }
+sub child_item   { $_[0]->bare_sizer->GetItem($_[1]) }    # child with that number
+sub child_widgets{
 	my ($self) = shift;
 	my @widgets;
-	for ($self->GetChildren){ push @widgets, $_->GetWindow if $_->IsWindow }
+	for ($self->bare_sizer->GetChildren)
+		{ push @widgets, $_->GetWindow if $_->IsWindow }
 	@widgets;
 }
 
 		unless ref $check eq 'CODE';
 
 	my @item;
-	for ($self->GetChildren){ push @item, $_ if $check->($_) }
+	for ($self->bare_sizer->GetChildren){ push @item, $_ if $check->($_) }
 	@item;
 }