OpenCores
URL https://opencores.org/ocsvn/an-fpga-implementation-of-low-latency-noc-based-mpsoc/an-fpga-implementation-of-low-latency-noc-based-mpsoc/trunk

Subversion Repositories an-fpga-implementation-of-low-latency-noc-based-mpsoc

[/] [an-fpga-implementation-of-low-latency-noc-based-mpsoc/] [trunk/] [mpsoc/] [perl_gui/] [lib/] [perl/] [software_editor.pl] - Rev 42

Go to most recent revision | Compare with Previous | Blame | View Log

#!/usr/bin/perl
 
use strict;
use warnings;
 
use Glib qw(TRUE FALSE);
use Gtk2 '-init';
use Gtk2::SourceView2;
use Data::Dumper;
 
 
use base 'Class::Accessor::Fast';
require "widget.pl"; 
 
 
__PACKAGE__->mk_accessors(qw{
	window
	sourceview
	buffer
	filename
	search_regexp
	search_case
	search_entry
	regexp
	highlighted
});
 
my $NAME = 'Otec';
 
 
exit main() unless caller;
 
 
sub software_main {
	my ($sw,$file) = @_;
 
 
 
	my $app = __PACKAGE__->new();
	my ($table,$tview,$window)=$app->build_gui($sw);
	my $main_c=(defined $file)? "$sw/$file" : "$sw/main.c";
	$app->load_source($main_c) if (-f $main_c );
 
	#Gtk2->main();
 
	return ($app,$table,$tview,$window);
}
 
 
sub build_gui {
	my ($self,$sw) = @_;
 
	my $window = def_popwin_size (75,75,'Source Editor','percent');
	my $table= def_table(2,10,FALSE);
 
 
 
 
	my $hpaned = Gtk2::HPaned -> new;
	my $vpaned = Gtk2::VPaned -> new;
	$table->attach_defaults ($vpaned,0, 10, 0,1);
	#my $make = def_image_button('icons/run.png','Compile');
	#$table->attach ($make,9, 10, 1,2,'shrink','shrink',0,0);
	#$make -> signal_connect("clicked" => sub{
		#$self->do_save();
		#run_make_file($sw,$tview);	
 
	#});
 
	$window -> add ( $table);
 
	my($width,$hight)=max_win_size();
 
	my $scwin_dirs = Gtk2::ScrolledWindow -> new;
	$scwin_dirs -> set_policy ('automatic', 'automatic');
	$hpaned -> pack1 ($scwin_dirs, TRUE, TRUE);
	$hpaned ->set_position ($width*.15);
 
	my $scwin_text = Gtk2::ScrolledWindow -> new;
	$scwin_text -> set_policy ('automatic', 'automatic');
	$hpaned -> pack2 ($scwin_text, TRUE, TRUE);
 
 
	my ($scwin_info,$tview)= create_text();
	add_colors_to_textview($tview);
	$vpaned-> pack1 ($hpaned, TRUE, TRUE);
	$vpaned ->set_position ($hight*.5);
	$vpaned-> pack2 ($scwin_info, TRUE, TRUE);
 
 
my ($tree_view,$tree_store) =$self->build_tree_view($sw);
 
 
 
 
$scwin_dirs -> add($tree_view);
 
 
 
 
#print "$sw/\n";
 
	#my $window = Gtk2::Window->new();
	#$window->set_size_request(480, 360);
	#$window->set_title($NAME);
	$self->window($window);
 
	my $vbox = Gtk2::VBox->new(FALSE, 0);
	$scwin_text->add_with_viewport($vbox);
 
	$vbox->pack_start($self->build_menu("$sw/",$window,$tree_view,$tree_store,$scwin_dirs), FALSE, FALSE, 0);
	$vbox->pack_start($self->build_search_box, FALSE, FALSE, 0);
 
	my $scroll = Gtk2::ScrolledWindow->new();
	$scroll->set_policy('automatic', 'automatic');
	$scroll->set_shadow_type('in');
	$vbox->pack_start($scroll, TRUE, TRUE, 0);
 
	my $buffer = $self->create_buffer();
	my $sourceview = Gtk2::SourceView2::View->new_with_buffer($buffer);
	$sourceview->set_show_line_numbers(TRUE);
	$sourceview->set_tab_width(2);
	$sourceview->set_indent_on_tab(TRUE);
	$sourceview->set_highlight_current_line(TRUE);
#	$sourceview->set_draw_spaces(['tab', 'newline']);
 
	#
	# Fix Gtk2::TextView's annoying paste behaviour when pasting with the mouse
	# (middle button click). By default gtk will scroll the text view to the
	# original place where the cursor is.
	#
	$sourceview->signal_connect(button_press_event => sub {
		my ($view, $event) = @_;
 
		# We're only interested on middle mouse clicks (mouse-paste)
		return FALSE unless $event->button == 2;
 
		# Remember the position of the paste
		my (@coords) = $sourceview->window_to_buffer_coords('text', $event->x, $event->y);
		my ($iter) = $sourceview->get_iter_at_position(@coords);
		$self->{paste_mark} = $buffer->create_mark('paste', $iter, FALSE);
 
		return FALSE;
	});
 
 
	#
	# If a paste is done through the middle click then place the cursor at the end
	# of the pasted text.
	#
	$buffer->signal_connect('paste-done' => sub {
		my $mark = delete $self->{paste_mark} or return;
 
		my $iter = $buffer->get_iter_at_mark($mark);
		$buffer->place_cursor($iter);
 
		$self->sourceview->scroll_to_mark(
			$mark,
			0.0,
			FALSE,
			0.0, 0.5
		);
		$buffer->delete_mark($mark);
	});
 
 
	$scroll->add($sourceview);
	$self->sourceview($sourceview);
	$self->buffer($sourceview->get_buffer);
 
	$window->signal_connect(delete_event => sub {
		Gtk2->main_quit();
		return TRUE;
	});
 
	$window->show_all();
	return ($table,$tview,$window);
}
 
 
 
 
sub build_tree_view{
	my ($self,$sw)=@_;
 
	# Directory name, full path
my $tree_store = Gtk2::TreeStore->new('Glib::String', 'Glib::String');
my $tree_view = Gtk2::TreeView->new($tree_store);
my $column = Gtk2::TreeViewColumn->new_with_attributes('', Gtk2::CellRendererText->new(), text => "0");
$tree_view->append_column($column);
$tree_view->set_headers_visible(FALSE);
$tree_view->signal_connect (button_release_event => sub{
	my $tree_model = $tree_view->get_model();
 	my $selection = $tree_view->get_selection();
 	my $iter = $selection->get_selected();
 	if(defined $iter){
		my $path = $tree_model->get($iter, 1) ;
		$path= substr $path, 0, -1;
		$self->do_save();
		#print "open $path\n";
		 $self->load_source($path) if(-f $path);
	}
	 return;
});
 
 
$tree_view->signal_connect ('row-expanded' => sub {
	my ($tree_view, $iter, $tree_path) = @_;
 	my $tree_model = $tree_view->get_model();
	my ($dir, $path) = $tree_model->get($iter);
 
	# for each of $iter's children add any subdirectories
	my $child = $tree_model->iter_children ($iter);
	while ($child) {
  		my ($dir, $path) = $tree_model->get($child, 0, 1);
  		add_to_tree($tree_view,$tree_store, $child, $dir, $path);
  		$child = $tree_model->iter_next ($child);
 	}
	 return;
});
 
my $child = $tree_store->append(undef);
$tree_store->set($child, 0, $sw, 1, '/');
add_to_tree($tree_view,$tree_store, $child, '/', "$sw/");
return ($tree_view,$tree_store);
 
}
 
 
 
