Commits

Herbert Breunung  committed 9c00dd1 Draft

0.93 got phases right new modes started

  • Participants
  • Parent commits afb45ec

Comments (0)

Files changed (6)

File lib/Wx/Perl/Smart/Factory.pm

 			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(

File lib/Wx/Perl/Smart/Frame.pm

 sub new {
 	my ($class, $label, $mode) = @_; #$parent, $widgets, $border
 	my ($self) = $class->SUPER::new(
-		undef, -1, $label, [1,1], [-1,-1],
-		&Wx::wxCAPTION | &Wx::wxCLOSE_BOX | &Wx::wxFRAME_TOOL_WINDOW | &Wx::wxSYSTEM_MENU #| &Wx::wxRESIZE_BORDER
+		undef, -1, $label, [1,1], [-1,-1], &Wx::wxDEFAULT_FRAME_STYLE ^ &Wx::wxRESIZE_BORDER
 	);
 	$self->SetIcon( Wx::GetWxPerlIcon() );
 	$self->{'mode'} = $mode;
 	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->{'subwidget'}{$name};
+		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->{'subwidget'}{$name} = $widget;
-		$self->{'default_val'}{$name} = $widget->GetValue if $widget_io{ref $widget};
+		$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->{'subwidget'}{$name};
-		$self->{'subwidget'}{$name} = '';
-		$self->{'default_val'}{$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} = '';
 	}
 }
 sub GetSubscribedWidget {
 	my ($self) = shift;
 	my @widget;
 	for my $name (@_){
-		warn ((caller(0))[3].": there is no widget subscribed as $name") unless exists $self->{'subwidget'}{$name};
-		push @widget, $self->{'subwidget'}{$name};
+		warn ((caller(0))[3].": there is no widget subscribed as $name") unless 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->{'subwidget'}{shift;}}
+#sub w { shift->GetSubscribedWidget(@_) }
+#sub WidgetSubscribed {shift->{'managed'}{'widget'}{shift;}}
+sub SubscribeStrings {
+	my ($self, $string) = @_;
+	warn ((caller(0))[3].': needs a HASH ref as parameter') unless ref $string eq 'HASH';
+	while (my ($name, $value) = each %$string) {
+		$self->{'managed'}{'string'}{$name} = $value;
+	}
+	$self;
+}
+
+sub GetSubscribedString {
+	my ($self, $name) = @_;
+	$self->{'managed'}{'string'}{$name};
+}
+
 
 
 sub GetValues {
 	my ($self) = shift;
 	my %value;
-	$value{$_} = $self->{'subwidget'}{$_}->GetValue() for keys %{$self->{'default_val'}};
+	$value{$_} = $self->{'managed'}{'widget'}{$_}->GetValue() for keys %{$self->{'managed'}{'default_val'}};
 	return \%value;
 }
 sub SetValues {
 	my ($self, $value) = @_;
+	$value = {$value, @_} if scalar(@_) % 2 == 1 and ref $value ne 'HASH';
 	return warn ((caller(0))[3].': need a Hashref a parameter') unless ref $value eq 'HASH';
 	while (my ($name, $value) = each %$value) {
 		warn ((caller(0))[3].": $name is not a subscribed widget"), next
-			unless exists $self->{'default_val'}{$name};
-		$self->{'subwidget'}{$name}->SetValue(  $value );
+			unless exists $self->{'managed'}{'default_val'}{$name};
+		$self->{'managed'}{'widget'}{$name}->SetValue(  $value );
 	}
 	$self;
 }
 	my ($self) = shift;
 	my ($name) = shift // ':all';   # value name
 	return warn ((caller(0))[3].": $name is not a subscribed widget")
-		unless exists $self->{'default_val'}{$name} or $name eq ':all';
+		unless exists $self->{'managed'}{'default_val'}{$name} or $name eq ':all';
 	if ($name eq ':all'){
-		$self->{'subwidget'}{$_}->SetValue( $self->{'default_val'}{$_} )
-			for keys %{ $self->{'default_val'} };
+		$self->{'managed'}{'widget'}{$_}->SetValue( $self->{'managed'}{'default_val'}{$_} )
+			for keys %{ $self->{'managed'}{'default_val'} };
 	} 
-	else { $self->{'subwidget'}{$name}->SetValue( $self->{'default_val'}{$name} ) }
+	else { $self->{'managed'}{'widget'}{$name}->SetValue( $self->{'managed'}{'default_val'}{$name} ) }
 	$self;
 }
 

