Commits

Herbert Breunung committed 36adcac

adding sp1 branch

  • Participants
  • Parent commits f7e5fec
  • Branches sp1

Comments (0)

Files changed (55)

lib/Kephra/API.pm

 use strict;
 use warnings;
-#use Carp;
+
 use Kephra::API::Command;
 use Kephra::API::Docs;
 use Kephra::API::Event;
 use Kephra::API::KeyMap;
-#use Kephra::API::Macro;
 #use Kephra::API::Plugin;
 #use Kephra::API::Sandrum;
 use Kephra::App::Focus;
-use Kephra::App::Window;
-use Kephra::File;
-use Kephra::Config;
-use Kephra::Help;
+#use Kephra::App::Window;
+#use Kephra::Config;
 use Kephra::Log;
 #use Kephra::Worker;
 
-
 package Kephra::API;
-my $VERSION = 0.5;
+my $VERSION = 0.1;
 
 Kephra::API::Command::switch_variables({
  '$app'    => { switch => 'app',         class => 'Kephra::App' },
  '$ed'     => { switch => 'editor',      class => 'Kephra::App::Editor' },
 });
 Kephra::API::Command::init();
-Kephra::Config::init();
-
 
 sub app             { $Kephra::App::_ref }
-sub main_window     { $Kephra::App::Window::_ref }
+sub main_window     { $Kephra::App::Frame::_ref }
 sub editor          { Kephra::API::Docs::active_editor() }
-sub docbar          { Kephra::App::Part::Editor::active_docbar() }
+sub docbar          { $Kephra::App::Bar::Document::_ref }
 sub document        { Kephra::API::Docs::active_doc() }
-sub all_documents   { Kephra::API::Docs::all_doc() }
+sub all_documents   { Kephra::API::Docs::all() }
 sub do_with_all_documents { }
 
 sub focus           { Kephra::App::Focus::set(@_) }
 sub focus_back      { Kephra::App::Focus::set_back(@_) }
 
 # IO-unit
-sub input  {main_window()->{'part'}{'iounit'}->get_line() if ref main_window() and exists main_window()->{'part'}{'iounit'} }
-sub output {main_window()->{'part'}{'iounit'}->output(@_) if ref main_window() and exists main_window()->{'part'}{'iounit'} }
-sub log    {main_window()->{'part'}{'iounit'}->output('log', @_) if ref main_window() and exists main_window()->{'part'}{'iounit'} }
+#sub input  { main_window()->{'part'}{'iounit'}->get_line() if ref main_window() and exists main_window()->{'part'}{'iounit'} }
+#sub output { main_window()->{'part'}{'iounit'}->output(@_) if ref main_window() and exists main_window()->{'part'}{'iounit'} }
+#sub log    { main_window()->{'part'}{'iounit'}->output('log', @_) if ref main_window() and exists main_window()->{'part'}{'iounit'} }
+
+sub note {}
+sub warn {}
+sub error {}
+
 
 sub configs  { }
 
 sub available_plugins {}
 sub unregister_plugin {}
 
+# if you want to know more, read Kephra::Internals.pod
 
-1; # if you want to know more, please read Kephra::Internals.pod
 
+1;

lib/Kephra/API/Docs.pm

+use v5.10;
 use strict;
 use warnings;
-
-use Kephra::API;
+use Wx;
+use Kephra::App::Editor;
+use Kephra::App::Panel;
 use Kephra::Document;
 
 package Kephra::API::Docs;
+my %document;                           # keys of subhashes: ID editor panel file
+my $active;
+my $lowest_free_ID = 1;
+use constant DOC_CLASS => 'Kephra::Document';
+use Scalar::Util qw(looks_like_number);
 
-my %document;
-my $active;
-my $previous;
 
-sub previous_doc  { $previous }
-sub active_doc    { $active }
+sub active_doc    { $active || '' }
 sub active_editor { $active->editor }
 sub set_active_doc{
-	my $any = shift;
-	Kephra::Log::warning('need a parameter!') unless $any;
-	my $new_doc = doc_by_anything( $any ) ;
-	return unless defined $new_doc;
-	_activate($new_doc);
-	return 1;
+	my $doc = find( shift );
+	$active = $doc if $doc;
 }