sub build_search_box {
	my $self = shift;
 
	# Elements of the search box
	my $hbox = Gtk2::HBox->new(FALSE, 0);
 
	my $search_entry = Gtk2::Entry->new();
	$search_entry->signal_connect(activate => sub {$self->do_search()});
	$search_entry->signal_connect(icon_release => sub {$self->do_search()});
	$self->search_entry($search_entry);
 
	my $search_regexp = Gtk2::CheckButton->new('RegExp');
	$search_regexp->signal_connect(toggled => sub {
		$self->search_regexp($search_regexp->get_active);
	});
 
	my $search_case = Gtk2::CheckButton->new('Case');
	$search_case->signal_connect(toggled => sub {
		$self->search_case($search_case->get_active);
	});
 
	my $search_icon = Gtk2::Button->new_from_stock('gtk-find');
	$search_entry->set_icon_from_stock(primary => 'gtk-find');
 
	$hbox->pack_start($search_entry, TRUE, TRUE , 0);
	$hbox->pack_start($search_regexp, FALSE, FALSE, 0);
	$hbox->pack_start($search_case, FALSE, FALSE, 0);
 
	return $hbox;
}
 
 
sub create_buffer {
	my $self = shift;
	my $tags = Gtk2::TextTagTable->new();
 
	add_tag($tags, search => {
			background => 'yellow',
	});
	add_tag($tags, goto_line => {
			'paragraph-background' => 'orange',
	});
 
	my $buffer = Gtk2::SourceView2::Buffer->new($tags);
	$buffer->signal_connect('notify::cursor-position' => sub {
		$self->clear_highlighted();
	});
 
	return $buffer;
}
 
 
sub add_tag {
	my ($tags, $name, $properties) = @_;
 
	my $tag = Gtk2::TextTag->new($name);
	$tag->set(%{ $properties });
	$tags->add($tag);
}
 
 
sub detect_language {
	my $self = shift;
	my ($filename) = @_;
 
	# Guess the programming language of the file
	my $manager = Gtk2::SourceView2::LanguageManager->get_default;
	my $language = $manager->guess_language($filename);
	$self->buffer->set_language($language);
}
 
 
sub load_source {
	my $self = shift;
	my ($filename) = @_;
	my $buffer = $self->buffer;
 
	# Guess the programming language of the file
	$self->detect_language($filename);
 
	# Loading a file should not be undoable.
	my $content;
	do {
		open my $handle, $filename or die "Can't read file $filename because $!";
		local $/;
		$content = <$handle>;
		close $handle;
	};
	$buffer->begin_not_undoable_action();
	$buffer->set_text($content);
	$buffer->end_not_undoable_action();
 
	$buffer->set_modified(FALSE);
	$buffer->place_cursor($buffer->get_start_iter);
 
	$self->filename($filename);
	$self->window->set_title("$filename - $NAME");
}
 
 
sub clear_highlighted {
	my $self = shift;
 
	my $highlighted = delete $self->{highlighted} or return;
 
	my $buffer = $self->buffer;
 
	my @iters;
	foreach my $mark (@{ $highlighted->{marks} }) {
		my $iter = $buffer->get_iter_at_mark($mark);
		push @iters, $iter;
		$buffer->delete_mark($mark);
	}
 
	$buffer->remove_tag_by_name($highlighted->{name}, @iters);
}
 
 
sub get_text {
	my $self = shift;
	my $buffer = $self->buffer;
	return $buffer->get_text($buffer->get_start_iter, $buffer->get_end_iter, FALSE);
}
 
 
sub do_search {
	my $self = shift;
	my $criteria = $self->search_entry->get_text;
	if ($criteria eq '') {return;}
 
	my $case = $self->search_case;
	my $buffer = $self->buffer;
 
 
	# Start the search at the last search result or from the current cursor's
	# position. As a fall back we also add the beginning of the document. Once we
	# have the start position we can erase the previous search results.
	my @start;
	if (my $highlighted = $self->highlighted) {
		# Search from the last match
		push @start, $buffer->get_iter_at_mark($highlighted->{marks}[1]);
		$self->clear_highlighted();
	}
	else {
		# Search from the cursor
		push @start, $buffer->get_iter_at_offset(
			$buffer->get_property('cursor-position')
		);
	}
	push @start, $buffer->get_start_iter;
 
	my @iters;
	if ($self->search_regexp) {
		# Gtk2::SourceView2 nor Gtk2::SourceView support regular expressions so we
		# have to do the search by hand!
 
		my $text = $self->get_text;
		my $regexp = $case ? qr/$criteria/m : qr/$criteria/im;
 
		foreach my $iter (@start) {
			# Tell Perl where to start the regexp lookup
			pos($text) = $iter->get_offset;
 
			if ($text =~ /($regexp)/g) {
				my $word = $1;
				my $pos = pos($text);
				@iters = (
					$buffer->get_iter_at_offset($pos - length($word)),
					$buffer->get_iter_at_offset($pos),
				);
				last;
			}
		}
	}
	else {
		# Use the builtin search mechanism
		my $flags = $case ? [ ] : [ 'case-insensitive' ];
		foreach my $iter (@start) {
			@iters = Gtk2::SourceView2::Iter->forward_search($iter, $criteria, $flags);
			last if @iters;
		}
	}
 
	$self->show_highlighted(search => @iters) if @iters;
}
 
 
sub show_highlighted {
	my $self = shift;
	my ($tag_name, $start, $end) = @_;
	my $buffer = $self->buffer;
 
	# Highlight the region, remember it and scroll to it
	my $match_start = $buffer->create_mark('match-start', $start, TRUE);
	my $match_end = $buffer->create_mark('match-end', $end, FALSE);
 
	$buffer->apply_tag_by_name($tag_name, $start, $end);
 
	# We have a callback that listens to when the cursor is placed and we don't
	# want it to undo our work! So let's unhighlight the previous entry.
	delete $self->{highlighted};
	$buffer->place_cursor($end);
 
	$self->sourceview->scroll_to_mark(
		$match_start,
		0.2,
		FALSE,
		0.0, 0.5
	);
 
	# Keep a reference to the markers once they have been added to the buffer.
	# Using them before can be catastrophic (segmenation fault).
	#
	$self->highlighted({
		name  => $tag_name,
		marks => [$match_start, $match_end],
	});
}
 
 
sub do_file_new {
	my ($self,$sw,$window,$tree_view,$tree_store,$scwin_dirs) = @_;
	my $buffer = $self->buffer;
 
 
	# Set no language
	$buffer->set_language(undef);
 
	# Showing a blank editor should not be undoable.
	$buffer->begin_not_undoable_action();
	$buffer->set_text('');
	$buffer->end_not_undoable_action();
 
	$buffer->set_modified(FALSE);
	$buffer->place_cursor($buffer->get_start_iter);
 
	$self->filename('');
	$self->window->set_title("Untitled - $NAME");
	$self->do_save_as($sw,$window,$tree_view,$tree_store,$scwin_dirs);
}
 
 
sub do_file_open {
	my $self = shift;
	my ($window, $action, $menu_item) = @_;
 
	my $dialog = Gtk2::FileSelection->new("Open file...");
	$dialog->signal_connect(response => sub {
		my ($dialog, $response) = @_;
 
		if ($response eq 'ok') {
			my $file = $dialog->get_filename;
			return if -d $file;
			$self->load_source($file);
		}
 
		$dialog->destroy();
	});
	$dialog->show();
}
 
 
sub do_show_about_dialog {
	my $self = shift;
 
	my $dialog = Gtk2::AboutDialog->new();
	$dialog->set_authors("Emmanuel Rodriguez");
	$dialog->set_comments("Gtk2::SourceView2 Demo");
	$dialog->signal_connect(response => sub {
		my ($dialog, $response) = @_;
		$dialog->destroy();
	});
	$dialog->show();
}
 
 
sub do_ask_goto_line {
	my $self = shift;
 
	my $dialog = Gtk2::Dialog->new_with_buttons(
		"Goto to line",
		$self->window,
		[ 'modal' ],
		'gtk-cancel' => 'cancel',
		'gtk-ok'     => 'ok',
	);
 
	my $hbox = Gtk2::HBox->new(FALSE, 0);
	$hbox->pack_start(
		Gtk2::Label->new("Line number: "),
		FALSE, FALSE, 0
	);
	my $entry = Gtk2::Entry->new();
	$hbox->pack_start($entry, TRUE, TRUE, 0);
 
	$dialog->get_content_area->add($hbox);
	$dialog->show_all();
 
 
	# Signal handlers
	$entry->signal_connect(activate => sub {
		if ($entry->get_text =~ /(\d+)/) {
			$dialog->response('ok');
		}
	});
 
	# Run the dialog
	my $response = $dialog->run();
	$dialog->destroy();
	return unless $response eq 'ok';
 
	return unless my ($line) = ($entry->get_text =~ /(\d+)/);
	my $buffer = $self->buffer;
	my $start = $buffer->get_iter_at_line($line - 1);
	my $end = $start->copy;
	$end->forward_to_line_end;
 
	$self->clear_highlighted();
	$self->show_highlighted(goto_line => $start, $end);
}
 
 
sub do_quit {
	my ($self,$window) = @_;
	$window->destroy;
}
 
 
sub do_save_as {
	my ($self,$sw,$window,$tree_view,$tree_store,$scwin_dirs) = @_;
 
	# If no file is associated with the editor then ask the user for a file where
	# to save the contents of the buffer.
	my $dialog = Gtk2::FileChooserDialog->new(
		"Save file", $self->window, 'save',
		'gtk-cancel' => 'cancel',
		'gtk-save'   => 'ok',
	);
	if(defined  $sw){
		$dialog->set_current_folder ($sw); 
		#print "open_in:$sw\n";
 
	}
 
	my $response = $dialog->run();
	if ($response eq 'ok') {
		my $file=$dialog->get_filename;
		$self->filename($file);
		$self->do_save();
		$tree_view->destroy;
		($tree_view,$tree_store) =$self->build_tree_view($sw);
		$scwin_dirs->add($tree_view);
		$scwin_dirs->show_all;
		$self->load_source($file);
 
 
	}
	$dialog->destroy();
 
 
}
 
 
sub do_save {
	my $self = shift;
 
	my $filename = $self->filename;
 
	# If there's no file then do a save as...
	if (! $filename) {
		#$self->do_save_as();
		return;
	}
 
	my $buffer = $self->buffer;
	open my $handle, '>:encoding(UTF-8)', $filename or die "Can't write to $filename: $!";
	print $handle $self->get_text;
	close $handle;
 
	if (! $buffer->get_language) {
		$self->detect_language($filename);
	}
}
 
 
 
 
 