File lib/Wx/Perl/Smart/Sizer.pm

 		if defined $orientation and $orientation != &Wx::wxVERTICAL and $orientation != &Wx::wxHORIZONTAL;
 	die __PACKAGE__.'::new needs a hash ref as forth parameter' if defined $init_arg and ref $init_arg ne 'HASH';
 
+	$orientation     =  &Wx::wxHORIZONTAL unless defined $orientation;
 	my %default_arg = (
-		flags        => &Wx::wxLEFT|&Wx::wxRIGHT|&Wx::wxGROW,
+		flags        => ($orientation == &Wx::wxHORIZONTAL 
+							? &Wx::wxALIGN_CENTER_VERTICAL | &Wx::wxALIGN_LEFT
+							: &Wx::wxALIGN_TOP | &Wx::wxLEFT | &Wx::wxRIGHT|&Wx::wxGROW),
 		border       => 0,
 		add_callback => sub {},
 	);
 	# sanitize arguments
-	$orientation     =  &Wx::wxHORIZONTAL unless defined $orientation;
 	my (%arg, @arg_stack);
 	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 $daddy = $parent;
-	$daddy = $daddy->GetParent while $daddy->GetParent;
-	$daddy = '' unless ref $daddy eq 'Wx::Perl::Smart::Frame' or ref $daddy eq 'Wx::Perl::Smart::Panel';
+	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';
 
+	# create the sizer
 	my ($self) = $class->SUPER::new( $orientation );
 	for (my $pos = 0; $pos < scalar @$widgets; $pos++) {
-		my $widget = $widgets->[$pos];
-		my ($proportion) = (0);
+		my $widget = $widgets->[$pos]; 	# pick next widgets in the list
+
+		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'){
 			my %old_arg = %arg;
 			push @arg_stack, \%old_arg;
 				}
 			}
 			elsif (substr($widget, 0, 1) eq '<' and substr($widget, -1) eq '>') {
-				next unless $daddy;
-				$widget = $daddy->GetSubscribedWidget( substr($widget, 1, -1) );
+				next unless $root;
+				$widget = $root->GetSubscribedWidget( substr($widget, 1, -1) );
 				next unless $widget;
 			}
 			elsif (looks_like_number($widget)) {
 		$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;

File lib/favs.yml

 ---
-buntwave:
-  amplitude_x: 270
-  amplitude_y: 270
-  density: 687
-  fav_select: schaufelrad
-  flow_colour: 13
-  frequency_x: 2
+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: 9
-  length: 19
-  rotation: 2
+  friction: 8
+  length: 32
+  rotation: 1
+  rotation_dir: 0
   scale_colour: 1
   start_colour: 0
   thickness: 1
   y_invers: ''
   zoom: 0
-ringsonne:
-  amplitude_x: 270
-  amplitude_y: 270
-  density: 90
-  fav_select: buntwave
-  flow_colour: 3
-  frequency_x: 28
-  frequency_y: 30
-  friction: 0
-  length: 29
-  rotation: 29
-  rotation_dir: 1
-  scale_colour: 1
-  start_colour: 0
-  thickness: 1
-  y_invers: ''
-  zoom: '-2'
-rotschaufel:
-  amplitude_x: 270
-  amplitude_y: 270
-  density: 114
-  flow_colour: 5
-  frequency_x: 3
-  frequency_y: 4
-  friction: 5
-  length: 12
-  rotation: 2
-  rotation_dir: 1
-  scale_colour: 1
-  start_colour: 0
-  thickness: 1
-  y_invers: ''
-  zoom: '-2'
-schaufelrad:
-  amplitude_x: 270
-  amplitude_y: 270
-  density: 114
-  flow_colour: 2
-  frequency_x: 3
-  frequency_y: 4
-  friction: 5
-  length: 12
-  rotation: 2
-  rotation_dir: 1
-  scale_colour: 1
-  start_colour: 892
-  thickness: 1
-  y_invers: ''
-  zoom: '-2'

File lib/harmonograph.pl

 use YAML::Tiny;
 
 package Harmonograph;
-our $VERSION = '0.92';
+our $VERSION = '0.93';
 use base qw(Wx::App);
 
 my $fav_file = 'favs.yml'; 
 my $l18n_file = 'localisation.yaml';
-my $language = 'german';
+my $language = 'english';
 
 sub OnInit {
 	my $app = shift;
 
 	# making UI
 	my $frame = $app->{'frame'} = Wx::Perl::Smart::Frame->new(__PACKAGE__." $VERSION");
-
+	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 $max_amp = $app->{'max_amp'} = $origin_offset - 10;        # max amplitude
-	my $repaint = sub { $app->Repaint() };
 	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,   30],
+		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;
 	$frame->SubscribeWidgets({
 		drawboard    => Wx::Perl::DrawMap->new($frame, $boardsize),
-		fav_select   => [-ComboBox => \@remembered_pic_names, 0, -1, sub {
-										$frame->SetValues( $app->{'favorites'}[0]{ $_[0]->GetValue() } );$app->Repaint()}],
+		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()  }],
+		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],
-		rotation_dir => Wx::Perl::RadioGroup->new($frame, [@l18n{'no','left','right'}], 0, &Wx::wxHORIZONTAL, $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([
-		# left part
+	$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>'],
-	],[ # right half
+	],[ # right half
 		-TabbedBox =>  [ 
 			$l18n{'oscillators'} => [[
-				{border => 5, flags => &Wx::wxGROW|&Wx::wxALL},
-				-LabeledBox => [ $l18n{'frequency'} => [qw( <frequency_x> <frequency_y> <y_invers> )]],
-				-LabeledBox => [ $l18n{'start_amp'} => [qw( <amplitude_x> <amplitude_y>            )]],
+				{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,
+				]],
 				-LabeledBox => [ $l18n{'rotation'}  => [qw( <rotation_dir> <rotation>              )]],
 				{border => 10},								'<friction>', 
 			]],
 				-LabeledBox => [ $l18n{'line'}  => [qw( <length> <density>                         )]], # <thickness>
 				-LabeledBox => [ $l18n{'color'} => [qw( <start_colour> <flow_colour> <scale_colour>)]],
 				{border => 10},							'<zoom>',
-			]]
+			]]
 		],