-sub _activate {
-	$previous = $active;
-	$active = shift;
-}
-sub add_and_activate {
+sub previous_doc  { App::Kephra::Focus::last( DOC_CLASS ) }
+sub all           { values %{$document{'ID'}} }
+
+
+
+sub add {
 	my $doc = shift;
-	add($doc);
-	_activate($doc);
-}
-sub add {            # silently
-	my $doc = shift;
-	Kephra::Log::warning("add to me only docs, not $doc!") unless $doc->isa('Kephra::Document');
-	$document{$doc->editor} = $doc;
-}
-sub del {
-	my $doc = shift;
-	Kephra::Log::warning("add to me only docs, not $doc!") unless $doc->isa('Kephra::Document');
-	Kephra::Log::warning("$doc was not in the stash!") unless $document{$doc->editor};
-	delete $document{$doc->editor};
+	Kephra::Log::warning('need a ' . DOC_CLASS . " thats in stash, not $doc!", 1)
+		unless ref $doc and $doc->isa( DOC_CLASS );
+	$document{'ID'}  {$lowest_free_ID} = $doc;
+	$document{'panel'}{$doc->panel}    = $doc if $doc->panel;
+	$document{'editor'}{$doc->editor}  = $doc if $doc->editor;
+	$document{'file'}{$doc->file_path} = $doc if $doc->file_path;
+	$lowest_free_ID++;
 }
 
+sub rename_file {
+	my $doc = find( shift );
+	Kephra::Log::warning('need a ' . DOC_CLASS . " thats in stash, not $doc!", 1)
+		unless ref $doc and $doc->isa( DOC_CLASS );
+	for (keys %{$document{'file'}} ){
+		delete $document{'file'}{$_} if $document{'file'}{$_} eq $doc;
+	}
+	$document{'file'}{$doc->file_path} = $doc if $doc->file_path;
+}
 
-sub doc_by_anything {
+sub remove {
+	my $doc = shift;
+say "remove $doc ", scalar keys %{$document{'ID'}}, ' ',scalar keys %{$document{'file'}}; 
+	Kephra::Log::warning('need a ' . DOC_CLASS . ' thats in stash, not $doc!', 1)
+		unless ref $doc and $doc->isa( DOC_CLASS );
+	delete $document{'ID'}{$doc->ID};
+	delete $document{'panel'}{$doc->panel}    if $doc->panel;
+	delete $document{'editor'}{$doc->editor}  if $doc->editor;
+	delete $document{'file'}{$doc->file_path} if $doc->file_path;
+say "removed $doc ", scalar keys %{$document{'ID'}}, ' ',scalar keys %{$document{'file'}}; 
+
+}
+
+
+sub find {
 	my $any = shift;
-	Kephra::Log::warning("need a parameter!") unless $any;
-	return     ref($any) eq ''                  ? doc_by_path ($any)
-			 : $any->isa('Wx::Panel')           ? doc_by_panel($any)
-			 : $any->isa('Kephra::App::Editor') ? doc_by_ed   ($any)
-			 : $any->isa('Kephra::Document')    ? $document{$any->editor} 
-			 :                                    undef;
+	Kephra::Log::warning("need a parameter!", 1) unless defined $any and $any;
+	return     looks_like_number($any)                                     ? $document{'ID'}    {$any}
+	         : ref($any) eq ''                                             ? $document{'file'}  {$any}
+	         : $any->isa('Kephra::App::Panel')                             ? $document{'panel'} {$any}
+	         : $any->isa('Kephra::App::Editor')                            ? $document{'editor'}{$any}
+	         :($any->isa(DOC_CLASS) and $document{'ID'}{$any->ID} eq $any) ? $any
+	         :                                                               undef;
 }
-sub doc_by_ed {
-	my $ed = shift;
-	Kephra::Log::warning("needs a Kephra::App::Editor, not $ed!")
-		unless $ed->isa('Kephra::App::Editor');
-	return $document{$ed};
-}
-sub doc_by_panel {
-	my $panel = shift;
-	Kephra::Log::warning("needs a Wx::Panel, not $panel!") unless $panel->isa('Wx::Panel');
-	for my $ed (keys %document) {
-		return $document{$ed} if $document{$ed}->panel and $document{$ed}->panel eq $panel;
-	}
-}
-sub doc_by_path {
-	my $file_path = shift;
-	Kephra::Log::warning("needs a file path as input!") unless $file_path and -e $file_path;
-	for my $ed (keys %document) {
-		return $document{$ed} if $document{$ed}->file_path eq $file_path;
-	}
-}
-sub all_doc { values %document }
-
-sub dump_all_ed { print "$_ + \n" for keys %document }
 
 sub file_loaded {
 	my $file_path = shift;
-	Kephra::Log::warning("needs a file path as input!") unless $file_path and -e $file_path;
-	for my $ed (keys %document) {
-		return 1 if $document{$ed}->file_path and $document{$ed}->file_path eq $file_path;
+	#Kephra::Log::warning("needs a file path as input!") unless $file_path and -e $file_path;
+	for my $doc ( all() ) {
+		return 1 if $doc->file_path and $doc->file_path eq $file_path;
 	}
 }
+
+sub dump_all_ed { say $_ for keys %{$document{'editor'}} }
+
+
 1;
+

lib/Kephra/API/GCL.pm

-use strict;
-use warnings;
-
-# GUI Composition Language
-package Kephra::API::GCL;
-
-
-1;
-
-__END__
-
-will be split one day as a seperate project

lib/Kephra/API/Macro.pm

-use strict;
-use warnings;
-
-package Kephra::API::Macro;
-
-
-1;

lib/Kephra/API/Plugin.pm

-use strict;
-use warnings;
-
-package Kephra::API::Plugin;
-
-# init the registered plugins
-sub start {}
-
-# register a plugin
-sub register {}
-sub unregister {}
-
-# load and unload a specific plugin
-sub load {}
-sub unload {}
-
-1;

lib/Kephra/API/Sandrum.pm

-use strict;
-use warnings;
-
-package Kephra::API::Sandrum;
-
-
-1;

lib/Kephra/App.pm

-use strict;
-use warnings;
-
-use Wx;
-use Kephra::API;
-
-package Kephra::App;
-our @ISA = 'Wx::App';
-our $_ref;
-
-Kephra::API::Command::register({
- 'app-close-save'=> {sub => '$app->close_save', label=> 'Exit', keys=> 'alt+q'},
-});
-
-sub OnInit {
-	$_ref = shift;
-
-	my $win = Kephra::App::Window->new(__PACKAGE__);
-
-	Kephra::File::new();
-
-	$win->Center();
-	$win->Refresh();   # remove visual clutter on start
-	$win->Show();
-
-	1;
-}
-
-sub close_save {
-	Kephra::File::close_all();
-	close_raw();
-}
-
-sub close_raw  {
-	my $win = Kephra::API::main_window();
-	$win->destroy();
-}
-
-sub OnExit {
-	my $app = shift;
-	Wx::wxTheClipboard->Flush;
-	1;
-}
-
-# $app->ExitMainLoop(1);
-1;

lib/Kephra/App/Bar/Document.pm

 use warnings;
 use Wx;
 use Wx::AUI;
-use Kephra::API;
-use Kephra::App::Panel;
-use Kephra::App::Util;
 
 package Kephra::App::Bar::Document;
 our @ISA = 'Wx::AuiNotebook';
+our $_ref;
+my $lowest_free_untitled_ID = 1;
+
 
 Kephra::API::Command::register({
  'docbar-select-left'     =>{sub=>'$docbar->select_page_left',     label=>'Previous Tab',  keys=>'ctrl+pageup'},
  'docbar-select-right'    =>{sub=>'$docbar->select_page_right',    label=>'Next Tab',      keys=>'ctrl+pagedown'},
- 'docbar-select-leftmost' =>{sub=>'$docbar->select_page_leftmost', label=>'First Tab',     keys=>'ctrl+shift+pageup'},
- 'docbar-select-rightmost'=>{sub=>'$docbar->select_page_rightmost',label=>'Last Tab',      keys=>'ctrl+shift+pagedown'},
+ #'docbar-select-leftmost'=>{sub=>'$docbar->select_page_leftmost', label=>'First Tab',     keys=>'ctrl+shift+pageup'},
+ #'docbar-select-rightmost'=>{sub=>'$docbar->select_page_rightmost',label=>'Last Tab',      keys=>'ctrl+shift+pagedown'},
  'docbar-move-left'       =>{sub=>'$docbar->move_page_left',       label=>'Move Left',     keys=>'alt+pageup'},
  'docbar-move-right'      =>{sub=>'$docbar->move_page_right',      label=>'Move Right',    keys=>'alt+pagedown'},
- 'docbar-move-leftmost'   =>{sub=>'$docbar->move_page_leftmost',   label=>'Move Leftmost', keys=>'alt+shift+pageup'},
- 'docbar-move-rightmost'  =>{sub=>'$docbar->move_page_rightmost',  label=>'Move Rightmost',keys=>'alt+shift+pagedown'},
+ #'docbar-move-leftmost'   =>{sub=>'$docbar->move_page_leftmost',   label=>'Move Leftmost', keys=>'alt+shift+pageup'},
+ #'docbar-move-rightmost'  =>{sub=>'$docbar->move_page_rightmost',  label=>'Move Rightmost',keys=>'alt+shift+pagedown'},
 });
 
 
-my ($is_panel, $is_widget) = Kephra::App::Util::get(qw/is_panel is_widget/);
-
 sub new {
 	my( $class, $parent) = @_;
-	my $self = $class->SUPER::new( $parent, -1, [-1,-1], [-1,-1],
+	my $self = $_ref = $class->SUPER::new( $parent, -1, [-1,-1], [-1,-1],
 		&Wx::wxAUI_NB_TOP | &Wx::wxAUI_NB_TAB_MOVE | &Wx::wxAUI_NB_WINDOWLIST_BUTTON |
 		&Wx::wxAUI_NB_SCROLL_BUTTONS | &Wx::wxAUI_NB_CLOSE_ON_ACTIVE_TAB
 	);
 
-	$self->{'visual_page_order'} = [];   # visual order of internal indexes : vis -> int
-	$self->{'internal_page_order'} = []; # internal order of visual indexes : int -> vis
-	$self->activate_events();
+	$self->{'visual_page_order'} = [];   # visual order of internal pos : vis -> int
+	$self->{'internal_page_order'} = []; # internal order of visual pos : int -> vis
+	$self->mount_events();
 
 	return $self;
 }
 
-sub activate_events {
+sub mount_events {
 	my ($self) = @_;
+	#Wx::Event::EVT_SET_FOCUS ($self,  sub { print "focus--\n";$_[1]->Skip });
 	Wx::Event::EVT_AUINOTEBOOK_BEGIN_DRAG( $self, -1, sub {
-		my ($nb, $event ) = @_;
-		$self->{'DND_page_nr'} = $event->GetSelection;
+		my ($bar, $event ) = @_;
+		$bar->{'DND_page_nr'} = $event->GetSelection;
 	});
 	Wx::Event::EVT_AUINOTEBOOK_END_DRAG($self, -1, sub {
-		my ($nb, $event ) = @_;
-		return unless defined $self->{'DND_page_nr'};
-		$nb->move_page_index_visually($self->{'DND_page_nr'}, $event->GetSelection);
-		$self->{'DND_page_nr'} = undef;
+		my ($bar, $event ) = @_;
+		return unless defined $bar->{'DND_page_nr'};
+		$bar->move_page_position_visually($bar->{'DND_page_nr'}, $event->GetSelection);
+		$bar->{'DND_page_nr'} = undef;
+		Kephra::App::Focus::stay();
 	});
 	Wx::Event::EVT_AUINOTEBOOK_PAGE_CHANGED( $self, -1, sub {
-		my ($nb, $event ) = @_;
-		my $new_page = $nb->GetPage( $event->GetSelection );
+		my ($bar, $event ) = @_;
+		my $new_page = $bar->GetPage( $event->GetSelection );
 		Kephra::API::Docs::set_active_doc( $new_page );
 		Kephra::API::main_window()->refresh_title();
-		Wx::Window::SetFocus( $new_page );
+		Kephra::API::focus( $new_page );
 		$event->Skip;
 	});
 	Wx::Event::EVT_AUINOTEBOOK_PAGE_CLOSE( $self, -1, sub {
-		my ($nb, $event ) = @_; 
+		my ($bar, $event ) = @_; 
 		$event->Veto;
 		Kephra::File::close_active();
 	});
-	#Wx::Event::EVT_AUINOTEBOOK_PAGE_CHANGED(
-	#);
 	# keep focus on editor even when klicking on tab bar
-	#Wx::Event::EVT_LEFT_DOWN($self, sub { Kephra::API::active_editor()->focus; print "--"; });
+	#Wx::Event::EVT_LEFT_UP($self, sub { Kephra::API::active_editor()->focus; print "--"; });
 	#$self->Connect( -1, -1, &Wx::wxEVT_SET_FOCUS, sub {  print "--"; } )
 }
-sub silence_events {
+
+sub unmount_events {
 	my ($self) = @_;
 	Wx::Event::EVT_AUINOTEBOOK_BEGIN_DRAG( $self, -1, sub {});
 	Wx::Event::EVT_AUINOTEBOOK_END_DRAG  ( $self, -1, sub {});
 	Wx::Event::EVT_AUINOTEBOOK_PAGE_CLOSE  ( $self, -1, sub {});
 }
 
+
 sub add_page {
-	my ($self, $new_page, $label, $position) = @_;
-	return unless $new_page and ($is_panel->($new_page) or $is_widget->($new_page));
+	my ($self, $new_page, $position, $title, $set_active) = @_;
+	return Kephra::Log::warning( "got no panel", 1 ) until Kephra::App::Util::is_panel($new_page);
 	my $active_pos = $self->GetSelection;
 
-	$label    = ''                           unless defined $label;
-	$position = 'right'                      if $position eq 'default' or $position == -1;
+	$title    = ''                           unless defined $title;
+	$position = 'right'                      if $position eq 'default' or $position eq -1;
 	$position = $self->rightmost_page_pos+1  if $position eq 'rightmost';
 	$position = $active_pos + 1              if $position eq 'right';
 	$position = $active_pos                  if $position eq 'left';
 	$position = $self->leftmost_page_pos     if $position eq 'leftmost';
-	#$set_active = 1                          unless defined $set_active;
+	$set_active = 0                          unless defined $set_active;
 
-	# put panel under a none-panel
-	unless ($new_page->isa('Kephra::App::Panel')) {
-		my $widget = $new_page;
-		$new_page = Kephra::App::Panel->new( $self, \$widget);# if ($position == 0 or $label);
-		# document property: panel the editor sits on has to be set before EVT_AUINOTEBOOK_PAGE_CHANGED
-		Kephra::DocumentStash::doc_by_ed( $widget )->panel( $new_page ) if $widget->isa('Kephra::Editor'); # and ($position == 0 or $label);
-	}
-	else { $new_page->Reparent( $self ) }
-
-	$self->InsertPage( $position, $new_page, '');# if $position == 0 or $label; # last parameter sets new pace as active
-	$self->set_page_title( $label, $new_page );
+	$new_page->Reparent($self);
+	$self->InsertPage( $position, $new_page, $title, $set_active);
+	$self->set_page_title( $title, $new_page );
+	Kephra::API::focus($new_page) if $set_active;
+	Kephra::API::main_window()->refresh_title() if $set_active;
 
 	# inserting new index to position translators
 	for   (@{$self->{'visual_page_order'}}){ $_++ if $_ >= $position }
 	splice @{$self->{'visual_page_order'}},  $position, 0, $position;
 	$self->refresh_internal_page_order();
 
-	return $new_page;
+	$self;
 }
 
 sub remove_page {
-	my ($self, $internal_position) = @_;
+	my ($self, $page) = @_;
+	my $internal_position = $self->GetPageIndex( $page );
 
-	$self->DeletePage( $internal_position );
+	$self->RemovePage( $internal_position );
 	my $visual_position = $self->{'internal_page_order'}[$internal_position];
 	my $visual = $self->{'visual_page_order'};
 	splice @$visual, $visual_position, 1;
 	$self->refresh_internal_page_order;
 }
 
-sub refresh_internal_page_order {
+
+sub refresh_internal_page_order {       # sync visual_page_order index with internal_page_order after each change
 	my ($self) = @_;
 	my $visual = $self->{'visual_page_order'};
 	return unless ref $visual eq ref [];
 	$self->{'internal_page_order'} = $internal;
 }
 
-sub move_page_index_visually { # for dnd only
+sub move_page_position_visually {          # for dnd only
 	my ($self, $from, $to ) = @_;
 	return unless $from >= 0 and $from < $self->GetPageCount;
 	return unless $to >= 0 and $to < $self->GetPageCount;
-	my $index = splice @{$self->{'visual_page_order'}}, $from, 1;
-	splice @{$self->{'visual_page_order'}}, $to, 0, $index;
+	my $position = splice @{$self->{'visual_page_order'}}, $from, 1;
+	splice @{$self->{'visual_page_order'}}, $to, 0, $position;
 	$self->refresh_internal_page_order();
 }
 
-sub move_page_visually { # for movements by keyboard
+sub move_page_visually  {               # for movements by keyboard
 	my ($self, $from, $to ) = @_;
 	my $max = $self->GetPageCount - 1;
 	return if $from < 0 or $from > $max;
 	my $label = $self->GetPageText( $pos );
 	my $visual = $self->{'visual_page_order'};
 
-	$self->silence_events();
+	$self->unmount_events();
 	$self->RemovePage( $pos );
 	$self->InsertPage( $to, $page, $label);
 	my $removed = splice @$visual, $from, 1;
 	$self->{'visual_page_order'} = $visual;
 	$self->refresh_internal_page_order();
 	$self->SetSelection( $self->{'visual_page_order'}[$to] );
-	$self->activate_events();
+	$self->mount_events();
 }
 
-sub move_page_left  { 
+sub move_page_left      {
 	my ($self) = @_;
 	$self->move_page_visually ( 
 		$self->active_visual_pos, $self->next_page_pos_rot_left( $self->GetSelection )
 	);
 }
-sub move_page_right { 
+sub move_page_right     {
 	my ($self) = @_;
 	$self->move_page_visually( 
 		$self->active_visual_pos, $self->next_page_pos_rot_right( $self->GetSelection )
 	$self->move_page_visually( $self->active_visual_pos, $self->rightmost_page_pos );
 }
 
-sub select_page_left  { 
+sub select_page_left    { 
 	my ($self) = @_;
 	$self->raise_page( $self->next_page_pos_rot_left( $self->GetSelection ) );
 }
-sub select_page_right { 
+sub select_page_right   { 
 	my ($self) = @_;
 	$self->raise_page( $self->next_page_pos_rot_right( $self->GetSelection ) );
 }
 sub select_page_leftmost  { $_[0]->raise_page( $_[0]->leftmost_page_pos ) }
 sub select_page_rightmost { $_[0]->raise_page( $_[0]->rightmost_page_pos ) }
 
-sub leftmost_page_pos { 0 }
-sub rightmost_page_pos { $_[0]->GetPageCount-1 }
-sub active_visual_pos { $_[0]->{'internal_page_order'}[ $_[0]->GetSelection ] }
-sub next_page_pos_rot_left {
+sub active_visual_pos     { $_[0]->{'internal_page_order'}[ $_[0]->GetSelection ] }
+sub leftmost_page_pos     { 0 }
+sub rightmost_page_pos    { $_[0]->GetPageCount-1 }
+sub valid_page_pos        { 
+	1 if $_[1] >= $_[0]->leftmost_page_pos and $_[1]<= $_[0]->rightmost_page_pos
+}
+sub next_page_pos_rot_left{
 	my ($self) = @_; # take in position of internal order
 	my $pos = $self->{'internal_page_order'}[ $_[1] ];
 	$self->{'visual_page_order'}[$pos == 0 ? $self->rightmost_page_pos : $pos-1]
 }
-sub next_page_pos_rot_right {
+sub next_page_pos_rot_right{
 	my ($self) = @_; # take in position of internal order
 	my $pos = $self->{'internal_page_order'}[ $_[1] ];
 	$self->{'visual_page_order'}[$pos == $self->rightmost_page_pos ? 0 : $pos+1]
 }
 
-sub raise_page {
-	my ($self, $iop) = @_; # can be Index Or Page (panel reference)
-	my $index = int $iop eq $iop ? $iop : $self->GetPageIndex($iop);
-	return if $index < 0 or $index > $self->rightmost_page_pos;
-	$self->SetSelection( $index );
-	my $page = $self->GetPage($index);
-	#print $page->GetChildren,"||\n";
-	Kephra::App::Focus::set($page);
+
+sub raise_page    {
+	my ($self, $pop) = @_; # can be Position Or Page (panel reference)
+	my $position = int $pop eq $pop ? $pop : $self->GetPageIndex($pop);
+	return unless $self->valid_page_pos( $position );
+	# if just selecting the currrent, only tab drives focus nuts
+	$position == $self->GetSelection
+		? Kephra::API::focus( $self->GetPage($position) )
+		: $self->SetSelection( $position );
 }
 
+
+sub active_title { $_[0]->GetPageText( $_[0]->GetSelection ) }
+
 sub set_page_title {
 	my ($self, $label, $page) = @_;
 	return if ref $page and $page ne ref $page and $page->isa(' Wx::Window');
 	my $position = $page ? $self->GetPageIndex($page) : $self->GetSelection;
-	return unless $position >= 0;
-	$label = '<untitled>' unless $label;
+	return unless $self->valid_page_pos($position);
+	$label = '<untitled '.($lowest_free_untitled_ID++).'>' unless $label;
 	my $max_width = 15;
 	if ( length($label) > $max_width and $max_width > 7 ) {
 		$label = substr( $label, 0, $max_width - 2 ) . '..';
 	}
 	$self->SetPageText( $position, $label );
 }
-
 sub refresh_page_title {
 	my $self = shift;
 	my $doc = shift // Kephra::API::document();
 	$self->SetPageText($position, $label);
 }
 
-1;
 
+
+1;

lib/Kephra/App/Bar/Menu.pm

-use strict;
-use warnings;
-
-use Kephra::App::Menu;
-use Kephra::Config::Default;
-use Kephra::Log;
-
-package Kephra::App::Bar::Menu;
-
-sub get {
-	my $menu_def = Kephra::Config::Default::mainmenu();
-	return Kephra::Log::error("got no array ref as menu definition")
-		unless ref $menu_def eq 'ARRAY';
-
-	my $bar = Wx::MenuBar->new();
-	for my $menu_data (@{ Kephra::App::Menu::assemble($menu_def) }) {
-		next unless ref $menu_data eq ref [];
-		$bar->Append( Kephra::App::Menu::compile( $menu_data ) );
-	}
-	return $bar;
-}
-
-sub set {
-	my $which_menu = shift;
-}
-
-
-1;

lib/Kephra/App/Bar/Side.pm

 use strict;
 use warnings;
+use Wx;
+use Kephra::API;
+use Kephra::App::Splitter;
+use Kephra::App::ToolBar;
+use Kephra::App::Util;
 
 package Kephra::App::Bar::Side;
 our @ISA = 'Wx::Panel';
 
-sub new {}
+sub new {
+}
 sub add {}
 sub remove {}
 

lib/Kephra/App/Dialog/Base.pm

Empty file added.

lib/Kephra/App/Dialog/Keymap.pm

 use warnings;
 
 use Wx;
-use Kephra::API;
+use Kephra::CommandList;
 
 package Kephra::App::Dialog::Keymap;
 my $cache;
 		$dialog, -1,  &Wx::wxDefaultPosition, &Wx::wxDefaultSize, &Wx::wxLC_REPORT 
 	);
 	my $col;
-	my $data = Kephra::API::Command::_raw_list();
+	my $data = Kephra::CommandList::_raw();
 	$list->InsertColumn($col++, $_) for qw(Command Keys Help);
 	$list->SetColumnWidth(0, 200);
 	$list->SetColumnWidth(1, 140);

lib/Kephra/App/Editor.pm

+use v5.10;
 use strict;
 use warnings;
-
 use Wx;
-#use Wx::DND;
 use Wx::STC;
-#use Wx::Scintilla;
-
 use Kephra::API;
 use Kephra::App::Editor::TextDropTarget;
-use Kephra::App::Util;
-use Kephra::Edit;           # has to be first of edit modules
-use Kephra::Edit::Comment;
-use Kephra::Edit::Format;
-use Kephra::Edit::Search;
+
 
 package Kephra::App::Editor;
 our @ISA = 'Wx::StyledTextCtrl';
-#our @ISA = 'Wx::ScintillaTextCtrl';
+use Kephra::App::Util qw(create_color);
 
-my $color = Kephra::App::Util::get('create_color');
 
 sub new {
 	my( $class, $parent, $style) = @_;
 	my ($self, @which) = @_;
 	$self->DragAcceptFiles(1) if $^O eq 'MSWin32'; # enable drop files on win
 	$self->SetDropTarget( Kephra::App::Editor::TextDropTarget->new($self) );
+
 	Wx::Event::EVT_STC_CHANGE       ($self, -1, sub {
 		my ($ed, $event) = @_;
 		$ed->{'change_pos'} = $ed->GetCurrentPos;
 		$event->Skip;
 	} );
+	
 	Wx::Event::EVT_KEY_DOWN ($self, sub {
 		my ($ed, $event) = @_;
 		my $key = Kephra::API::KeyMap::keycode_from_event($event);
-		Kephra::API::log("pressed key $key inside the editor");
+		#Kephra::API::log("pressed key $key inside the editor");
+		#say $key;
 		if (Kephra::API::KeyMap::keycode_is_registered($key)){
 			my $cmd = Kephra::API::KeyMap::cmd_from_keycode($key);
-			Kephra::API::log("run command: $cmd");
+			#say $cmd;
+			#Kephra::API::log("run command: $cmd");
 			Kephra::API::Command::run( $cmd );
 		}
 		else {$event->Skip}
+
+		if    ($key ==  0)                     {  }
+		#elsif ($key ==  &Wx::WXK_PAGEUP + 2000){$output_book->AdvanceSelection(0)}
+		#elsif ($key ==  ord('Q')        + 4000){Kephra::API::app()->close_save }
+		else {$event->Skip}
 	});
 	#Wx::Event::EVT_RIGHT_DOWN
 	#Wx::Event::EVT_STC_UPDATEUI
 	#Wx::Event::EVT_STC_START_DRAG   ($ep, -1, sub {
 	#Wx::Event::EVT_STC_DRAG_OVER    ($ep, -1, sub { $droppos = $_[1]->GetPosition });
 	#Wx::Event::EVT_STC_DO_DROP   
-
+	$self;
+}
+sub unmount_events {
+	my ($self) = @_;
+	Wx::Event::EVT_STC_CHANGE($self, -1, sub { } );
+	Wx::Event::EVT_KEY_DOWN($self, sub { $_[1]->Skip });
+	#Wx::Event::EVT_RIGHT_DOWN
+	#Wx::Event::EVT_STC_UPDATEUI
+	Wx::Event::EVT_STC_SAVEPOINTREACHED($self, -1, sub { });
+	Wx::Event::EVT_STC_SAVEPOINTLEFT($self, -1, sub { });
+	#Wx::Event::EVT_DROP_FILES       ($ep, sub{});
+	#Wx::Event::EVT_STC_START_DRAG   ($ep, -1, sub {
+	#Wx::Event::EVT_STC_DRAG_OVER    ($ep, -1, sub { $droppos = $_[1]->GetPosition });
+	#Wx::Event::EVT_STC_DO_DROP   
+	$self;
 }
 
 sub set_margin {
 		$self->SetMarginSensitive( 0, 1 );
 		$self->SetMarginSensitive( 1, 1 );
 		$self->SetMarginSensitive( 2, 1 );
-		$self->StyleSetForeground(&Wx::wxSTC_STYLE_LINENUMBER, $color->(123,123,137));
-		$self->StyleSetBackground(&Wx::wxSTC_STYLE_LINENUMBER, $color->(226,226,222));
+		$self->StyleSetForeground(&Wx::wxSTC_STYLE_LINENUMBER, create_color(123,123,137));
+		$self->StyleSetBackground(&Wx::wxSTC_STYLE_LINENUMBER, create_color(226,226,222));
 		$self->SetMarginWidth(0,  0);
 		$self->SetMarginWidth(1, 31);
 		$self->SetMarginWidth(2,  0);
 
 	# extra margin left and right inside the white text area
 	$self->SetMargins(2, 2);
+	$self;
 }
 
 sub insert_text {
 
 sub set_colors {
 	my $self = shift;
-	$self->SetCaretLineBack( $color->(250,245,185) );
+	$self->SetCaretLineBack( create_color(250,245,185) );
 	#$self->SetCaretPeriod( 500 );
 	#$self->SetCaretWidth( 2 );
-	$self->SetCaretForeground( $color->(0,0,255) );
+	$self->SetCaretForeground( create_color(0,0,255) );
 	$self->SetCaretLineVisible(1);
-	$self->SetSelForeground( 1, $color->(243,243,243) );
-	$self->SetSelBackground( 1, $color->(0, 17, 119) );
-	$self->SetWhitespaceForeground( 1, $color->(204, 204, 153) );
+	$self->SetSelForeground( 1, create_color(243,243,243) );
+	$self->SetSelBackground( 1, create_color(0, 17, 119) );
+	$self->SetWhitespaceForeground( 1, create_color(204, 204, 153) );
 	$self->SetViewWhiteSpace(1);
 
-	$self->SetEdgeColour( $color->(200,200,255) );
+	$self->SetEdgeColour( create_color(200,200,255) );
 	$self->SetEdgeColumn( 80 );
 	$self->SetEdgeMode( &Wx::wxSTC_EDGE_LINE );
 }
 	 $self->StyleSetSpec(30,"fore:#f36600,back:#fff8f8");                       # qw = Array
 }
 
-1;
-
-__END__
-
-$self->SetIndicatorCurrent( $c);
-$self->IndicatorFillRange( $start, $len );
-$self->IndicatorClearRange( 0, $len )
-	#Wx::Event::EVT_STC_STYLENEEDED($self, sub{}) 
-	#Wx::Event::EVT_STC_CHARADDED($self, sub {});
-	#Wx::Event::EVT_STC_ROMODIFYATTEMPT($self, sub{}) 
-	#Wx::Event::EVT_STC_KEY($self, sub{}) 
-	#Wx::Event::EVT_STC_DOUBLECLICK($self, sub{}) 
-	Wx::Event::EVT_STC_UPDATEUI($self, -1, sub { 
-		#my ($ed, $event) = @_; $event->Skip; print "change \n"; 
-	});
-	#Wx::Event::EVT_STC_MODIFIED($self, sub {});
-	#Wx::Event::EVT_STC_MACRORECORD($self, sub{}) 
-	#Wx::Event::EVT_STC_MARGINCLICK($self, sub{}) 
-	#Wx::Event::EVT_STC_NEEDSHOWN($self, sub {});
-	#Wx::Event::EVT_STC_PAINTED($self, sub{}) 
-	#Wx::Event::EVT_STC_USERLISTSELECTION($self, sub{}) 
-	#Wx::Event::EVT_STC_UR$selfROPPED($self, sub {});
-	#Wx::Event::EVT_STC_DWELLSTART($self, sub{}) 
-	#Wx::Event::EVT_STC_DWELLEND($self, sub{}) 
-	#Wx::Event::EVT_STC_START_DRAG($self, sub{}) 
-	#Wx::Event::EVT_STC_DRAG_OVER($self, sub{}) 
-	#Wx::Event::EVT_STC_DO_DROP($self, sub {});
-	#Wx::Event::EVT_STC_ZOOM($self, sub{}) 
-	#Wx::Event::EVT_STC_HOTSPOT_CLICK($self, sub{}) 
-	#Wx::Event::EVT_STC_HOTSPOT_DCLICK($self, sub{}) 
-	#Wx::Event::EVT_STC_CALLTIP_CLICK($self, sub{}) 
-	#Wx::Event::EVT_STC_AUTOCOMP_SELECTION($self, sub{})
-	#$self->SetAcceleratorTable( Wx::AcceleratorTable->new() );
-	#Wx::Event::EVT_MENU( $self, 1000, sub { $_[1]->Skip; } );
-	#Wx::Event::EVT_STC_SAVEPOINTREACHED($self, -1, \&Kephra::File::savepoint_reached);
-	#Wx::Event::EVT_STC_SAVEPOINTLEFT($self, -1, \&Kephra::File::savepoint_left);
-	$self->SetAcceleratorTable(
-		Wx::AcceleratorTable->new(
-			[&Wx::wxACCEL_CTRL, ord 'n', 1000],
-	));
+1;

lib/Kephra/App/Editor/TextDropTarget.pm

 package Kephra::App::Editor::TextDropTarget;
 use base 'Wx::TextDropTarget';
 use Kephra::App::Editor;
-use Kephra::File;
+#use Kephra::File;
 
 sub new {
 	my ($class, $ed) = @_;
 sub OnDropText {
 	my( $self, $x, $y, $text ) = @_;
 	$text =~ m|^(file:)?(.*)|s;
-	if ($1)  { Kephra::File::open($2) }
+	if ($1)  { #Kephra::File::open($2)
+	}
 	else     {
 		my $pos = $self->{'ed'}->PositionFromPoint( [$x, $y] );
 		$self->{'ed'}->insert_text($2, $pos);

lib/Kephra/App/Frame.pm

+use strict;
+use warnings;
+use Wx;
+use Kephra::API;
+
+
+package Kephra::App::Frame;
+our @ISA = 'Wx::Frame';
+our $_ref;
+my $title_end = "$Kephra::NAME $Kephra::VERSION";
+
+#Kephra::CommandList::register_cmd({
+ #'window-fullscreen-toggle'=>{sub => '$win->toggle_fullscreen', label=>'Fullscreen', keys=>'F11'},
+ #'iounit-focus'            =>{sub =>'$win->{"part"}{"iounit"}->focus_on_input', label => ' ', keys => 'esc'},
+#});
+
+
+sub new {
+	my( $class, $title ) = @_;
+	my( $self ) = $_ref = $class->SUPER::new ( undef, -1, $title, [-1,-1],[1000, 800] );
+	$self->SetIcon( Wx::GetWxPerlIcon() );
+	Kephra::App::Focus::set($self);
+
+	#Wx::Event::EVT_CLOSE( $self, sub{ Kephra::App::close_save() });
+
+	return $self;
+}
+
+sub close   { $_ref->Close() }
+sub destroy { $_ref->Destroy() }
+
+sub get_title { $_ref->GetTitle( )       }
+sub set_title { $_ref->SetTitle( $_[1] ) }
+sub refresh_title {
+	my $self = shift;
+	my $doc = Kephra::API::document();
+
+#print "refresh ",$doc->file_name;
+
+	my $title = (ref $doc and $doc->file_name)
+		? $doc->file_name.' ('.$doc->file_path.')'
+		: Kephra::API::docbar()->active_title();
+	$self->set_title( $title . " - $title_end" );
+}
+
+sub toggle_fullscreen {
+	my ($self) = @_;
+	$self->{fullscreen} ^= 1;
+	$self->ShowFullScreen ( 
+		$self->{fullscreen}, 
+		&Wx::wxFULLSCREEN_NOCAPTION | &Wx::wxFULLSCREEN_NOBORDER
+	);
+}
+
+1;

lib/Kephra/App/Menu.pm

 use Wx;
 
 use Kephra::API;
+use Kephra::CommandList;
+use Kephra::Log;
 
 
 package Kephra::App::Menu;
 			if    ($first_chr eq '+') {$item_def = join('-', @$parents, $menu_name).substr($item_def, 1)}
 			elsif ($first_chr eq '-') {$item_def = join('-', @$parents)          .substr($item_def, 1)}
 
-			my $cmd_data = Kephra::API::Command::all_properties( $item_def );
+			my $cmd_data = Kephra::CommandList::cmd_all_properties( $item_def );
 			next unless ref $cmd_data;
 			push @menu_data, {
 				'type' => 'item',

lib/Kephra/App/Panel.pm

 sub hide {}
 sub all_widgets {  }
 sub widget_by_nr { }
-sub get_position { $_[0]->sizer->get_position($_[1]) }
+sub get_position {
+	my ($self) = shift; 
+	my ($child) = shift;
+	$self->sizer->get_position($child);
+}
 
 1;

lib/Kephra/App/Part/Editor.pm

 use strict;
 use warnings;
+use Cwd;
+use File::Find;
+use File::Spec;
+use Kephra::API;
 
 package Kephra::App::Part::Editor;
+our @ISA = 'Kephra::App::Panel';
 
-use Kephra::API;
-use Kephra::App::Bar::Document;
+my @docbar;
+my $docbar;
 
-#my $_ref; # whole panel widget, parent of all this
-my %doc_bar;
-#my $active;
-
-sub active_docbar{ $doc_bar{'leftup'} }
 
 sub new {
-	my( $class, $parent) = @_;
-	$doc_bar{'leftup'} = Kephra::App::Bar::Document->new( $parent );
-	# Wx::SplitterWindow->new( $splitter{'left'}, -1 );
-	return $doc_bar{'leftup'};
+	#my( $class, $parent) = @_;
+	#my $self = $panel = $class->SUPER::new(
+		#$parent, -1, [-1,-1], [-1,-1], 
+		#&Wx::wxTR_SINGLE | &Wx::wxTR_HIDE_ROOT,
+	#);
+#
+	#my @lib = @{ get_modules_and_paths('lib') };
+	#my $root_ID = $self->AddRoot( 'Root', -1, -1, Wx::TreeItemData->new( ));
+	#for (0 .. $#lib){
+		#my $data = Wx::TreeItemData->new; 
+		#$data->SetData( $lib[$_][1] );
+		#my $ItemID = $self->AppendItem( $root_ID, $lib[$_][0] );
+		#$self->SetItemData( $ItemID, $data );
+	#}
+#
+	#Wx::Event::EVT_TREE_ITEM_ACTIVATED( $self, -1, sub {
+		#my ($fb, $event) = @_;
+		#Kephra::File::open( $fb->GetItemData( $event->GetItem )->GetData );
+		#Wx::Window::SetFocus( $fb );
+	#} );
+	#Wx::Event::EVT_KEY_DOWN ($self, sub {
+		#my ($fb, $event) = @_;
+		#my $key = Kephra::KeyMap::code_from_event($event);
+		#Kephra::API::log("pressed key $key inside the filebrowser");
+		#if    ($key ==  &Wx::WXK_ESCAPE) {Kephra::API::focus_back() }
+		#elsif ($key ==  &Wx::WXK_F2)     {Kephra::API::focus_back() }
+		#elsif ($key ==  &Wx::WXK_F11)    {Kephra::API::main_window()->toggle_fullscreen() } 
+		#else { $event->Skip }
+	#});
+#
+	# selection only visible when browser has focus
+	#Wx::Event::EVT_SET_FOCUS($self, sub { $_[0]->SelectItem( $_[0]->GetSelection, 1) });
+	#Wx::Event::EVT_KILL_FOCUS($self, sub { $_[0]->SelectItem( $_[0]->GetSelection, 0) });
+#
+	#my ($fi_ID, $cookie) = $self->GetFirstChild($root_ID);
+	#$self->SelectItem( $fi_ID, 1 ); # hack tor eall start when focus at number 1 not 0
+	#$self->SelectItem( $fi_ID, 0 );
+	#return $self;
 }
 
-sub create_document {
-	my $file = shift;
-	my $doc = Kephra::API::document();
-	my $win = Kephra::API::main_window();
-	my $main_doc_bar = active_docbar();
-
-	if ($doc and $doc->editor->is_empty and $file) { # overwrite empty doc
-		$doc->assign_file_path($file);
-		$main_doc_bar->set_page_title( $doc->file_name );
-	} else {                                         # make new editor
-		$doc = Kephra::Document->new();
-		$doc->assign_file_path( $file );
-		$doc->panel( Kephra::App::Panel->new( $main_doc_bar ) );
-		$doc->editor( Kephra::App::Editor->new( $doc->panel ) );
-		$doc->panel->append( \$doc->editor );
-		Kephra::API::Docs::add_and_activate( $doc );
-		$main_doc_bar->add_page($doc->panel, $doc->file_name, -1, 1);
-		Kephra::API::focus( $doc->editor );
-	}
-	$win->refresh_title();
-
-	return $doc;
-}
-
-sub remove_document {
-	my $doc = shift;
-	return unless ref $doc and $doc->isa('Kephra::Document');
-	my $main_doc_bar = active_docbar();
-	if ($main_doc_bar->GetPageCount > 1) {
-		$main_doc_bar->remove_page( $main_doc_bar->GetPageIndex( $doc->panel ) );
-		Kephra::API::Docs::del($doc);
-	} else {
-		$doc->editor->ClearAll;
-		$doc->assign_file_path('');
-		$main_doc_bar->set_page_title('');
-	}
-	Kephra::API::main_window()->refresh_title();
-}
-
-sub raise_document {
-	my $doc = Kephra::API::Docs::doc_by_anything(shift);
-	active_docbar()->raise_page( $doc->{panel} ) if $doc;
-}
-
-sub active_title {
-	my $nb = active_docbar();
-	$nb->GetPageText( $nb->GetSelection );
-}
-
-1;
+1;

lib/Kephra/App/Part/FileBrowser.pm

 use Kephra::API;
 use Kephra::File;
 
-Kephra::API::Command::register({
- 'filebrowser-focus' =>{ sub=>'focus', label => ' ', keys => 'F2' },
+Kephra::CommandList::register_cmd_namespace('filebrowser');
+Kephra::CommandList::register_cmd({
+ '+-focus' =>{ sub=>'focus', label => ' ', keys => 'F2' },
 });
 
 
 	} );
 	Wx::Event::EVT_KEY_DOWN ($self, sub {
 		my ($fb, $event) = @_;
-		my $key = Kephra::API::KeyMap::keycode_from_event($event);
+		my $key = Kephra::KeyMap::code_from_event($event);
 		Kephra::API::log("pressed key $key inside the filebrowser");
 		if    ($key ==  &Wx::WXK_ESCAPE) {Kephra::API::focus_back() }
 		elsif ($key ==  &Wx::WXK_F2)     {Kephra::API::focus_back() }

lib/Kephra/App/Part/IOUnit.pm

-use strict;
-use warnings;
-use Wx::AUI;
-use Wx::Perl::ProcessStream;
-use Kephra::API;
-
-package Kephra::App::Part::IOUnit;
-
-our @ISA = 'Wx::Panel';
-
-Kephra::API::KeyMap::register_map({ 'iounit' => {
-	'esc' => 1,
-	'window-fullscreen-toggle' => '' 
-} });
-
-
-sub new {
-	my( $class, $parent) = @_;
-	my $self = $class->SUPER::new($parent, -1);
-	$self->{'input'} = my $input = Wx::TextCtrl->new
-		($self, -1, '', [-1,-1], [-1, -1], &Wx::wxTE_PROCESS_ENTER );
-	$self->{'output_book'} = my $output_book = Wx::Notebook->new (
-		$self, -1, [-1,-1], [-1, -1], &Wx::wxNB_TOP
-	);
-	$self->{'output_slots'} = {};
-	$self->{'master_slot_name'} = 'all';
-	$self->{'active_slot_name'} = 'drum';
-	$self->{'process'} = '';
-
-	$self->create_slot($_) for ($self->{'master_slot_name'}, qw/drum perl shell output log warn/);
-	$self->raise_slot( $self->{'active_slot_name'} );
-
-	Wx::Event::EVT_SET_FOCUS($output_book, sub {$self->focus_on_input} );
-	Wx::Event::EVT_NOTEBOOK_PAGE_CHANGED( $output_book, -1, sub {
-		my ($nb, $event ) = @_;
-		$self->{'active_slot_name'} = $nb->GetPageText( $event->GetSelection );
-	});
-	Wx::Event::EVT_TEXT_ENTER($input, -1, sub {
-		my ($input, $event ) = @_;
-		my $cmd = $input->GetValue;
-		$input->Clear;
-		my $active_name = $self->{'active_slot_name'};
-		return unless $active_name eq 'drum'
-				   or $active_name eq 'perl'
-				   or $active_name eq 'shell'
-				   or $active_name eq 'output';
-		$self->output_line('log',"$active_name command $cmd");
-		my $outxt = $self->{'output_slots'}{ $active_name };
-		if    ($active_name eq 'drum')  { 
-		}
-		elsif ($active_name eq 'perl')  { 
-			$self->output_line ('perl',  $cmd . ' => "' . eval($cmd) . '"' );
-		}
-		elsif ($active_name eq 'shell') {
-			
-			$self->{'process'} = Wx::Perl::ProcessStream->OpenProcess
-				(qq~"$ENV{SHELL}" "$cmd"~ , __PACKAGE__, $self->{'output_slots'}{'shell'});
-		}
-	});
-	Wx::Perl::ProcessStream::EVT_WXP_PROCESS_STREAM_STDOUT(
-		$self->{'output_slots'}{'shell'}, sub {
-			my ($txt, $event) = @_;
-			$event->Skip(1);
-			$self->output_line('shell', $event->GetLine );
-	} );
-
-	Wx::Event::EVT_KEY_DOWN ($input, sub {
-		my ($input, $event) = @_;
-		my $key = Kephra::API::KeyMap::keycode_from_event($event);
-		Kephra::API::log("pressed key $key inside the IOUnit");
-
-		my $slot = $self->{'output_slots'}{ $self->{'active_slot_name'} };
-
-		if    ($key ==  0)                     {  }
-		elsif ($key ==  &Wx::WXK_UP     + 2000){
-		#$txt->MoveUp(1,0);
-		#print $txt->HitTest([12,5]),"\n";
-		#$txt->SetCaretPosition(  ); 
-		#$txt->ScrollIntoView( $txt->HitTest([12,5])-1, &Wx::WXK_UP);
-			$slot->PageUp( 1, &Wx::WXK_UP);
-			$slot->ShowPosition( $slot->GetCaretPosition )
-		}
-		elsif ($key ==  &Wx::WXK_UP     + 3000){$slot->ShowPosition(0)}
-		elsif ($key ==  &Wx::WXK_DOWN   + 2000){$slot->PageDown(1,0) }
-		elsif ($key ==  &Wx::WXK_DOWN   + 3000){$slot->ShowPosition($slot->GetLastPosition-1) }
-		elsif ($key ==  &Wx::WXK_PAGEUP + 2000){$output_book->AdvanceSelection(0)}
-		#elsif ($key ==  &Wx::WXK_PAGEUP + 3000){Kephra::App::Part::Editor::select_tab_leftmost()  }
-		#elsif ($key ==  &Wx::WXK_PAGEUP + 4000){Kephra::App::Part::Editor::move_tab_left()  }
-		#elsif ($key ==  &Wx::WXK_PAGEUP + 5000){Kephra::App::Part::Editor::move_tab_leftmost()  }
-		elsif ($key ==  &Wx::WXK_PAGEDOWN+2000){$output_book->AdvanceSelection(1)}
-		#elsif ($key ==  &Wx::WXK_PAGEDOWN+3000){Kephra::App::Part::Editor::select_tab_rightmost()}
-		#elsif ($key ==  &Wx::WXK_PAGEDOWN+4000){Kephra::App::Part::Editor::move_tab_right()}
-		#elsif ($key ==  &Wx::WXK_PAGEDOWN+5000){Kephra::App::Part::Editor::move_tab_rightmost()}
-		elsif ($key ==  &Wx::WXK_F2)           {Kephra::App::Part::FileBrowser::focus() } 
-		elsif ($key ==  &Wx::WXK_F11)          {Kephra::API::main_window()->toggle_fullscreen() } 
-		elsif ($key ==  &Wx::WXK_ESCAPE)       {Kephra::API::editor()->focus() } 
-		elsif ($key ==  &Wx::WXK_TAB    + 2000){Kephra::API::editor()->focus() } # SHIFT LOCK
-		elsif ($key ==  ord('Q')        + 2000){Kephra::File::close_active() }
-		elsif ($key ==  ord('Q')        + 4000){Kephra::API::app()->close_save }
-		else {$event->Skip}
-	});
-
-	my $sizer = Wx::BoxSizer->new( &Wx::wxVERTICAL );
-	$sizer->Add( $output_book, 1, &Wx::wxGROW);
-	$sizer->Add( $input,  0, &Wx::wxGROW);
-	$self->SetSizer( $sizer );
-
-	return $self;
-}
-
-sub create_slot {
-	my ($self, $slot_name) = @_;
-	die __PACKAGE__ . "::create_slot: wanted to creat already existing output slot"
-		if exists $self->{'output_slots'}{ $slot_name };
-	my $slot = $self->{'output_slots'}{ $slot_name } = Wx::RichTextCtrl->new(
-		$self->{'output_book'}, -1, '', [-1,-1], [-1,-1],
-		&Wx::wxTE_MULTILINE | &Wx::wxTE_READONLY
-	);
-	# put new pages on second last pos, because all is on last
-	my $pos = $self->{'output_book'}->GetPageCount;
-	$pos-- if $pos;
-	$self->{'output_book'}->InsertPage ( $pos, $slot, $slot_name, 0 );
-	Wx::Event::EVT_SET_FOCUS($slot, sub { $self->focus_on_input });
-}
-
-sub output {
-	my ($self, $slot_name, $msg, $raise) = @_;
-	return unless defined $self->{'output_slots'}{ $slot_name };
-	my $slot = $self->{'output_slots'}{ $slot_name };
-	my $stamped_msg = Kephra::Log::timestamp() . ' ' . $msg;
-	if ($slot_name eq 'log') {
-		$slot->AppendText("\n") if $slot->GetValue;
-		$slot->AppendText($stamped_msg);
-	}
-	else                     { $slot->AppendText($msg) }
-	$slot->ShowPosition( $slot->GetCaretPosition );
-	unless ($slot_name eq $self->{'master_slot_name'}) {
-		my $masterslot =  $self->{'output_slots'}{ $self->{'master_slot_name'} };
-		$masterslot->AppendText("\n") if $masterslot->GetValue;
-		$masterslot->AppendText("<$slot_name> $stamped_msg");
-		$masterslot->ShowPosition( $masterslot->GetCaretPosition);
-	}
-	$self->raise_slot($slot_name) if $raise;
-}
-sub output_string { $_[0]->output(@_) }
-sub output_line {
-	my $self = shift;
-	my ($slot_name, $msg) = @_;
-	return unless defined $self->{'output_slots'}{ $slot_name };
-	my $slot = $self->{'output_slots'}{ $slot_name };
-	my ($x, $y) = $slot->GetLastPosition;
-	$slot->AppendText("\n")
-		if ($slot_name ne 'log' and $slot_name ne $self->{'master_slot_name'})
-		and $slot->GetValue     and $x > 0;
-	$self->output(@_);
-}
-sub output_on_clear_and_raised {
-	my ($self, $slot_name, $msg) = @_;
-	return unless defined $self->{'output_slots'}{ $slot_name };
-	$self->raise_slot($slot_name);
-	$self->{'output_slots'}{ $slot_name }->Clear;
-	$self->output(@_);
-}
-
-sub raise_slot {
-	my ($self, $slot_name) = @_;
-	return unless defined $self->{'output_slots'}{ $slot_name };
-	my $nb = $self->{'output_book'};
-	my $page = $self->{'output_slots'}{ $slot_name };
-	for (0 .. $nb->GetPageCount-1) {
-		$nb->ChangeSelection( $_ ),last if $nb->GetPage($_) eq $page;
-	}
-	Kephra::API::focus_back();
-}
-
-sub focus_on_input { Kephra::API::focus( shift->{'input'} ) }
-
-sub get_line  {}
-sub get_click {}
-
-1;

lib/Kephra/App/Part/OrgPad.pm

-use strict;
-use warnings;
-
-use Kephra::App::Editor;
-
-package Kephra::App::Part::OrgPad;
-our @ISA = 'Kephra::App::Editor';
-
-
-sub new {
-    my( $class, $parent, $style) = @_;
-    my $ed = $class->SUPER::new($parent, -1);
-    $ed->set_margin('no');
-
-    return $ed;
-}
-
-
-1;

lib/Kephra/App/Part/Outline.pm

-use strict;
-use warnings;
-
-use Kephra::App::Editor;
-
-package Kephra::App::Part::Outline;
-our @ISA = 'Kephra::App::Panel';
-
-
-sub new {
-    my( $class, $parent, $style) = @_;
-    my $self = $class->SUPER::new($parent, -1);
-    #$ed->set_margin('no');
-
-    return $self;
-}
-
-
-1;

lib/Kephra/App/Part/TextLab.pm

-use strict;
-use warnings;
-
-package Kephra::App::Part::TextLab;
-
-
-1;

lib/Kephra/App/Sizer.pm

 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;
-	my ($mark_child) = shift;
-	my $pos = $self->get_position($mark_child);
-	return Kephra::Log::error("bookmark child $mark_child not found", 1) unless $pos > -1;
-	$self->insert($pos, 0, @_);
-}
-sub insert_after   {
-	my ($self) = shift;
-	my ($mark_child) = shift;
-	my $pos = $self->get_position($mark_child);
-	return Kephra::Log::error("bookmark child $mark_child not found", 1) unless $pos > -1;
-	$self->insert($pos+1, 0, @_);
-}
+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_before   {
+	#my ($self) = shift;
+	#my ($mark_child) = shift;
+	#my $pos = $self->get_position($mark_child);
+	#return Kephra::Log::error("bookmark child $mark_child not found", 1) unless $pos > -1;
+	#$self->insert($pos, 0, @_);
+#}
+#sub insert_after   {
+	#my ($self) = shift;
+	#my ($mark_child) = shift;
+	#my $pos = $self->get_position($mark_child);
+	#return Kephra::Log::error("bookmark child $mark_child not found", 1) unless $pos > -1;
+	#$self->insert($pos+1, 0, @_);
+#}
 sub insert          {
 	my ($self) = shift;
 	my ($position) = shift;
 	Kephra::Log::error("$child is no child of $self", 1);
 	return -1;
 }
-sub is_child     { $_[0]->child_item( $_[1] ) ne '' ? 1 : 0 }
+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;

lib/Kephra/App/ToolBar.pm

 use Wx;
 
 use Kephra::API;
+use Kephra::CommandList;
+use Kephra::Log;
 
 
 package Kephra::App::ToolBar;

lib/Kephra/App/Window.pm

-use strict;
-use warnings;
-use Wx;
-use Kephra::API;
-use Kephra::App::Bar::Menu;
-use Kephra::App::Bar::MainTool;
-use Kephra::App::Bar::Search;
-use Kephra::App::Bar::Status;
-use Kephra::App::Dialog;
-use Kephra::App::Part::Editor;
-use Kephra::App::Part::TextLab;
-use Kephra::App::Part::IOUnit;
-use Kephra::App::Part::FileBrowser;
-use Kephra::App::Part::ProjectManager;
-use Kephra::App::Part::TreeLib;
-use Kephra::App::Part::OrgPad;
-use Kephra::App::Part::ScratchSheet;
-
-
-package Kephra::App::Window;
-our @ISA = 'Wx::Frame';
-our $_ref;
-my $title_end = "$Kephra::NAME $Kephra::VERSION";
-
-Kephra::API::Command::register({
- 'window-fullscreen-toggle'=>{sub =>'$win->toggle_fullscreen', label=>'Fullscreen', keys=>'F11'},
- 'iounit-focus'            =>{sub =>'$win->{"part"}{"iounit"}->focus_on_input', label => ' ', keys => 'esc'},
-});
-
-
-sub new {
-	my( $class, $title ) = @_;
-	my( $self ) = $_ref = $class->SUPER::new ( undef, -1, $title, [-1,-1],[1000, 800] );
-	$self->SetIcon( Wx::GetWxPerlIcon() );
-	Kephra::App::Focus::set($self);
-
-	# container var for all panel, sizer and splitter
-	my (%panel, %sizer, %splitter, %gui_part);
-	$splitter{'left'}  = Wx::SplitterWindow->new( $self,             -1 );
-	$splitter{'right'} = Wx::SplitterWindow->new( $splitter{'left'}, -1 );
-	$splitter{'below'} = Wx::SplitterWindow->new( $splitter{'right'},-1 );
-	$panel   {'above'} = Wx::Panel         ->new( $splitter{'below'});
-	$splitter{'edit'}  = Wx::SplitterWindow->new( $panel   {'above'},-1 );
-
-	for my $name (qw /left right above below edit/) {
-		$panel{ $name } = Wx::Panel->new( $splitter{ $name } ) unless $name eq 'above';
-		$sizer{ $name } = Wx::BoxSizer->new( &Wx::wxHORIZONTAL );
-		$sizer{ $name } = Wx::BoxSizer->new( &Wx::wxVERTICAL ) if $name eq 'above'
-															   or $name eq 'below';
-		$panel{ $name }->SetSizer( $sizer{ $name } );
-	}
-	$self->{'part'} = \%gui_part;
-	$gui_part{'editor'}      = Kephra::App::Part::Editor   ->new( $panel{'edit'} );
-	$gui_part{'searchbar'}   = Kephra::App::Bar::Search    ->new( $panel{'above'} );
-	$gui_part{'iounit'}      = Kephra::App::Part::IOUnit   ->new( $panel{'below'} );
-	$gui_part{'filebrowser'} = Kephra::App::Part::FileBrowser->new($panel{'left'} );
-	#my $projectman      = Kephra::App::Part::ProjectManarger->new( $panel{'left'} );
-	$gui_part{'treelib'}     = Kephra::App::Part::TreeLib  ->new( $panel{'right'} );
-	#my $orgpad          = Kephra::App::Part::OrgPad     ->new( $panel{'right'} );
-	#my $scratchsheet    = Kephra::App::Part::ScratchSheet->new( $panel{'right'} );
-	$gui_part{'statusbar'}   = Kephra::App::Bar::Status    ->new( $self );
-
-	$splitter{'left'}->SplitVertically( $panel{'left'}, $splitter{'right'}, 200);
-	$splitter{'left'}->SetSashGravity(0);
-	$splitter{'left'}->SetSashPosition(200);
-	$splitter{'left'}->SetMinimumPaneSize(140);
-	$splitter{'right'}->SplitVertically( $splitter{'below'}, $panel{'right'}, -200);
-	$splitter{'right'}->SetSashGravity(1);
-	$splitter{'right'}->SetSashPosition(-200);
-	$splitter{'right'}->SetMinimumPaneSize(140);
-	$splitter{'below'}->SplitHorizontally( $panel{'above'}, $panel{'below'}, -200);
-	$splitter{'below'}->SetSashGravity(1);
-	$splitter{'below'}->SetSashPosition(-200);
-	$splitter{'below'}->SetMinimumPaneSize(100);
-	$splitter{'edit'}->Initialize( $panel{'edit'} );
-
-	$sizer{'edit'} ->Add( $gui_part{'editor'},     1, &Wx::wxGROW );
-	$sizer{'above'}->Add( $splitter{'edit'},       1, &Wx::wxGROW );
-	$sizer{'above'}->Add( $gui_part{'searchbar'},  0, &Wx::wxGROW );
-	$sizer{'below'}->Add( $gui_part{'iounit'},     1, &Wx::wxGROW );
-	$sizer{'right'}->Add( $gui_part{'treelib'},    1, &Wx::wxGROW );
-	$sizer{'left'} ->Add( $gui_part{'filebrowser'},1, &Wx::wxGROW );
-
-	$sizer{'main'} = Wx::BoxSizer->new( &Wx::wxVERTICAL );
-	$sizer{'main'}->Add( $splitter{'left'},       1, &Wx::wxGROW);
-	$sizer{'main'}->Add( $gui_part{'statusbar'},  0, &Wx::wxGROW);
-	$self->SetSizer( $sizer{'main'} );
-
-	$self->SetMenuBar( Kephra::App::Bar::Menu::get() );
-	$self->GetMenuBar->SetAcceleratorTable( Wx::AcceleratorTable->new() );
-
-	#Wx::Event::EVT_SPLITTER_DCLICK( ,sub {});  #&Wx::wxSP_NOBORDER  );
-	Wx::Event::EVT_CLOSE( $self, sub{ Kephra::App::close_save() });
-
-	return $self;
-}
-
-sub close   { $_ref->Close() }
-sub destroy { $_ref->Destroy() }
-
-sub get_title { $_ref->GetTitle( )       }
-sub set_title { $_ref->SetTitle( $_[1] ) }
-sub refresh_title {
-	my $self = shift;
-	my $doc = Kephra::API::Docs::active_doc();
-	my $title = (ref $doc and $doc->file_name)
-		? $doc->file_name.' ('.$doc->file_path.')'
-		: Kephra::App::Part::Editor::active_title();
-	$self->set_title( $title . " - $title_end" );
-}
-
-sub toggle_fullscreen {
-	my ($self) = @_;
-	$self->{fullscreen} ^= 1;
-	$self->ShowFullScreen ( 
-		$self->{fullscreen}, 
-		&Wx::wxFULLSCREEN_NOCAPTION | &Wx::wxFULLSCREEN_NOBORDER
-	);
-}
-
-1;

lib/Kephra/Config.pm

-use strict;
-use warnings;
-use File::UserConfig;
-
-package Kephra::Config;
-
-sub init {
-}
-
-1;

lib/Kephra/Config/Default.pm

-use strict;
-use warnings;
-
-package Kephra::Config::Default;
-
-sub global {
-	require Kephra::Config::Default::Global;
-	return Kephra::Config::Default::Global::get();
-}
-
-sub localisation {
-	require Kephra::Config::Default::Localisation;
-	return Kephra::Config::Default::Localisation::english();
-}
-
-sub keymap {}
-sub iconmap {}
-
-sub mainmenu {
-	require Kephra::Config::Default::Menu;
-	return Kephra::Config::Default::Menu::main();
-}
-sub contextmenu {}
-
-sub maintoolbar {
-	require Kephra::Config::Default::ToolBar;
-	return Kephra::Config::Default::ToolBar::maintoolbar();
-}
-sub searchbar {
-	require Kephra::Config::Default::ToolBar;
-	return Kephra::Config::Default::ToolBar::searchbar();
-}
-sub statusbar {}
-
-sub syntaxmode {}
-
-
-1;

lib/Kephra/Config/Default/Global.pm

-use strict;
-use warnings;
-
-package Kephra::Config::Default::Global;
-
-sub get { {
-	about => {
-		version => 0,
-	},
-	app => {
-		window => {},
-		doc_bar => {},
-	},
-	document => {
-		
-	},
-	editor => {
-		
-	},
-	file => {
-		open => {},
-		save => {},
-		session => {},
-		project => {},
-	},
-}; }
-
-1;

lib/Kephra/Config/Default/Localisation.pm

-use strict;
-use warnings;
-
-package Kephra::Config::Default::Localisation;
-
-sub english { return {
-	command => {
-		label => {
-			file => {
-				open => 'Open',
-				close => 'Close',
-			},
-			help => {
-				about => 'About...',
-			},
-		},
-		help => {
-			
-		},
-	}
-} }
-
-1;

lib/Kephra/Config/Default/Menu.pm

-use strict;
-use warnings;
-
-package Kephra::Config::Default::Menu;
-
-sub main { [
-	[	{section_name => 'file'},
-		'+-new',
-		'+-open',
-		'+-reopen',
-		'+-save',
-		'+-save-as',
-		'+-rename',
-		'+-close',
-		'+-close-other',
-		'+-close-all',
-		'',
-		#[	{section_name => 'session'},
-		#],
-		#'',
-		'app-close-save',
-	],
-	[	{section_name => 'edit'},
-		'+-undo',
-		'+-redo',
-		'',
-		'+-cut',
-		'+-copy',
-		'+-insert',
-		'+-replace',
-		'+-delete',
-		'',
-		[	{section_name => 'line'},
-			'--copy-line',
-			'--double',
-			'--delete-line',
-			'',
-			'--move-line-up',
-			'--move-line-down',
-			'--move-page-up',
-			'--move-page-down',
-			'--move-doc-begin',
-			'--move-doc-end',
-		],
-		[	{section_name => 'selection'},
-			'--double',
-			'',
-			'--move-line-up',
-			'--move-line-down',
-			'--move-page-up',
-			'--move-page-down',
-			'--move-doc-begin',
-			'--move-doc-end',
-		],
-		[	{section_name => 'select'},
-			'+-content',
-			'+-form',
-			'+-line-start',
-			'+-line-end',
-			'+-line-up',
-			'+-line-down',
-			'+-block-up',
-			'+-block-down',
-			'+-page-up',
-			'+-page-down',
-			'+-doc-start',
-			'+-doc-end',
-			'+-doc',
-		],
-		'',
-		[	{section_name => 'format'},
-			'--indent-level',
-			'--dedent-level',
-		],
-		#[	{section_name => 'comment'},
-		#],
-		#[	{section_name => 'convert'},
-		#],
-	],
-	[	{section_name => 'search'},
-			'edit-goto-last-change',
-			'edit-find-next-comment',
-			'edit-find-prev-comment',
-	],
-	[	{section_name => 'document'},
-		[	{section_name => 'change'},
-			'docbar-select-left',
-			'docbar-select-right',
-			'docbar-select-leftmost',
-			'docbar-select-rightmost',
-			'',
-			'docbar-move-left',
-			'docbar-move-right',
-			'docbar-move-leftmost',
-			'docbar-move-rightmost',
-		],
-		#'',
-		#[	{section_name => 'encoding'},
-			#'+-utf',
-			#'+-iso-8859-15',
-			#'+-ascii',
-		#],
-		#[	{section_name => 'tabwidth'},
-		#],
-		#[	{section_name => 'lineendchars'},
-			#'+-linux',
-			#'+-mac',
-			#'+-windows',
-		#],
-		#[	{section_name => 'readonly'},
-		#],
-	],
-	#[	{section_name => 'project'},
-	#],
-	#[	{section_name => 'tools'},
-	#],
-	#[	{section_name => 'plugins'},
-	#],
-	[	{section_name => 'view'},
-		'window-fullscreen-toggle',
-	],
-	[	{section_name => 'config'},
-		'+-global-dialog',
-		'+-keymap-dialog',
-		#[	{section_name => 'file'},
-		#],
-	],
-	[	{section_name => 'help'},
-		'+-documentation',
-		'+-homepage',
-		'+-bugreport',
-		'+-forum',
-		'',
-		'+-about',
-	],
-]; }
-
-1;
-
-__END__
-
-[	{ ID => 'file'}
-	'file_new',
-	'',
-],
-
----
-- ID: file
-- file_new
-- ''

lib/Kephra/Config/Default/ToolBar.pm

-use strict;
-use warnings;
-
-package Kephra::Config::Default::ToolBar;
-
-sub maintoolbar {[
-	
-];}
-
-sub searchbar { [
-	{section_name => 'searchbar'},
-	'combobox find 200',
-	'',
-	'combobox replace 200',
-]; }
-
-1;

lib/Kephra/Config/File.pm

-use strict;
-use warnings;
-
-package Kephra::Config::File;
-
-sub load {}
-sub store {}
-
-1;
-
-__END__
-
-	YAML::DumpFile('text.yml',
-	[
-		{ ID => 'file'},
-		'file_new',
-		'file_open',
-		'file_save',
-		'file_close',
-		'',
-		'app_close_save',
-	]
-	);

lib/Kephra/Config/Localisation.pm

-use strict;
-use warnings;
-
-package Kephra::Config::Localisation;
-
-sub load {}
-sub change_to {}
-sub available {}
-
-
-1;

lib/Kephra/Config/Tree.pm

-use strict;
-use warnings;
-
-package Kephra::Config::Tree;
-
-# just merge complex structures, prefer first on conflicts
-sub merge {}
-
-# positiv if there keys in forst but not second HoH
-sub conflict {}
-
-# only leave structures at keys that also exist in second HoH
-sub trunc {}
-
-# 
-sub update_layout {}
-
-# convert HoH to flat Hash
-sub flat {}
-# convert flat hash to HoH
-sub restructure {}
-
-1;

lib/Kephra/Document.pm

-package Kephra::Document;
-use Moo;
+use v5.10;
+use File::Spec;
 use Kephra::API;
 use Kephra::File;
-use File::Spec;
-use Kephra::Log;
 
-has editor => (
-	is  => 'rw',
-	isa => sub {Kephra::Log::warning("$_[0] is no editor")
-				unless ref $_[0] eq 'Kephra::App::Editor'},
-);
-has panel => (
-	is  => 'rw',
-	isa => sub {Kephra::Log::error("$_[0] is no panel")
-				unless ref $_[0] eq 'Wx::Panel' or ref $_[0] eq 'Kephra::App::Panel'
-				},
-);
-has file_path    => ( is  => 'rw', );
-has file_dir     => ( is  => 'rw', );
-has file_name    => ( is  => 'rw', );
-#has content      => ( is  => 'rw' );
-has notes        => ( is  => 'rw', );
+package Kephra::Document;
+use Moo; 
+# export SUB_QUOTE_DEBUG=1
 
-has syntax_mode  => ( is  => 'rw', default => sub { 'perl' } );
-has readonly     => ( is  => 'rw', );
-has active_config=> ( is  => 'rw', );
-has caret_pos    => ( is  => 'rw', );
-has edit_pos     => ( is  => 'rw', );
-has coding       => ( is  => 'rw', );
-has EOL          => ( is  => 'rw', );
-has tab_size     => ( is  => 'rw', );
-has tab_use      => ( is  => 'rw', );
-has folded_lines => ( is  => 'rw', );
-has marked_lines => ( is  => 'rw', );
 
-sub assign_file_path {
-	my ($self, $file_path) = @_;
-	return unless defined $file_path and -e $file_path;
-	if ($file_path){
-		$file_path = Kephra::File::normalize_name($file_path);
-		$self->file_path($file_path);
+has ID =>     ( is  => 'rwp' );
+has editor => ( is  => 'ro' );
+has panel  => ( is  => 'ro' );
+has text   => ( is  => 'ro', );
+has notes  => ( is  => 'rw', );
+has file_path=>( 
+	is      => 'rw',
+	coerce  =>  sub { Kephra::File::normalize_path($_[0]) },
+	trigger =>  sub {
+		return if $_[0]->old_file_path and $_[0]->old_file_path eq $_[0]->file_path;
 		my @path_parts = File::Spec->splitpath( $_[0]->file_path );
-		$self->file_dir( $path_parts[1] );
-		$self->file_name( $path_parts[2] );
-	} else {
-		$self->file_path('');
-		$self->file_dir('');
-		$self->file_name('');
-	}
-	$self;
-}
-sub raise {
-	Kephra::API::docbar()->raise_page( shift->panel() );
-}
+		$_[0]->_set_file_dir( $path_parts[1] );
+		$_[0]->_set_file_name( $path_parts[2] );
+		Kephra::API::Docs::rename_file($_[0]) if $_[0]->ID;
+		$_[0]->_set_old_file_path( $_[0]->file_path );
+	});
+has file_dir     => ( is => 'rwp', );
+has file_name    => ( is => 'rwp', );
+has old_file_path=> ( is => 'rwp' );
+has content      => ( is => 'rw', reader=> sub{ $_[0] } );
+
+has syntax_mode  => ( is => 'rw', default => sub { 'perl' } );
+has readonly     => ( is => 'rw', );
+has active_config=> ( is => 'rw', );
+has caret_pos    => ( is => 'rw', );
+has edit_pos     => ( is => 'rw', );
+has encoding     => ( is => 'rw', );
+has EOL          => ( is => 'rw', );
+has tab_size     => ( is => 'rw', );
+has tab_use      => ( is => 'rw', );
+has folded_lines => ( is => 'rw', );
+has marked_lines => ( is => 'rw', );
+
+sub BUILDARGS {
+	my ( $self, @args ) = @_;
+	unshift @args, "file_path" if @args % 2 == 1;
+	my %args = @args;
+
+	$args{'panel'} = Kephra::App::Panel->new( Kephra::API::docbar() );
+	$args{'editor'} = Kephra::App::Editor->new( $args{'panel'} );
+	$args{'panel'}->append( \$args{'editor'} );