sub build_menu {
	my ($self,$sw,$window,$tree_view,$tree_store,$scwin_dirs) = @_;
 
	my $entries = [
		# name, stock id, label
		[ "FileMenu",  undef, "_File" ],
		[ "SearchMenu",  undef, "_Search" ],
		[ "HelpMenu",  undef, "_Help" ],
 
		# name, stock id, label, accelerator, tooltip, method
		[
			"New",
			'gtk-new',
			"_New",
			"<control>N",
			"Create a new file",
			sub { $self->do_file_new($sw,$window,$tree_view,$tree_store,$scwin_dirs) }
		],
		[
			"Open",
			'gtk-open',
			"_Open",
			"<control>O",
			"Open a file",
			sub { $self->do_file_open(@_) }
		],
		[
			"Save",
			'gtk-save',
			"_Save",
			"<control>S",
			"Save current file",
			sub { $self->do_save(@_) }
		],
		[
			"SaveAs",
			'gtk-save',
			"Save _As...",
			"<control><shift>S",
			"Save to a file",
			sub { $self->do_save_as($sw,$window,$tree_view,$tree_store,$scwin_dirs) }
		],
		[
			"Quit",
			'gtk-quit',
			"_Quit",
			"<control>Q",
			"Quit",
			sub { $self->do_quit($window) }
		],
		[
			"About",
			'gtk-about',
			"_About",
			undef,
			"About",
			sub { $self->do_show_about_dialog(@_) }
		],
		[
			"GotoLine",
			undef,
			"Goto to _Line",
			"<control>L",
			"Go to line",
			sub { $self->do_ask_goto_line(@_) }
		],
	];
 
	my $actions = Gtk2::ActionGroup->new("Actions");
	$actions->add_actions($entries, undef);
 
	my $ui = Gtk2::UIManager->new();
	$ui->insert_action_group($actions, 0);
	$ui->add_ui_from_string(<<'__UI__');
<ui>
	<menubar name='MenuBar'>
		<menu action='FileMenu'>
			<menuitem action='New'/>
			<menuitem action='Open'/>
			<separator/>
			<menuitem action='Save'/>
			<menuitem action='SaveAs'/>
			<separator/>
			<menuitem action='Quit'/>
		</menu>
		<menu action='SearchMenu'>
			<menuitem action='GotoLine'/>
		</menu>
		<menu action='HelpMenu'>
			<menuitem action='About'/>
		</menu>
	</menubar>
</ui>
__UI__
 
	$self->window->add_accel_group($ui->get_accel_group);
 
	return $ui->get_widget('/MenuBar');
}
 
 
 
