Commits

Herbert Breunung committed c72b236 Draft

ufff after massive rewrite averything works again, lazy widget eval and tied together sizer gen(LabeledBox and TabbedBox counts too)

Comments (0)

Files changed (13)

lib/Wx/Perl/DisplaySlider.pm

+use v5.12;
+use warnings;
+use Wx;
+
+package Wx::Perl::DisplaySlider;
+use base qw(Wx::Panel);
+
+sub new {
+	my ($class, $parent, $label, $default, $min, $max, $callback, $transport) = @_;
+
+	$label = '' unless defined $label;
+	$default = $min if $default < $min;
+	$default = $max if $default > $max;
+
+
+	my ($self) = $class->SUPER::new( $parent );
+	$self->{'min'} = $min;
+	$self->{'max'} = $max;
+	$self->{'default'} = $default;
+	$callback = sub {} unless ref $callback eq 'CODE'; 
+	my $frontlabel = Wx::StaticText->new($self, -1, "$label : ");
+	my $slider = $self->{'slider'}= Wx::Slider->new($self,-1,$default,$min,$max);
+	$slider->SetMinSize([300,-1]);
+	my $text =   $self->{'text'}  = Wx::TextCtrl->new(
+			$self, -1, $default, [-1,-1], [40, -1], &Wx::wxTE_PROCESS_ENTER| &Wx::wxTE_RIGHT
+	);
+
+	my $sizer = Wx::BoxSizer->new( &Wx::wxHORIZONTAL);
+	my $grow_center_all = &Wx::wxGROW | &Wx::wxALL| &Wx::wxALIGN_CENTER_VERTICAL;
+	$sizer->Add($frontlabel, 0, $grow_center_all, 10 );
+	$sizer->Add($slider,     1, $grow_center_all,  5 );
+	$sizer->Add($text,       0, $grow_center_all,  5 );
+
+	Wx::Event::EVT_SCROLL( $slider, sub { # text always shows current value of slider
+		$text->SetValue( $slider->GetValue) if $text->GetValue != $slider->GetValue;
+	} );
+	Wx::Event::EVT_SCROLL_THUMBRELEASE( $slider, sub {
+		#return if $slider->GetValue == $text->GetValue;
+		$text->SetValue( $slider->GetValue );
+		$callback->(); 
+	} );
+	Wx::Event::EVT_TEXT_ENTER($text, -1, sub {
+		return if $slider->GetValue == $text->GetValue;
+		$slider->SetValue( $text->GetValue );
+		$callback->(); 
+	});
+	Wx::Event::EVT_KILL_FOCUS($text, sub {
+		$_[1]->Skip;
+		if ($slider->GetValue != $text->GetValue){
+			$slider->SetValue( $text->GetValue );
+			$callback->();
+		}
+	});
+	Wx::Event::EVT_MIDDLE_DOWN( $slider, sub { $self->ResetValue; $callback->() } );
+	Wx::Event::EVT_LEFT_DCLICK( $slider, sub { $self->ResetValue; $callback->() } );
+    
+    $self->SetSizerAndFit( $sizer );
+    $self->ResetValue();
+    $self;
+}
+
+sub GetValue {
+	my ($self) = shift;
+	$self->{'text'}->GetValue;
+}
+sub SetValue{
+	my ($self, $value) = @_;
+	$value = 0 unless defined $value;
+	$value = 0 + $value;
+	return if $value < $self->{'min'};
+	return if $value > $self->{'max'};
+	$self->{'text'}->SetValue( $value );
+	$self->{'slider'}->SetValue( $value );
+}
+sub ResetValue {
+	my ($self) = shift;
+	$self->SetValue( $self->{'default'} );
+}
+
+1;

lib/Wx/Perl/DrawMap.pm

 	$self;
 }
 