-	],);#~line
+	]); #~line
 	$frame->ResetValues();
 	$app->Repaint();
 	$app->SetTopWindow($frame);
 sub Remember {
 	my $app = shift;
 	my $frame = $app->{'frame'};
-	my $cb = $frame->w('fav_select'); # combo box
+	my $cb = $frame->GetSubscribedWidget('fav_select'); # combo box
 	my $name = Wx::GetTextFromUser
 		($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;
-	$app->{'favorites'}[0]{$name} = $app->{'frame'}->GetValues;
+			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 {
-	my $app = shift;
-	my $cb = $app->{'frame'}->w('fav_select');
+	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};
-	if ($cb->IsEmpty){
+	if ($cb->IsEmpty){
 		$cb->SetValue('');
-		$app->{'frame'}->ResetValues();
+		$frame->ResetValues();
 		$app->{'favorites'} =  YAML::Tiny->new;
 	} else {
 		$cb->SetSelection(0);
-		$app->SetValues( $app->{'favorites'}[0]{ $cb->GetValue() } );
+		$frame->SetValues( $app->{'favorites'}[0]{ $cb->GetValue() } );
 		delete $app->{'favorites'}[0]{$name};
 	}
 	$app->Repaint();
 
 sub Save {
 	my $app = shift;
-	my $format = lc $app->{'frame'}->w('format_select')->GetValue();
+	my $format = lc $app->{'frame'}->GetSubscribedWidget('format_select')->GetValue();
 	my $file = Wx::FileSelector(
 		$app->{'l18n'}{'save_under'}.' '.uc($format),            '.', 
-		$app->{'frame'}->w('fav_select')->GetValue().".$format",  '',
-		'(*)|*', &Wx::wxFD_SAVE, $app->{'frame'}
+		$app->{'frame'}->GetSubscribedWidget('fav_select')->GetValue().".$format",
+		'', '(*)|*', &Wx::wxFD_SAVE, $app->{'frame'}
 	);
-	$app->{'frame'}->w('drawboard')->SaveAsFile($file, $format) if $file;
+	$app->{'frame'}->GetSubscribedWidget('drawboard')->SaveAsFile($file, $format) if $file;
 }
 sub SaveAll {
 	my $app = shift;
 	my $frame = $app->{'frame'};
-	my $format = lc $app->{'frame'}->w('format_select')->GetValue();
+	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();
 		$frame->SetValues( $app->{'favorites'}[0]{$_} );
 		$app->Repaint();
 		my $file = File::Spec->catfile($dir, "$_.$format" );
-		$frame->w('drawboard')->SaveAsFile($file, $format);
+		$frame->GetSubscribedWidget('drawboard')->SaveAsFile($file, $format);
 	}
 	$frame->SetValues($values);
 	$app->Repaint();
 
 sub Repaint {
 	my $app = shift;
-	my $board = $app->{'frame'}->w('drawboard');
+	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 $win_size_factor = $max_amp / 10;
 	my $pi = 3.1415926536; 
-	my $xangle = $v->{'amplitude_x'} / 360 * $pi;                               # beginning with start amplitudes
-	my $yangle = $v->{'amplitude_y'} / 360 * $pi;
+	my $xangle = $v->{'amplitude_x'} / 180 * $pi;                               # beginning with start amplitudes
+	my $yangle = $v->{'amplitude_y'} / 180 * $pi;
 	my $dx = $v->{'frequency_x'};                                               # one step of the oscillator rotation 
 	my $dy = $v->{'frequency_y'};
 	my $max_freq = $dx > $dy ? $dx : $dy;
 	my $friction_factor =  (1 - (0.00005 * $v->{'friction'})) ** $step_size;
 	my $steps = $v->{'length'} * 100 * $v->{'density'};
 
-	#$dy = $v->{'y_invers'} ? - $dy : $dy;
+	$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 $rot = 0;# deg2rad($degrees);
 	my $colour_flow = Colour::Flow->new(
 		 $v->{'scale_colour'},
-		($v->{'flow_colour'} ? 10 / $v->{'flow_colour'} * $v->{'density'} : 0), # change rate
+		($v->{'flow_colour'} ? 40 / $v->{'flow_colour'} * $v->{'density'} : 0), # change rate
 		 $v->{'start_colour'},
 	);
 	$board->Colour( $colour_flow->get_rgb() );
 		#                         ($ys*$cur_amp*$value->{'zoom'})+$midoffset );
 
 		$board->Point(sin($xangle) * $max_amp + $origin_offset, 
-					  sin($yangle) * $max_amp + $origin_offset);
+					 -sin($yangle) * $max_amp + $origin_offset);
 	}
 	$board->PublishDrawing();
 }

File lib/localisation.yaml

   amount: Amount
   ask_another_name: 'Please select another name or delete the other memory first.'
   ask_for_a_name: 'Remember under which name ?'
+  closed: Closed
   color: Color
   density: Density
-  line: Line
   flow: Flow
   forget: Forget
-  frequency: Frequency
+  free: Free
+  frequency: 'Frequency (Hz)'
   friction: Friction
+  lateral: Lateral
+  line: Line
   left: Left
   length: Length
-  no: 'No'
+  mode: Mode
+  no: No
+  open: Open
   oscillators: Oscillators
+  phase: Phase
   remember: Remember
   right: Right
+  rotary: Rotary
   rotation: Rotation
   save: 'Save'
   save_all_under: 'Choose Directory where to Save All Remebered as'
   save_under: 'Save Picture in the File Format'
   scale: Scale
   start: Start
-  start_amp: 'Starting Amplitude'
+  start_amp: 'Starting Amplitude (DEG)'
   thickness: Thickness
   visuals: Visuals
   y_inverse: 'Y - Inverse Direction'
   amount: Betrag
   ask_another_name: 'Bitte anderen Namen waehlen, oder Vorhandenes vorher loeschen.'
   ask_for_a_name: 'Unter welchem Namen merken ?'
+  closed: Geschlossen
   color: Farbe
   density: Dichte
-  line: Linie
   flow: Verlauf
   forget: Vergiss
-  frequency: Frequenz
+  free: Frei
+  frequency: 'Frequenz (Hz)'
   friction: Reibung
+  lateral: Linear
   left: Links
   length: Laenge
+  line: Linie
   thickness: Dicke
+  mode: Modus
   no: Keine
+  open: Offen
   oscillators: Oszillatoren
+  phase: Phase
   remember: Merke
   right: Rechts
+  rotary: Drehend
   rotation: Rotation
   save: 'Speichern'
   save_all_under: 'Waehle Verzeichnis wo alle Gemerkten gespeichert werden als'
   save_under: 'Speichere Bild in Dateiformat'
   scale: Skala
   start: Start
-  start_amp: Startamplitude
+  start_amp: 'Startamplitude (DEG)'
   visuals: Optik
   y_inverse: 'Y - Richtung invers'
   zoom: Zoom