package Padre::Wx::StatusBar; =pod =head1 NAME Padre::Wx::StatusBar - Encapsulates status bar customizations =head1 DESCRIPTION C implements Padre's statusbar. It is the bottom pane holding various, err, status information on Padre. The information shown are (in order): =over 4 =item * Filename of current document, with a leading star if file has been updated and not saved =item * (Optional) Icon showing status of background tasks =item * (Optional) Mimetype of current document =item * Type of end of lines of current document =item * Position in current document =back It inherits from C, so check wx documentation to see all the available methods that can be applied to it besides the added ones (see below). =cut use 5.008; use strict; use warnings; use Padre::Constant (); use Padre::Current (); use Padre::Util (); use Padre::Wx (); use Padre::Wx::Icon (); use Padre::Wx::Role::MainChild (); use Padre::MimeTypes (); use Class::XSAccessor accessors => { _task_sbmp => '_task_sbmp', # Static bitmap holding the task status _task_status => '_task_status', # Current task status _task_width => '_task_width', # Current width of task field }; our $VERSION = '0.50'; our @ISA = qw{ Padre::Wx::Role::MainChild Wx::StatusBar }; use constant { FILENAME => 0, TASKLOAD => 1, HIGHLIGHTER => 2, MIMETYPE => 3, NEWLINE => 4, POSTRING => 5, RDONLY => 6, }; ##################################################################### =pod =head1 METHODS =head2 new my $statusbar = Padre::Wx::StatusBar->new( $main ); Create and return a new Padre statusbar. One should pass the C<$main> Padre window as argument, to get a reference to the statusbar parent. =cut sub new { my $class = shift; my $main = shift; # Create the basic object my $self = $class->SUPER::new( $main, -1, Wx::wxST_SIZEGRIP | Wx::wxFULL_REPAINT_ON_RESIZE ); $self->{main} = $main; # create the static bitmap that will hold the task load status my $sbmp = Wx::StaticBitmap->new( $self, -1, Wx::wxNullBitmap ); $self->_task_sbmp($sbmp); $self->_task_status('foobar'); # init status to sthg defined Wx::Event::EVT_LEFT_DOWN( $sbmp, sub { require Padre::TaskManager; Padre::TaskManager::on_dump_running_tasks(@_); }, ); # Set up the fields $self->SetFieldsCount(7); #$self->SetStatusWidths( -1, 0, 100, 100, 50, 100 ); # react to resize events, to adapt size of icon field Wx::Event::EVT_SIZE( $self, \&on_resize ); return $self; } ##################################################################### =pod =head2 clear $statusbar->clear; Clear all the status bar fields, ie, they will display an empty string in all fields. =cut sub clear { my $self = shift; $self->SetStatusText( "", FILENAME ); $self->SetStatusText( "", HIGHLIGHTER ); $self->SetStatusText( "", MIMETYPE ); $self->SetStatusText( "", NEWLINE ); $self->SetStatusText( "", POSTRING ); $self->SetStatusText( "", RDONLY ); return; } =pod =head2 refresh $statusbar->refresh; Force an update of the document fields in the statusbar. =cut sub refresh { my $self = shift; my $current = $self->current; # Blank the status bar if no document is open my $editor = $current->editor or return $self->clear; # Prepare the various strings that form the status bar my $main = $self->{main}; my $notebook = $current->notebook; my $document = $current->document; my $newline = $document->get_newline_type || Padre::Constant::NEWLINE; my $pageid = $notebook->GetSelection; my $filename = $document->filename || ''; my $old = $notebook->GetPageText($pageid); my $text = $filename ? File::Basename::basename($filename) : substr( $old, 1 ); $self->{_last_editor} = $editor; $self->{_last_modified} = $editor->GetModify; my $modified = $self->{_last_modified} ? '*' : ' '; my $title = $modified . $text; my $position = $editor->GetCurrentPos; my $line = $editor->GetCurrentLine; my $start = $editor->PositionFromLine($line); my $lines = $editor->GetLineCount; my $char = $position - $start; my $width = $self->GetCharWidth; my $highlighter = Padre::MimeTypes->get_highlighter_name( $document->get_highlighter ); my $mime_type_name = Padre::MimeTypes->get_mime_type_name( $document->get_mimetype ); my $percent = int( 100 * $line / $lines ); # Set some defaults to advoid "use of uninittialized value" - messages: $mime_type_name = '???' if !defined($mime_type_name); #my $postring = Wx::gettext('L:') . ( $line + 1 ) . ' ' . Wx::gettext('Ch:') . "$char $percent%"; my $format = '%' . length( $lines + 1 ) . 's,%-3s %3s%%'; my $length = length( $lines + 1 ) + 8; my $postring = sprintf( $format, ( $line + 1 ), $char, $percent ); my $rdstatus = $self->is_read_only; # update task load status $self->update_task_status; # Write the new values into the status bar and update sizes if ( defined( $main->{infomessage} ) and ( $main->{infomessage} ne '' ) and ( $main->{infomessage_timeout} > time ) ) { $self->SetStatusText( $main->{infomessage}, FILENAME ); } else { $self->SetStatusText( "$modified $filename", FILENAME ); } $self->SetStatusText( $highlighter, HIGHLIGHTER ); $self->SetStatusText( $mime_type_name, MIMETYPE ); $self->SetStatusText( $newline, NEWLINE ); $self->SetStatusText( $postring, POSTRING ); $self->SetStatusText( $rdstatus, RDONLY ); $self->SetStatusWidths( -1, $self->_task_width, ( length($highlighter) + 2 ) * $width, ( length($mime_type_name) + 2 ) * $width, ( length($newline) + 2 ) * $width, ( $length + 2 ) * $width, length($rdstatus) * $width, ); # move the static bitmap holding the task load status $self->_move_bitmap; # Fixed ticket #190: Massive GDI object leakages # http://padre.perlide.org/ticket/190 # Please remember to call SetPageText once per the same text # This still leaks but far less slowly (just on undo) if ( $old ne $title ) { $notebook->SetPageText( $pageid, $title ); } return; } =pod =head2 update_task_status $statusbar->update_task_status; Checks whether a task status icon update is in order and if so, changes the icon to one of the other states =cut sub update_task_status { my $self = shift; my $status = $self->_get_task_status; return if $status eq $self->_task_status; # Nothing to do # Store new status $self->_task_status($status); my $sbmp = $self->_task_sbmp; # If we're idling, just hide the icon in the statusbar if ( $status eq 'idle' ) { $sbmp->Hide; $sbmp->SetBitmap(Wx::wxNullBitmap); $sbmp->SetToolTip(''); $self->_task_width(0); return; } # Not idling, show the correct icon in the statusbar $sbmp->SetBitmap( Padre::Wx::Icon::find("status/padre-tasks-$status") ); $sbmp->SetToolTip( $status eq 'running' ? Wx::gettext('Background Tasks are running') : Wx::gettext('Background Tasks are running with high load') ); $sbmp->Show; $self->_task_width(20); } =pod =head2 update_pos $statusbar->update_pos; Update the cursor position =cut sub update_pos { my $self = shift; my $current = $self->current; my $editor = $current->editor or return $self->clear; my $position = $editor->GetCurrentPos; # Skip expensive update if there is nothing to update: return if defined( $self->{Last_Pos} ) and ( $self->{Last_Pos} == $position ); # Detect modification: unless (defined( $self->{_last_editor} ) and ( $self->{_last_editor} eq $editor ) and defined( $self->{_last_modified} ) and ( $self->{_last_modified} == $editor->GetModify ) ) { # Either the tab has changed or the file has been modified: $self->refresh; } $self->{Last_Pos} = $position; my $line = $editor->GetCurrentLine; my $start = $editor->PositionFromLine($line); my $lines = $editor->GetLineCount; my $char = $position - $start; my $percent = int( 100 * $line / $lines ); my $format = '%' . length( $lines + 1 ) . 's,%-3s %3s%%'; my $postring = sprintf( $format, ( $line + 1 ), $char, $percent ); $self->SetStatusText( $postring, POSTRING ); } ##################################################################### =pod =head2 on_resize $statusbar->on_resize( $event ); Handler for the EVT_SIZE C<$event>. Used to move the task load bitmap to its position. =cut sub on_resize { my ($self) = @_; # note: parent resize method will be called automatically $self->_move_bitmap; $self->Refresh; } ##################################################################### # Private methods # # my $status = $self->_get_task_status; # # return 'idle', 'running' or 'load' depending on the number of threads # currently working. # sub _get_task_status { my $self = shift; my $manager = $self->current->ide->task_manager; # still in editor-startup phase, default to idle return 'idle' unless defined $manager; my $running = $manager->running_tasks; return 'idle' unless $running; my $max_workers = $manager->max_no_workers; my $jobs = $manager->task_queue->pending + $running; # high load is defined as the state when the number of # running and pending jobs is larger that twice the # MAXIMUM number of workers return ( $jobs > 2 * $max_workers ) ? 'load' : 'running'; } # # $statusbar->_move_bitmap; # # move the static bitmap holding the task load status to its proper location. # sub _move_bitmap { my ($self) = @_; my $sbmp = $self->_task_sbmp; my $rect = $self->GetFieldRect(TASKLOAD); my $size = $sbmp->GetSize; $sbmp->Move( $rect->GetLeft + ( $rect->GetWidth - $size->GetWidth ) / 2, $rect->GetTop + ( $rect->GetHeight - $size->GetHeight ) / 2, ); $sbmp->Refresh; } sub is_read_only { my ($self) = @_; my $file = $self->current->document->file || ''; my $is_rdonly = $file->readonly if $file; $is_rdonly ? return Wx::gettext('Read Only') : return ':)'; } 1; =pod =head1 SEE ALSO Icons for background status courtesy of Mark James, at L. =head1 COPYRIGHT & LICENSE Copyright 2008-2009 The Padre development team as listed in Padre.pm. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. The full text of the license can be found in the LICENSE file included with this module. =cut # Copyright 2008-2009 The Padre development team as listed in Padre.pm. # LICENSE # This program is free software; you can redistribute it and/or # modify it under the same terms as Perl 5 itself.