+
 sub Colour {
 	my ($self, $r, $g, $b) = @_;
 	$self->{'colour'}->Set( $r, $g, $b, 0 );

lib/Wx/Perl/RadioGroup.pm

 
 sub new {
 	my ($class, $parent, $label, $default, $orient, $callback) = @_;
+
 	return warn ((caller(0))[3].' needs a Widget ref as first parameter')
 		unless blessed($parent) and $parent->isa('Wx::Window');
 	return warn ((caller(0))[3].' needs a ARRAY ref as second parameter')
 	$self->ResetValue ();
 	$self;
 }
+sub GetSelectedLabel {}
+
 sub GetValue {
 	my ($self) = shift;
 	for (0 .. scalar @{$self->{'button'}} - 1) {

lib/Wx/Perl/Smart/Factory.pm

-use v5.12;
-use warnings;
-use Wx;
-
-package Wx::Perl::Smart::Factory;
-our $VERSION = '0.1';
-use Scalar::Util qw(blessed looks_like_number);
-
-sub Make {
-	my @widget;
-	for my $widget_def (@_){
-		next unless defined $widget_def;
-		warn ((caller(0))[3].': need an ARRAY ref as parameter, not $widget_def'), next unless ref $widget_def eq 'ARRAY';
-		my $widget;
-		if ($widget_def->[0] eq '-Button'){
-			warn ((caller(0))[3].': @$widget_def is no proper WxButton definition (-Button => $parent, "label", &callback)'),
-				next if not(blessed($widget_def->[1]) and $widget_def->[1]->isa('Wx::Window'))
-				or ref $widget_def->[2]
-				or ref $widget_def->[3] ne 'CODE';
-			$widget = Wx::Button->new($widget_def->[1], -1, $widget_def->[2]);
-			Wx::Event::EVT_BUTTON( $widget, $widget, $widget_def->[3] );
-		} elsif ($widget_def->[0] eq '-CheckBox'){
-			warn ((caller(0))[3].': @$widget_def is no proper Checkbox definition (-CheckBox => $parent, "label", checked?, &callback)'),
-				next if not(blessed($widget_def->[1]) and $widget_def->[1]->isa('Wx::Window'))
-				or ref $widget_def->[2]
-				or not looks_like_number($widget_def->[3])
-				or ($widget_def->[4] and ref $widget_def->[4] ne 'CODE');
-			$widget = Wx::CheckBox->new($widget_def->[1], -1, $widget_def->[2]);
-			$widget->SetValue($widget_def->[3]);
-			Wx::Event::EVT_CHECKBOX( $widget, -1, $widget_def->[4] ) if $widget_def->[4];
-		} elsif ($widget_def->[0] eq '-ComboBox'){
-			warn ((caller(0))[3].': @$widget_def is no proper ComboBox definition (-ComboBox => $parent, [options], "visible value", length, &callback)'),
-				next if not(blessed($widget_def->[1]) and $widget_def->[1]->isa('Wx::Window'))
-				or ref $widget_def->[2] ne 'ARRAY'
-				or ref $widget_def->[3] 
-				or ref $widget_def->[4]
-				or ($widget_def->[5] and ref $widget_def->[5] ne 'CODE');
-			my $textvalue = $widget_def->[3];
-			if (not defined $textvalue or not $textvalue){$textvalue = $widget_def->[2][0]   } 
-			elsif (looks_like_number($textvalue)) {$textvalue = $widget_def->[2][$textvalue] }
-			$textvalue = '' unless defined $textvalue;  # combobox doesnt like an undef in text field
-			my $length = $widget_def->[4];
-			$length = -1 unless $length;
-			$widget = Wx::ComboBox->new(
-				$widget_def->[1], -1, $textvalue, [-1,-1], [$length,-1], $widget_def->[2]
-			);
-			Wx::Event::EVT_COMBOBOX( $widget, -1, $widget_def->[5]) if $widget_def->[5];
-		}
-		push @widget, $widget if defined $widget and blessed($widget);
-	}
-	return $widget[0] if scalar @widget == 1;
-	return @widget;
-}
-
-
-1;

lib/Wx/Perl/Smart/Frame.pm

 use v5.12;
 use warnings;
 use Wx;
-use Wx::Perl::Smart::Sizer;
 use Wx::Perl::Smart::Panel;
-use Wx::Perl::Smart::Factory;
+use Wx::Perl::Smart::WidgetFactory;
 
 package Wx::Perl::Smart::Frame;
 our $VERSION = '0.20';
 my %widget_io = (
 	'Wx::ComboBox' =>1, 'Wx::CheckBox' =>1, 
 	'Wx::TextCtrl' =>1, 'Wx::StyledTextCtrl' =>1, 
-	'Wx::Perl::TextSlider' => 1, 'Wx::Perl::RadioGroup' =>1,
+	'Wx::Perl::DisplaySlider' => 1, 'Wx::Perl::RadioGroup' =>1,
 );
 
 sub new {
 	my ($class, $label, $mode) = @_; #$parent, $widgets, $border
-	my ($self) = $class->SUPER::new(
-		undef, -1, $label, [1,1], [-1,-1], &Wx::wxDEFAULT_FRAME_STYLE ^ &Wx::wxRESIZE_BORDER
-	);
+	$mode = '' unless defined $mode;
+	my $style = &Wx::wxDEFAULT_FRAME_STYLE;
+	$style = $style ^ &Wx::wxRESIZE_BORDER unless $mode eq 'resize';
+
+	my ($self) = $class->SUPER::new( undef, -1, $label, [1,1], [-1,-1], $style );
+	Wx::InitAllImageHandlers();
 	$self->SetIcon( Wx::GetWxPerlIcon() );
 	$self->{'mode'} = $mode;
-	Wx::InitAllImageHandlers();
+	$self->{'factory'} = Wx::Perl::Smart::WidgetFactory->new($self);
 	$self;
 }
+sub SetSmartLayout {
+	my ($self) = shift;
+	my $sizer = Wx::BoxSizer->new( &Wx::wxVERTICAL );
+	$sizer-> Add( Wx::Perl::Smart::Panel->new( $self, [ @_ ] ), 0 );
+	$self->SetSizerAndFit ($sizer);
+	$self->Center();
+	$self->Show(1);
+	$self;
+}
+
+
+
 
 sub SubscribeWidgets {
 	my ($self, $widgets) = @_;
 	warn ((caller(0))[3].'needs a hashref as parameter') unless ref $widgets eq 'HASH';
 	while (my ($name, $widget) = each %$widgets) {
 		warn ((caller(0))[3].": $name is already subscribed"), next if $self->{'managed'}{'widget'}{$name};
-		if (ref $widget eq 'ARRAY'){
-			splice (@$widget, 1, 0, $self);          # frames becomes the parent
-			$widget = Wx::Perl::Smart::Factory::Make($widget);
-		}
-		warn ((caller(0))[3].": $widget is not a widget"), next
-			unless blessed($widget) and $widget->isa('Wx::Window');
-		$self->{'managed'}{'widget'}{$name} = $widget;
-		$self->{'managed'}{'default_val'}{$name} = $widget->GetValue if $widget_io{ref $widget};
-		$widget->Reparent($self);
-		$widget->Show(0);
+		warn ((caller(0))[3].": $widget is not a widget"), next unless is_widget($widget) or ref $widget eq 'ARRAY';
+
+		if (ref $widget eq 'ARRAY'){ $self->{'managed'}{'widget_def'}{$name} = $widget }
+		else                       { $self->_SubscribeWidget($widget, $name) }
 	 }
 }
+sub _SubscribeWidget {
+	my ($self, $widget, $name) = @_;
+	$self->{'managed'}{'widget'}{$name} = $widget;
+	$self->{'managed'}{'default_val'}{$name} = $widget->GetValue if $widget_io{ref $widget};
+	$widget->Reparent($self);
+	$widget->Show(0);
+}
 sub UnsubscribeWidgets {
 	my ($self) = shift;
 	for my $name (@_){
-		warn ((caller(0))[3].": no widget subscribed as $name") unless exists $self->{'managed'}{'widget'}{$name};
-		$self->{'managed'}{'widget'}{$name} = '';
-		$self->{'managed'}{'default_val'}{$name} = '';
+		warn ((caller(0))[3].": no widget subscribed as $name")
+			unless exists $self->{'managed'}{'widget'}{$name}
+			    or exists $self->{'managed'}{'widget_ref'}{$name};
+		delete $self->{'managed'}{'widget'}{$name};
+		delete $self->{'managed'}{'widget_def'}{$name};
+		delete $self->{'managed'}{'default_val'}{$name};
 	}
 }
 sub GetSubscribedWidget {
 	my ($self) = shift;
 	my @widget;
 	for my $name (@_){
-		warn ((caller(0))[3].": there is no widget subscribed as $name") unless exists $self->{'managed'}{'widget'}{$name};
+		warn ((caller(0))[3].": there is no widget subscribed as $name"), next
+			unless exists $self->{'managed'}{'widget'}{$name}
+			    or exists $self->{'managed'}{'widget_def'}{$name};
+
+		$self->{'managed'}{'widget'}{$name} = $self->{'factory'}->Make(
+			$self->{'managed'}{'widget_def'}{$name}
+		) if not exists $self->{'managed'}{'widget'}{$name};
 		push @widget, $self->{'managed'}{'widget'}{$name};
 	}
 	return $widget[0] if scalar @widget == 1;
 	return @widget;
 }
-#sub w { shift->GetSubscribedWidget(@_) }
-#sub WidgetSubscribed {shift->{'managed'}{'widget'}{shift;}}
+sub IsWidgetSubscribed {
+	my ($self, $widget_wanted) = @_;
+	while (my ($name, $widget) = each %{$self->{'managed'}{'widget'}}) {
+		return $name if $widget eq $widget_wanted;
+	}
+	return 0;
+}
+
+
 sub SubscribeStrings {
 	my ($self, $string) = @_;
 	warn ((caller(0))[3].': needs a HASH ref as parameter') unless ref $string eq 'HASH';
 	}
 	$self;
 }
-
-sub GetSubscribedString {
-	my ($self, $name) = @_;
-	$self->{'managed'}{'string'}{$name};
+sub EvalSubscribedStrings {
+	my ($self, $string) = @_;
+	return $string if ref $string or not $string;
+	$string =~ s/(~\w+)/$self->{'managed'}{'string'}{substr($1, 1)}/ while index ($string, '~') > -1;
+	return $string;
 }
 
 
 }
 
 
-sub SetSmartLayout {
-	my ($self) = shift;
-	$self->SetSizerAndFit( 
-		Wx::Perl::Smart::Sizer->new($self, [ 
-			Wx::Perl::Smart::Panel->new( $self, [ @_ ] ) 
-		])
-	);
-	$self->Center();
-	$self->Show(1);
-	$self;
-
+sub widget_admin {
+	my ($widget) = shift;
+	return warn ((caller(0))[3].": need a WxWwidget") unless is_widget($widget);
+	while ($widget->GetParent){
+		$widget = $widget->GetParent;
+		return $widget if ref $widget eq __PACKAGE__;
+	}
 }
 
+sub is_widget { 1 if blessed($_[0]) and $_[0]->isa('Wx::Window') }
+
 1;

lib/Wx/Perl/Smart/LabeledBox.pm

-use v5.12;
-use warnings;
-use Wx;
-use Wx::Perl::Smart::Sizer;
-
-package Wx::Perl::Smart::LabeledBox;
-use base qw(Wx::Panel);
-sub new {
-	my ($class, $parent, $label, $widgets, $orientation, $init_arg) = @_;
-	return unless ref $widgets eq 'ARRAY';
-	my ($self) = $class->SUPER::new( $parent );
-	my ($sizer) = Wx::StaticBoxSizer->new 
-			(Wx::StaticBox->new($self, -1, " $label "), &Wx::wxVERTICAL);
-	$sizer->Add( Wx::Perl::Smart::Sizer->new
-			($self, $widgets, $orientation, $init_arg), 0, &Wx::wxGROW);
-	$self->SetSizerAndFit( $sizer );
-	$self;
-}
-
-1;

lib/Wx/Perl/Smart/Panel.pm

 use warnings;
 use Wx;
 use Wx::Perl::Smart::Sizer;
-use Wx::Perl::Smart::Factory;
+
 
 package Wx::Perl::Smart::Panel;
 use base qw(Wx::Panel);
-use Scalar::Util qw(blessed);
+use Scalar::Util qw(blessed looks_like_number);
 
 sub new {
 	my ($class, $parent, $widgets, $orientation, $init_arg) = @_;
-	die __PACKAGE__.'::new a widget as first arg'
-		if  defined $parent and not (blessed($parent) and $parent->isa('Wx::Window'));
-	die __PACKAGE__.'::new need a widget list (ARRAY ref) as second arg' unless ref $widgets eq 'ARRAY';
+
+	return warn ((caller(0))[3].': first parameter $parent is no proper WxWindow') 
+			unless blessed($parent) and $parent->isa('Wx::Window');
+	return warn ((caller(0))[3].': second parameter $widgets has should be ARRAY ref') unless ref $widgets eq 'ARRAY';
 
 	my ($self)  = $class->SUPER::new( $parent );
 	$self->{'sizer'} = Wx::Perl::Smart::Sizer->new($self, $widgets, $orientation, $init_arg);

lib/Wx/Perl/Smart/Sizer.pm

 use v5.12;
 use warnings;
 use Wx;
-#use Wx::Perl::Smart::LabeledBox;
-#use Wx::Perl::Smart::TabbedBox;
-use Wx::Perl::Smart::Factory;
+use Wx::Perl::Smart::WidgetFactory;
+use Wx::Perl::Smart::Frame;
 
-#use Wx::Perl::RadioGroup;
-#use Wx::Perl::TextSlider;
 
 package Wx::Perl::Smart::Sizer;
 our $VERSION = '0.23';
 	for (keys %default_arg) { $arg{$_} = defined $init_arg->{$_} ? $init_arg->{$_} : $default_arg{$_} }
 	$arg{'flags'} = ${$arg{'flags'}} | $default_arg{'flags'} if ref $arg{'flags'} eq 'SCALAR';
 	$arg{'add_callback'} = $default_arg{'add_callback'} unless ref $arg{'add_callback'} eq 'CODE';
-	my $root = $parent;
-	$root = $root->GetParent while $root->GetParent;
-	$root = '' unless ref $root eq 'Wx::Perl::Smart::Frame' or ref $root eq 'Wx::Perl::Smart::Panel';
+	my $admin = Wx::Perl::Smart::Frame::widget_admin($parent);
+	#my $factory = Wx::Perl::Smart::WidgetFactory->new($admin, $parent);
 
 	# create the sizer
 	my ($self) = $class->SUPER::new( $orientation );
 		my ($proportion) = (0);			# deref and count proportion of this widget
 		$proportion++, $widget = $$widget while ref $widget eq 'REF' or ref $widget eq 'SCALAR';
 
-
-		if (ref $widget eq 'HASH'){
+		if (ref $widget eq 'HASH'){     # change add arguments
 			my %old_arg = %arg;
 			push @arg_stack, \%old_arg;
 			for (keys %default_arg) {$arg{$_} = $widget->{$_} if defined $widget->{$_}}
 			next;
 		}
-		elsif (ref $widget eq 'ARRAY'){
+		elsif (ref $widget eq 'ARRAY'){  # subsizer
 			my $sizer = Wx::Perl::Smart::Sizer->new(
 				$parent, $widget, toggle_orientation($orientation),
 				{add_callback => $arg{'add_callback'}}
 		}
 		elsif (not ref $widget) {
 			next unless $widget;
-			if (substr($widget, 0, 1) eq '-' ) {
-				($widget, my $name) = split(':', substr($widget, 1));
-				if ($widget eq 'LabeledBox') {
-					next unless exists $widgets->[$pos+1];
-					$widget = $widgets->[$pos+1];
-					next unless ref $widget eq 'ARRAY' and scalar @$widget > 0 and not ref $widget->[0];
-					$pos++;
-					my $label = shift @$widget;
-					require Wx::Perl::Smart::LabeledBox;
-					$widget = Wx::Perl::Smart::LabeledBox->new($parent, $label, $widget);
-				}
-				elsif ($widget eq 'TabbedBox' ) {
-					next unless exists $widgets->[$pos+1];
-					$widget = $widgets->[$pos+1];
-					next unless ref $widget eq 'ARRAY' and scalar @$widget > 0 and not ref $widget->[0];
-					$pos++;
-					require Wx::Perl::Smart::TabbedBox;
-					$widget = Wx::Perl::Smart::TabbedBox->new(
-						$parent, $widget, toggle_orientation($orientation),
-						{add_callback => $arg{'add_callback'}}
-					);
-				}
-			}
-			elsif (substr($widget, 0, 1) eq '<' and substr($widget, -1) eq '>') {
-				next unless $root;
-				$widget = $root->GetSubscribedWidget( substr($widget, 1, -1) );
-				next unless $widget;
-			}
-			elsif (looks_like_number($widget)) {
+			if (looks_like_number($widget)) {  # numer indicate space
 				$proportion 
 					? $self->AddStretchSpacer( $proportion )
 					: $self->AddSpacer( $widget );
 				next;
 			}
+			elsif (substr($widget, 0, 1) eq '-' ) {
+				($widget, my $name) = split(':', substr($widget, 1));
+				if ($widget eq 'LabeledBox') {
+					next unless exists $widgets->[$pos+1];
+					my $subwidget = $widgets->[$pos+1];
+					next unless ref $subwidget eq 'ARRAY' and scalar @$subwidget > 0 and not ref $subwidget->[0];
+					$pos++;
+					my $label = shift $subwidget;
+					$label = $admin->EvalSubscribedStrings( $label ) if $admin;
+
+					$widget = Wx::StaticBoxSizer->new( 
+						Wx::StaticBox->new($parent, -1, " $label "), &Wx::wxVERTICAL
+					);
+					$widget->Add( 
+						Wx::Perl::Smart::Sizer->new(
+							$parent, $subwidget, toggle_orientation($orientation),
+							{add_callback => $arg{'add_callback'}}
+						), 0, &Wx::wxGROW
+					);
+				}
+				elsif ($widget eq 'TabbedBox' ) {
+					next unless exists $widgets->[$pos+1];
+					my $subwidget = $widgets->[$pos+1];
+					next unless ref $subwidget eq 'ARRAY' and scalar @$subwidget > 0 and not ref $subwidget->[0];
+					$pos++;
+
+					$widget = Wx::Notebook->new($parent,-1,[-1,-1],[-1,-1], &Wx::wxNB_TOP );
+					while (scalar @$subwidget > 1){
+						my $label         = shift $subwidget;
+						my $panel_widgets = shift $subwidget;
+						$label = $admin->EvalSubscribedStrings( $label ) if $admin;
+						$widget->AddPage( 
+							Wx::Perl::Smart::Panel->new(
+								$widget, $panel_widgets, &Wx::wxVERTICAL,
+								{add_callback => $arg{'add_callback'}}
+							), $label, 0
+						);
+					}
+					#$widget->ChangeSelection(0);
+				}
+				$admin->SubscribeWidgets({$name => $widget}) if $admin and $name;
+			}
+			elsif (substr($widget, 0, 1) eq '<' and substr($widget, -1) eq '>') {
+				next unless $admin;
+				my $name = substr $widget, 1, -1;
+				$widget = $admin->GetSubscribedWidget( $name );
+				next unless $widget;
+			}
 			elsif (substr($widget, 0, 1) eq '-' or substr($widget, 0, 1) eq '|') {
 				$widget = $orientation == &Wx::wxVERTICAL
 					? Wx::StaticLine->new($parent,-1,[-1,-1],[-1,2])
 					: Wx::StaticLine->new($parent,-1,[-1,-1],[2,-1]);
 			}
 			else {
-				$widget = substr($widget,1) if substr($widget,0,1) eq '-';
-				$widget = Wx::StaticText->new($parent, -1, $widget);
+				$widget = $admin->EvalSubscribedStrings($widget) if $admin;
+				$widget = Wx::StaticText->new( $parent, -1, $widget );
 			}
 		}
 		next unless blessed($widget) and ($widget->isa('Wx::Window') or $widget->isa('Wx::Sizer'));
 		$arg{'add_callback'}->($widget);
 		$widget->Reparent($parent) if defined $parent and $widget->isa('Wx::Window');
 		$widget->Show(1) if $widget->isa('Wx::Window');
-		
+
 		$self->Add( $widget, $proportion, $arg{'flags'}, $arg{'border'});
 	}
+
 	return $self;
 }
 

lib/Wx/Perl/Smart/TabbedBox.pm

-use v5.12;
-use warnings;
-use Wx;
-use Wx::Perl::Smart::Panel;
-
-package Wx::Perl::Smart::TabbedBox;
-use base qw(Wx::Notebook);
-use Scalar::Util qw(blessed);
-
-sub new {
-	my ($class, $parent, $widgets, $orientation, $init_arg) = @_;
-	die __PACKAGE__.'::new a widget as first arg'
-		if  defined $parent and not (blessed($parent) and $parent->isa('Wx::Window'));
-	die __PACKAGE__.'::new need a widget list (ARRAY ref) as second arg' unless ref $widgets eq 'ARRAY';
-
-	my ($self) = $class->SUPER::new( $parent, -1, [-1, -1],[-1, -1], &Wx::wxNB_TOP );
-	while (scalar @$widgets > 1){
-		my $label         = shift $widgets;
-		my $panel_widgets = shift $widgets;
-		$self->AddPage( Wx::Perl::Smart::Panel->new($self, $panel_widgets, $orientation, $init_arg), $label, 0);
-	}
-	#$self->ChangeSelection(0);
-	$self;
-}
-
-1;

lib/Wx/Perl/Smart/WidgetFactory.pm

+use v5.12;
+use warnings;
+use Wx;
+
+#use Wx::Perl::RadioGroup;
+#use Wx::Perl::DisplaySlider;
+
+
+package Wx::Perl::Smart::WidgetFactory;
+our $VERSION = '0.1';
+use Scalar::Util qw(blessed looks_like_number);
+
+sub new {
+	my ($class, $admin, $parent) = @_;
+	$parent = $admin unless defined $parent;
+	return warn ((caller(0))[3].': first parameter $admin has to be a smart widget')
+		if defined $admin and ref $admin ne 'Wx::Perl::Smart::Frame';
+	return warn ((caller(0))[3].': second parameter $parent has to be a widget')
+		if defined $parent and not(blessed($parent) and $parent->isa('Wx::Window'));
+
+	my $self = bless { admin => $admin, parent => $parent};
+	$self;
+}
+
+sub Make {
+	my $self = shift;
+	# switch for a dual oo and none-oop interface
+	if (defined $self and ref $self ne __PACKAGE__){ unshift @_, $self;  $self = '' }
+
+	my @widget;
+	for my $widget_def (@_){
+		next unless defined $widget_def;
+		warn ((caller(0))[3].': need an ARRAY ref as parameter, not $widget_def'), next unless ref $widget_def eq 'ARRAY';
+
+		# eval string placeholder
+		if ($self and $self->{'admin'}){
+			for (0 .. $#{ $widget_def}) {
+				$widget_def->[$_] = $self->{'admin'}->EvalSubscribedStrings($widget_def->[$_]) unless ref $widget_def->[$_]
+			}
+		}
+		# insert missing parent into widget definition
+		unless (blessed($widget_def->[1]) and $widget_def->[1]->isa('Wx::Window')){
+			warn ((caller(0))[3].': no parent to insert into widget definition - left out second "new" paramter'), next
+				unless $self and $self->{'parent'};
+			splice ($widget_def, 1, 0, $self->{'parent'});
+		}
+
+		my $widget;
+		#if (substr($widget_def->[0],0,3) eq '---' or substr($widget_def->[0],0,3) eq '|||'){	}
+		if ($widget_def->[0] eq '-Button'){
+			warn ((caller(0))[3].': second parameter of Button definition has to be a string'), next if ref $widget_def->[2]; 
+			warn ((caller(0))[3].': third parameter of Button definition is a callback (CODE ref)'), next if ref $widget_def->[3] ne 'CODE'; 
+
+			$widget = Wx::Button->new($widget_def->[1], -1, $widget_def->[2]);
+			Wx::Event::EVT_BUTTON( $widget, $widget, $widget_def->[3] );
+		} elsif ($widget_def->[0] eq '-CheckBox'){
+			warn ((caller(0))[3].': second parameter of CheckBox definition has to be a string'), next if ref $widget_def->[2]; 
+			warn ((caller(0))[3].': thrid parameter of CheckBox definition has to be the chacked status (0|1)'), next if not looks_like_number($widget_def->[3]);
+			warn ((caller(0))[3].': forth parameter of CheckBox definition has to be a CODE ref'), next if ref $widget_def->[4] ne 'CODE'; 
+			$widget = Wx::CheckBox->new($widget_def->[1], -1, $widget_def->[2]);
+			$widget->SetValue($widget_def->[3]);
+			Wx::Event::EVT_CHECKBOX( $widget, -1, $widget_def->[4] ) if $widget_def->[4];
+		} elsif ($widget_def->[0] eq '-Textslider'){
+
+				#$widget = TextSlider->new ($widget_def->[1], @{$range_defaults{$_}}, $repaint);
+		} elsif ($widget_def->[0] eq '-ComboBox'){
+			warn ((caller(0))[3].': second paramter in ComboBox definition has to be an ARRAY ref'), next if ref $widget_def->[2] ne 'ARRAY';
+				#or ref $widget_def->[3] 
+				#or ref $widget_def->[4]
+				#or ($widget_def->[5] and ref $widget_def->[5] ne 'CODE');
+			my $textvalue = $widget_def->[3];
+			if (not defined $textvalue or not $textvalue){$textvalue = $widget_def->[2][0]   } 
+			elsif (looks_like_number($textvalue)) {$textvalue = $widget_def->[2][$textvalue] }
+			$textvalue = '' unless defined $textvalue;  # combobox doesnt like an undef in text field
+			my $length = $widget_def->[4];
+			$length = -1 unless $length;
+			$widget = Wx::ComboBox->new(
+				$widget_def->[1], -1, $textvalue, [-1,-1], [$length,-1], $widget_def->[2]
+			);
+			Wx::Event::EVT_COMBOBOX( $widget, -1, $widget_def->[5]) if $widget_def->[5];
+		}
+		push @widget, $widget if defined $widget and blessed($widget);
+	}
+	return $widget[0] if scalar @widget == 1;
+	return @widget;
+}
+
+sub GetWidgetByNr {
+	my $self = shift;
+	
+}
+
+1;

lib/Wx/Perl/TextSlider.pm

-use v5.12;
-use warnings;
-use Wx;
-
-package Wx::Perl::TextSlider;
-use base qw(Wx::Panel);
-
-sub new {
-	my ($class, $parent, $label, $default, $min, $max, $callback) = @_;
-	$default = $min if $default < $min;
-	$default = $max if $default > $max;
-    
-	my ($self) = $class->SUPER::new( $parent );
-	$self->{'min'} = $min;
-	$self->{'max'} = $max;
-	$self->{'default'} = $default;
-	$callback = sub {} unless ref $callback eq 'CODE'; 
-	my $frontlabel = Wx::StaticText->new($self, -1, "$label : ");
-	my $slider = $self->{'slider'}= Wx::Slider->new($self,-1,$default,$min,$max);
-	$slider->SetMinSize([300,-1]);
-	my $text =   $self->{'text'}  = Wx::TextCtrl->new(
-			$self, -1, $default, [-1,-1], [40, -1], &Wx::wxTE_PROCESS_ENTER| &Wx::wxTE_RIGHT
-	);
-
-	my $sizer = Wx::BoxSizer->new( &Wx::wxHORIZONTAL);
-	my $grow_center_all = &Wx::wxGROW | &Wx::wxALL| &Wx::wxALIGN_CENTER_VERTICAL;
-	$sizer->Add($frontlabel, 0, $grow_center_all, 10 );
-	$sizer->Add($slider,     1, $grow_center_all,  5 );
-	$sizer->Add($text,       0, $grow_center_all,  5 );
-
-	Wx::Event::EVT_SCROLL( $slider, sub { # text always shows current value of slider
-		$text->SetValue( $slider->GetValue) if $text->GetValue != $slider->GetValue;
-	} );
-	Wx::Event::EVT_SCROLL_THUMBRELEASE( $slider, sub {
-		#return if $slider->GetValue == $text->GetValue;
-		$text->SetValue( $slider->GetValue );
-		$callback->(); 
-	} );
-	Wx::Event::EVT_TEXT_ENTER($text, -1, sub {
-		return if $slider->GetValue == $text->GetValue;
-		$slider->SetValue( $text->GetValue );
-		$callback->(); 
-	});
-	Wx::Event::EVT_KILL_FOCUS($text, sub {
-		$_[1]->Skip;
-		if ($slider->GetValue != $text->GetValue){
-			$slider->SetValue( $text->GetValue );
-			$callback->();
-		}
-	});
-	Wx::Event::EVT_MIDDLE_DOWN( $slider, sub { $self->ResetValue; $callback->() } );
-	Wx::Event::EVT_LEFT_DCLICK( $slider, sub { $self->ResetValue; $callback->() } );
-    
-    $self->SetSizerAndFit( $sizer );
-    $self->ResetValue();
-    $self;
-}
-
-sub GetValue {
-	my ($self) = shift;
-	$self->{'text'}->GetValue;
-}
-sub SetValue{
-	my ($self, $value) = @_;
-	$value = 0 unless defined $value;
-	$value = 0 + $value;
-	return if $value < $self->{'min'};
-	return if $value > $self->{'max'};
-	$self->{'text'}->SetValue( $value );
-	$self->{'slider'}->SetValue( $value );
-}
-sub ResetValue {
-	my ($self) = shift;
-	$self->SetValue( $self->{'default'} );
-}
-
-1;
+---
+rotashine:
+  amplitude_x: 90
+  amplitude_y: 180
+  app_mode: 0
+  density: 42
+  flow_colour: 2
+  format_select: PNG
+  frequency_x: 5
+  frequency_y: 3
+  friction: 8
+  length: 32
+  rotation: 1
+  rotation_dir: 0
+  scale_colour: 1
+  start_colour: 0
+  thickness: 1
+  y_invers: ''
+  zoom: 0

lib/harmonograph.pl

 #!/usr/bin/perl
-
-use v5.12;
-use warnings;
-use Wx;
+
+use v5.12;
+use warnings;
+use Wx;
 use Wx::Perl::DrawMap;
-use Wx::Perl::TextSlider;
-use Wx::Perl::RadioGroup;
+use Wx::Perl::DisplaySlider;
+use Wx::Perl::RadioGroup;
 use Wx::Perl::Smart::Frame;
-use Colour::Flow;
-use Math::Trig;
-use File::Spec;
-use YAML::Tiny;
-
-package Harmonograph;
-our $VERSION = '0.93';
-use base qw(Wx::App);
-
-my $fav_file = 'favs.yml'; 
-my $l18n_file = 'localisation.yaml';
-my $language = 'english';
-
-sub OnInit {
+use Colour::Flow;
+use Math::Trig;
+use File::Spec;
+use YAML::Tiny;
+
+package Harmonograph;
+our $VERSION = '0.94';
+use base qw(Wx::App);
+
+my $fav_file = 'favs.yaml'; 
+my $l18n_file = 'localisation.yaml';
+my $language = 'english';
+
+sub OnInit {
 	my $app = shift;
 
-	# load localisation texts in chosen language
-	my ($v, $dir, $f) = File::Spec->splitpath(__FILE__);
+	# load localisation texts in chosen language
+	my ($v, $dir, $f) = File::Spec->splitpath(__FILE__);
 	$l18n_file = File::Spec->catfile($dir, $l18n_file) if $dir;
-	die "localisation file $l18n_file is missing!" unless -e $l18n_file;
+	die "localisation file $l18n_file is missing!" unless -e $l18n_file;
 	my %l18n = %{YAML::Tiny->read( $l18n_file )->[0]{$language}};
-	$app->{'l18n'} = \%l18n;
+	$app->{'l18n'} = \%l18n;
 
 	# loading the numbers of the remembered favorites
 	$app->{'favorites'} = -e $fav_file ? YAML::Tiny->read( $fav_file ) : YAML::Tiny->new;
 	my @remembered_pic_names = ref $app->{'favorites'}->[0] eq 'HASH' ? keys $app->{'favorites'}->[0] : ();
 
 	# making UI
-	my $frame = $app->{'frame'} = Wx::Perl::Smart::Frame->new(__PACKAGE__." $VERSION");
+	my $frame = $app->{'frame'} = Wx::Perl::Smart::Frame->new(__PACKAGE__." $VERSION", 'fixed_size');
+	$frame->SubscribeStrings( $app->{'l18n'} );
 	my $remember= sub { $frame->SetValues( $app->{'favorites'}[0]{ $_[0]->GetValue() } ); $app->Repaint()};
 	my $repaint = sub { $app->Repaint() };
 	my $boardsize = Wx::GetDisplaySize()->GetHeight() - 250;
-	my $origin_offset = $app->{'origin_offset'} = $boardsize / 2;
+	my $origin_offset = $app->{'origin_offset'} = $boardsize / 2;
 	my $max_amp = $app->{'max_amp'} = $origin_offset - 10;        # max amplitude
-	my %range_defaults = (# label, min, max, init
-		frequency_x => ['X',               1, 1,  30], frequency_y => ['Y',               1,  1,   30],
-		amplitude_x => ['X',               0, 0, 360], amplitude_y => ['Y',               0,  0,  360],
-		rotation    => [$l18n{'amount'},   1, 0,  30], friction    => [$l18n{'friction'}, 0,  0,  200],
-		length      => [$l18n{'length'},  12, 1, 100], density     => [$l18n{'density'},100,  1,  100],
-		thickness   => [$l18n{'thickness'},1, 1,  12], zoom        => [$l18n{'zoom'},     0,-10,   10], 
-		start_colour=> [$l18n{'start'},    0, 0,1500], flow_colour => [$l18n{'flow'},     0,  0,   60],
-		scale_colour=> [$l18n{'scale'},    1, 1,   4],
+	my %range_defaults = (# label, min, max, init
+		frequency_x => ['X',               1, 1,  30], frequency_y => ['Y',               1,  1,   30],
+		amplitude_x => ['X',               0, 0, 360], amplitude_y => ['Y',               0,  0,  360],
+		rotation    => [$l18n{'amount'},   1, 0,  30], friction    => [$l18n{'friction'}, 0,  0,  200],
+		length      => [$l18n{'length'},  12, 1, 100], density     => [$l18n{'density'},100,  1,  100],
+		thickness   => [$l18n{'thickness'},1, 1,  12], zoom        => [$l18n{'zoom'},     0,-10,   10], 
+		start_colour=> [$l18n{'start'},    0, 0,1500], flow_colour => [$l18n{'flow'},     0,  0,   60],
+		scale_colour=> [$l18n{'scale'},    1, 1,   4],
 	);
-	$frame->SubscribeStrings( YAML::Tiny->read( $l18n_file )->[0]{$language} );
 	$frame->SubscribeWidgets
-		({$_         => Wx::Perl::TextSlider->new ($frame, @{$range_defaults{$_}}, $repaint)}) for keys %range_defaults;
+		({$_         => Wx::Perl::DisplaySlider->new($frame, @{$range_defaults{$_}}, $repaint)}) for keys %range_defaults;
 	$frame->SubscribeWidgets({
 		drawboard    => Wx::Perl::DrawMap->new($frame, $boardsize),
 		fav_select   => [-ComboBox => \@remembered_pic_names, 0, -1, $remember],
 		format_select=> [-ComboBox => [qw(PNG JPG TIFF BMP XPM)], 0, 70       ],
-		save         => [-Button   => $l18n{'save'},      sub {$app->Save()    }],
-		save_all     => [-Button   => $l18n{'all'},       sub {$app->SaveAll() }],
-		remember     => [-Button   => $l18n{'remember'},  sub {$app->Remember()}],
-		forget       => [-Button   => $l18n{'forget'},    sub {$app->Forget()  }],
-		no_phase     => [-Button   => $l18n{'no'},        sub {$frame->SetValues(amplitude_x =>  0, amplitude_y =>   0);$app->Repaint()}],
-		closed_phase => [-Button   => $l18n{'closed'},    sub {$frame->SetValues(amplitude_x => 90, amplitude_y =>  90);$app->Repaint()}],
-		open_phase   => [-Button   => $l18n{'open'},      sub {$frame->SetValues(amplitude_x => 90, amplitude_y => 180);$app->Repaint()}],
-		y_invers     => [-CheckBox => $l18n{'y_inverse'}, 0, $repaint],
+		save         => [-Button   => '~save',     sub {$app->Save()    }],
+		save_all     => [-Button   => '~all',      sub {$app->SaveAll() }],
+		remember     => [-Button   => '~remember', sub {$app->Remember()}],
+		forget       => [-Button   => '~forget',   sub {$app->Forget()  }],
+		no_phase     => [-Button   => '~no',       sub {$frame->SetValues(amplitude_x =>  0, amplitude_y =>   0);$app->Repaint()}],
+		closed_phase => [-Button   => '~closed',   sub {$frame->SetValues(amplitude_x => 90, amplitude_y =>  90);$app->Repaint()}],
+		open_phase   => [-Button   => '~open',     sub {$frame->SetValues(amplitude_x => 90, amplitude_y => 180);$app->Repaint()}],
+		y_invers     => [-CheckBox => '~y_inverse', 0,  $repaint],
 		rotation_dir => Wx::Perl::RadioGroup->new($frame, [@l18n{qw(no left right)}],       0, &Wx::wxHORIZONTAL, $repaint),
 		app_mode     => Wx::Perl::RadioGroup->new($frame, [@l18n{qw(lateral rotary free)}], 0, &Wx::wxHORIZONTAL, sub{}),
 	});
 
 	$frame->SetSmartLayout(
 	{flags => &Wx::wxGROW|&Wx::wxALL},
-	[	# left part
-		'<drawboard>',
-		10,
-		{border => 10, flags => &Wx::wxALL|&Wx::wxGROW},
-		'<fav_select>',
-		['<format_select>', 10,'<save>', 10, '<save_all>', \1, '<forget>', 10, '<remember>'],
+	[	# left part
+		'<drawboard>',
+		10,
+		{border => 10, flags => &Wx::wxALL|&Wx::wxGROW},
+		'<fav_select>',
+		['<format_select>', 10,'<save>', 10, '<save_all>', \1, '<forget>', 10, '<remember>'],
 	],[ # right half
-		-TabbedBox =>  [ 
-			$l18n{'oscillators'} => [[
+		-TabbedBox => [ 
+			'~oscillators' =>[
 				{border => 5, flags => &Wx::wxGROW|&Wx::wxALL},
-				[$l18n{'mode'}.':', '<app_mode>'],
-				-LabeledBox => [ $l18n{'frequency'} => [qw( <frequency_x> <frequency_y>)]], #  <y_invers>
-				-LabeledBox => [ $l18n{'start_amp'} => [
-					'<amplitude_x>',
-					'<amplitude_y>',
-					5,
-					[$l18n{'phase'}.':', \1, '<no_phase>', \1,'<closed_phase>', \1, '<open_phase>', 5],
-					5,
+				['~mode :', '<app_mode>'],
+				-LabeledBox =>['~frequency' =>[qw( <frequency_x> <frequency_y>)]], #<y_invers>
+				-LabeledBox =>['~start_amp' =>[qw( <amplitude_x> <amplitude_y>),
+					{border => 5, flags => &Wx::wxALL|&Wx::wxGROW},
+					['~phase :', \1, '<no_phase>', \1,'<closed_phase>', \1, '<open_phase>'],
 				]],
-				-LabeledBox => [ $l18n{'rotation'}  => [qw( <rotation_dir> <rotation>              )]],
-				{border => 10},								'<friction>', 
-			]],
-			$l18n{'visuals'} => [[
-				{border => 5, flags => &Wx::wxGROW|&Wx::wxALL},
-				-LabeledBox => [ $l18n{'line'}  => [qw( <length> <density>                         )]], # <thickness>
-				-LabeledBox => [ $l18n{'color'} => [qw( <start_colour> <flow_colour> <scale_colour>)]],
-				{border => 10},							'<zoom>',
-			]]
-		],
-	]); #~line
+				-LabeledBox =>[ '~rotation ' =>[qw( <rotation_dir>  <rotation> )]],
+				{border => 10}, '<friction>', 
+			],
+			'~visuals' => [
+				{border => 5, flags => &Wx::wxGROW|&Wx::wxALL},
+				-LabeledBox =>['~line'  =>[qw( <length>       <density>                   )]], #<thickness>
+				-LabeledBox =>['~color' =>[qw( <start_colour> <flow_colour> <scale_colour>)]],
+				{border => 10},'<zoom>',
+			],
+		],
+	]);
 	$frame->ResetValues();
-	$app->Repaint();
+	$app->Repaint();
 	$app->SetTopWindow($frame);
-	1;
-}
+	1;
+}
 
-
-sub Remember {
+
+
+sub Remember {
 	my $app = shift;
-	my $frame = $app->{'frame'};
+	my $frame = $app->{'frame'};
 	my $cb = $frame->GetSubscribedWidget('fav_select'); # combo box
 	my $name = Wx::GetTextFromUser
-		($app->{'l18n'}{'ask_for_a_name'}, __PACKAGE__." $VERSION", '', $frame);
+		($app->{'l18n'}{'ask_for_a_name'}, __PACKAGE__." $VERSION", '', $frame);
 	$name = Wx::GetTextFromUser
 		($app->{'l18n'}{'ask_another_name'}, __PACKAGE__." $VERSION", '', $frame)
 			while exists $app->{'favorites'}[0]{$name} or not $name;
 	my $values = $frame->GetValues;
-	delete $values->{'fav_select'};          # prevent bad recursion, restoring state that was when saved this one
-	$app->{'favorites'}[0]{$name} = $values;
-	$cb->SetValue($name);
-	$cb->Insert($name, 0);
-	$app->{'favorites'}->write( $fav_file );
-}
-sub Forget {
+	delete $values->{'fav_select'};          # prevent bad recursion, restoring state that was when saved this one
+	$app->{'favorites'}[0]{$name} = $values;
+	$cb->SetValue($name);
+	$cb->Insert($name, 0);
+	$app->{'favorites'}->write( $fav_file );
+}
+sub Forget {
 	my $app = shift;
-	my $frame = $app->{'frame'};
-	my $cb = $frame->GetSubscribedWidget('fav_select');
-	return if $cb->IsEmpty;
-	my $name = $cb->GetValue();
-	$cb->Delete( $cb->FindString($name) );
-	delete $app->{'favorites'}[0]{$name};
+	my $frame = $app->{'frame'};
+	my $cb = $frame->GetSubscribedWidget('fav_select');
+	return if $cb->IsEmpty;
+	my $name = $cb->GetValue();
+	$cb->Delete( $cb->FindString($name) );
+	delete $app->{'favorites'}[0]{$name};
 	if ($cb->IsEmpty){
-		$cb->SetValue('');
+		$cb->SetValue('');
 		$frame->ResetValues();
-		$app->{'favorites'} =  YAML::Tiny->new;
-	} else {
-		$cb->SetSelection(0);
-		$frame->SetValues( $app->{'favorites'}[0]{ $cb->GetValue() } );
-		delete $app->{'favorites'}[0]{$name};
-	}
-	$app->Repaint();
-	$app->{'favorites'}->write( $fav_file );
-}
-
-
-
-sub Save {
+		$app->{'favorites'} =  YAML::Tiny->new;
+	} else {
+		$cb->SetSelection(0);
+		$frame->SetValues( $app->{'favorites'}[0]{ $cb->GetValue() } );
+		delete $app->{'favorites'}[0]{$name};
+	}
+	$app->Repaint();
+	$app->{'favorites'}->write( $fav_file );
+}
+
+
+
+sub Save {
 	my $app = shift;
-	my $format = lc $app->{'frame'}->GetSubscribedWidget('format_select')->GetValue();
-	my $file = Wx::FileSelector(
+	my $format = lc $app->{'frame'}->GetSubscribedWidget('format_select')->GetValue();
+	my $file = Wx::FileSelector(
 		$app->{'l18n'}{'save_under'}.' '.uc($format),            '.', 
 		$app->{'frame'}->GetSubscribedWidget('fav_select')->GetValue().".$format",
-		'', '(*)|*', &Wx::wxFD_SAVE, $app->{'frame'}
-	);
-	$app->{'frame'}->GetSubscribedWidget('drawboard')->SaveAsFile($file, $format) if $file;
-}
-sub SaveAll {
+		'', '(*)|*', &Wx::wxFD_SAVE, $app->{'frame'}
+	);
+	$app->{'frame'}->GetSubscribedWidget('drawboard')->SaveAsFile($file, $format) if $file;
+}
+sub SaveAll {
 	my $app = shift;
 	my $frame = $app->{'frame'};
-	my $format = lc $app->{'frame'}->GetSubscribedWidget('format_select')->GetValue();
-	my $dir = Wx::DirSelector( $app->{'l18n'}{'save_all_under'}.' '.uc($format), '.', 0, [-1,-1], $frame);
-	return unless -d $dir;
-	my $values = $frame->GetValues();
-	for (keys $app->{'favorites'}[0]) {
+	my $format = lc $app->{'frame'}->GetSubscribedWidget('format_select')->GetValue();
+	my $dir = Wx::DirSelector( $app->{'l18n'}{'save_all_under'}.' '.uc($format), '.', 0, [-1,-1], $frame);
+	return unless -d $dir;
+	my $values = $frame->GetValues();
+	for (keys $app->{'favorites'}[0]) {
 		$frame->SetValues( $app->{'favorites'}[0]{$_} );
-		$app->Repaint();
+		$app->Repaint();
 		my $file = File::Spec->catfile($dir, "$_.$format" );
 		$frame->GetSubscribedWidget('drawboard')->SaveAsFile($file, $format);
-	}
-	$frame->SetValues($values);
-	$app->Repaint();
-}
-
-
-
-sub Repaint {
-	my $app = shift;
+	}
+	$frame->SetValues($values);
+	$app->Repaint();
+}
+
+
+
+sub Repaint {
+	my $app = shift;
 	my $board = $app->{'frame'}->GetSubscribedWidget('drawboard');
 	my $v = $app->{'frame'}->GetValues; # values
 
 	my $origin_offset   = $app->{'origin_offset'};
-	my $max_amp         = $app->{'max_amp'} * (1.2**$v->{'zoom'});
+	my $max_amp         = $app->{'max_amp'} * (1.2 ** $v->{'zoom'});
 	my $win_size_factor = $max_amp / 10;
 	my $pi = 3.1415926536; 
 	my $xangle = $v->{'amplitude_x'} / 180 * $pi;                               # beginning with start amplitudes
 	$dy *= 0.2 * $step_size;
 	my $friction_factor =  (1 - (0.00005 * $v->{'friction'})) ** $step_size;
 	my $steps = $v->{'length'} * 100 * $v->{'density'};
-
-	$dy = $v->{'y_invers'} ? - $dy : $dy;
-	#my $x = Math::Trig::asin( ($v->{'amplitude_x'} - $max_amp)/$max_amp );
-	#my $y = Math::Trig::asin( ($v->{'amplitude_y'} - $max_amp)/$max_amp );
-	#my $drot = $v->{'rotation'} / 2000;
-	#my $rota_dir = $v->{'rotation_dir'};
-	#$drot = - $drot if $rota_dir == 2;
-	#my $rot = 0;# deg2rad($degrees);
-	my $colour_flow = Colour::Flow->new(
-		 $v->{'scale_colour'},
-		($v->{'flow_colour'} ? 40 / $v->{'flow_colour'} * $v->{'density'} : 0), # change rate
-		 $v->{'start_colour'},
+
+	$dy = $v->{'y_invers'} ? - $dy : $dy;
+	#my $x = Math::Trig::asin( ($v->{'amplitude_x'} - $max_amp)/$max_amp );
+	#my $y = Math::Trig::asin( ($v->{'amplitude_y'} - $max_amp)/$max_amp );
+	#my $drot = $v->{'rotation'} / 2000;
+	#my $rota_dir = $v->{'rotation_dir'};
+	#$drot = - $drot if $rota_dir == 2;
+	#my $rot = 0;# deg2rad($degrees);
+	my $colour_flow = Colour::Flow->new(
+		 $v->{'scale_colour'},
+		($v->{'flow_colour'} ? 40 / $v->{'flow_colour'} * $v->{'density'} : 0), # change rate
+		 $v->{'start_colour'},
 	);
 	$board->Colour( $colour_flow->get_rgb() );
 	$board->NewDrawing();
 		$yangle += $dy;
 		$max_amp *= $friction_factor;
 
-		#my $xs = sin($x += $dx);
-		#my $ys = sin($y += $dy);
-		#$rot += $drot;
-		#($xs, $ys) = rotate($xs, $ys, $rot) if $rota_dir;
-		$board->Colour( $colour_flow->get_rgb() ) if $colour_flow->next_step(); 
-
-		#$app->{'dc'}->DrawPoint( ($xs*$cur_amp*$value->{'zoom'})+$midoffset,
+		#my $xs = sin($x += $dx);
+		#my $ys = sin($y += $dy);
+		#$rot += $drot;
+		#($xs, $ys) = rotate($xs, $ys, $rot) if $rota_dir;
+		$board->Colour( $colour_flow->get_rgb() ) if $colour_flow->next_step(); 
+
+		#$app->{'dc'}->DrawPoint( ($xs*$cur_amp*$value->{'zoom'})+$midoffset,
 		#                         ($ys*$cur_amp*$value->{'zoom'})+$midoffset );
-
+
 		$board->Point(sin($xangle) * $max_amp + $origin_offset, 
 					 -sin($yangle) * $max_amp + $origin_offset);
 	}
 	$board->PublishDrawing();
-}
-sub rotate {
-	my ($x, $y, $r) = @_;
-	my ($sinr, $cosr) = (sin($r), cos($r));
-	return ($cosr*$x - $sinr*$y, $sinr*$x + $cosr*$y);
-}
-
-package main;
-Harmonograph->new->MainLoop;
+}
+sub rotate {
+	my ($x, $y, $r) = @_;
+	my ($sinr, $cosr) = (sin($r), cos($r));
+	return ($cosr*$x - $sinr*$y, $sinr*$x + $cosr*$y);
+}
+
+package main;
+Harmonograph->new->MainLoop;