sub add_to_tree {
 my ($tree_view,$tree_store, $parent, $dir, $path) = @_;
my $tree_model = $tree_view->get_model();
 
# If $parent already has children, then remove them first
 my $child = $tree_model->iter_children ($parent);
 while ($child) {
  $tree_store->remove ($child);
  $child = $tree_model->iter_children ($parent);
 }
 
# Add children from directory listing
 opendir(DIRHANDLE, $path) || return ; #die "Cannot open directory:$path $!\n";
 foreach my $subdir (sort readdir(DIRHANDLE)) {
  if ($subdir ne '.' and $subdir ne '..'
                                   # and -d $path.$subdir and -r $path.$subdir
) {
   my $child = $tree_store->append($parent);
   $tree_store->set($child, 0, $subdir, 1, "$path$subdir/");
  }
 }
 closedir(DIRHANDLE);
}
 
 
# Directory expanded. Populate subdirectories in readiness.
 
sub populate_tree {
 
# $iter has been expanded
 my ($tree_view,$tree_store, $iter, $tree_path) = @_;
 my $tree_model = $tree_view->get_model();
 my ($dir, $path) = $tree_model->get($iter);
 
# for each of $iter's children add any subdirectories
 my $child = $tree_model->iter_children ($iter);
 while ($child) {
  my ($dir, $path) = $tree_model->get($child, 0, 1);
  add_to_tree($tree_view,$tree_store, $child, $dir, $path);
  $child = $tree_model->iter_next ($child);
 }
 return;
}
 
 
sub run_make_file {
	my ($dir,$outtext, $args)=@_;
	my $cmd =	(defined $args) ? "cd \"$dir/\" \n  make $args" :  "cd \"$dir/\" \n  make ";
	my $error=0;		
	add_info(\$outtext,"$cmd\n");
 
	my ($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout( $cmd);
	#($stdout,$exit,$stderr)=run_cmd_in_back_ground_get_stdout( $cmd);
 
 
	if($exit){
		if($stderr){
			$stderr=~ s/[‘,’]//g;
			add_info(\$outtext,"$stdout\n"); 
			add_colored_info(\$outtext,"$stderr\n","red"); 
		}
		add_colored_info(\$outtext,"Compilation failed.\n",'red'); 
		return 0;
 
	}else{
		add_info(\$outtext,"$stdout\n"); 
		if($stderr){ #probebly had warning
			$stderr=~ s/[‘,’]//g;
			#add_info(\$outtext,"$stdout\n"); 
			add_colored_info(\$outtext,"$stderr\n","green"); 
		}
 
		add_colored_info(\$outtext,"Compilation finished successfully.\n",'blue');  
		return 1;
	}
 
	#add_info(\$outtext,"**********Quartus compilation is done successfully in $target_dir!*************\n") if($error==0);
 
 
 
}
 
 
 
 
1;
 
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.