package Padre::Plugin::Ecliptic::QuickOutlineAccessDialog;
BEGIN {
$Padre::Plugin::Ecliptic::QuickOutlineAccessDialog::VERSION = '0.23';
}
# ABSTRACT: Quick outline autocomplete dialog
use warnings;
use strict;
# module imports
use Padre::Wx ();
# is a subclass of Wx::Dialog
use base 'Wx::Dialog';
# accessors
use Class::XSAccessor accessors => {
_plugin => '_plugin', # Plugin object
_sizer => '_sizer', # window sizer
_search_text => '_search_text', # search text control
_matches_list => '_matches_list', # matches list
_status_text => '_status_text', # status label
};
# -- constructor
sub new {
my ( $class, $plugin, %opt ) = @_;
# create object
my $self = $class->SUPER::new(
$plugin->main,
-1,
Wx::gettext('Quick Outline Access'),
Wx::wxDefaultPosition,
Wx::wxDefaultSize,
Wx::wxDEFAULT_FRAME_STYLE | Wx::wxTAB_TRAVERSAL,
);
$self->SetIcon(Wx::GetWxPerlIcon);
$self->_plugin($plugin);
# create dialog
$self->_create;
# Dialog's icon as is the same as plugin's
$self->SetIcon( $plugin->logo_icon );
return $self;
}
# -- event handler
#
# handler called when the ok button has been clicked.
#
sub _on_ok_button_clicked {
my ($self) = @_;
my $main = $self->_plugin->main;
# Open the selected outline item if the user pressed OK
my $selection = $self->_matches_list->GetSelection;
my $selected_outline_item = $self->_matches_list->GetClientData($selection);
if ($selected_outline_item) {
$main->outline->SelectItem($selected_outline_item);
}
$self->Destroy;
}
# -- private methods
#
# create the dialog itself.
#
sub _create {
my ($self) = @_;
# create sizer that will host all controls
my $sizer = Wx::BoxSizer->new(Wx::wxVERTICAL);
$self->_sizer($sizer);
# create the controls
$self->_create_controls;
$self->_create_buttons;
# wrap everything in a vbox to add some padding
$self->SetSizerAndFit($sizer);
$sizer->SetSizeHints($self);
# center the dialog
$self->Centre;
}
#
# create the buttons pane.
#
sub _create_buttons {
my ($self) = @_;
my $sizer = $self->_sizer;
my $butsizer = $self->CreateStdDialogButtonSizer( Wx::wxOK | Wx::wxCANCEL );
$sizer->Add( $butsizer, 0, Wx::wxALL | Wx::wxEXPAND | Wx::wxALIGN_CENTER, 5 );
Wx::Event::EVT_BUTTON( $self, Wx::wxID_OK, \&_on_ok_button_clicked );
}
#
# create controls in the dialog
#
sub _create_controls {
my ($self) = @_;
# search textbox
my $search_label = Wx::StaticText->new(
$self, -1,
Wx::gettext('&Type a Outline item name to access:')
);
$self->_search_text( Wx::TextCtrl->new( $self, -1, '' ) );
# matches result list
my $matches_label = Wx::StaticText->new(
$self, -1,
Wx::gettext('&Matching Outline Items:')
);
$self->_matches_list(
Wx::ListBox->new(
$self, -1, [ -1, -1 ], [ 400, 300 ], [],
Wx::wxLB_SINGLE
)
);
# Shows how many items are selected and information about what is selected
$self->_status_text( Wx::StaticText->new( $self, -1, '' ) );
$self->_sizer->AddSpacer(10);
$self->_sizer->Add( $search_label, 0, Wx::wxALL | Wx::wxEXPAND, 2 );
$self->_sizer->Add( $self->_search_text, 0, Wx::wxALL | Wx::wxEXPAND, 5 );
$self->_sizer->Add( $matches_label, 0, Wx::wxALL | Wx::wxEXPAND, 2 );
$self->_sizer->Add( $self->_matches_list, 0, Wx::wxALL | Wx::wxEXPAND, 2 );
$self->_sizer->Add( $self->_status_text, 0, Wx::wxALL | Wx::wxEXPAND, 10 );
$self->_setup_events;
return;
}
#
# Adds various events
#
sub _setup_events {
my $self = shift;
Wx::Event::EVT_CHAR(
$self->_search_text,
sub {
my $this = shift;
my $event = shift;
my $code = $event->GetKeyCode;
if ( $code == Wx::WXK_DOWN ) {
$self->_matches_list->SetFocus;
}
$event->Skip(1);
}
);
Wx::Event::EVT_TEXT(
$self,
$self->_search_text,
sub {
$self->_update_matches_list_box;
return;
}
);
Wx::Event::EVT_LISTBOX(
$self,
$self->_matches_list,
sub {
my $selection = $self->_matches_list->GetSelection;
if ( $selection != Wx::wxNOT_FOUND ) {
$self->_status_text->SetLabel( $self->_matches_list->GetString($selection) );
}
return;
}
);
Wx::Event::EVT_LISTBOX_DCLICK(
$self,
$self->_matches_list,
sub {
$self->_on_ok_button_clicked();
$self->EndModal(0);
}
);
Wx::Event::EVT_IDLE(
$self,
sub {
# update matches list
$self->_update_matches_list_box;
# focus on the search text box
$self->_search_text->SetFocus;
# unregister from idle event
Wx::Event::EVT_IDLE( $self, undef );
}
);
}
#
# Update matches list box from matched files list
#
sub _update_matches_list_box {
my $self = shift;
my $search_expr = $self->_search_text->GetValue;
#quote the search string to make it safer
$search_expr = quotemeta $search_expr;
#Populate the list box now
$self->_matches_list->Clear;
my $pos = 0;
my $main = $self->_plugin->main;
# recursively walk tree control
sub walk_tree {
my $tree = shift;
my $root = shift;
my @items = ();
if ( $root && $root->IsOk ) {
if ( $root != $tree->GetRootItem() ) {
push @items, $root;
}
if ( $tree->GetChildrenCount( $root, 0 ) ) {
my ( $child, $cookie ) = $tree->GetFirstChild($root);
while ( $child && $child->IsOk ) {
push @items, walk_tree( $tree, $child );
( $child, $cookie ) = $tree->GetNextChild( $root, $cookie );
}
}
}
return @items;
}
my $outline_tree = $main->outline;
my @items = walk_tree( $outline_tree, $outline_tree->GetRootItem() );
@items = sort { $outline_tree->GetItemText($a) cmp $outline_tree->GetItemText($b) } @items;
foreach my $item (@items) {
my $item_label = $outline_tree->GetItemText($item);
if ( $item_label =~ /$search_expr/i ) {
$self->_matches_list->Insert( $item_label, $pos, $item );
$pos++;
}
}
if ( $pos > 0 ) {
$self->_matches_list->Select(0);
$self->_status_text->SetLabel( "" . ( $pos + 1 ) . Wx::gettext(' item(s) found') );
} else {
$self->_status_text->SetLabel( Wx::gettext('No items found') );
}
return;
}
1;
__END__
=pod
=head1 NAME
Padre::Plugin::Ecliptic::QuickOutlineAccessDialog - Quick outline autocomplete dialog
=head1 VERSION
version 0.23
=head1 AUTHOR
Ahmad M. Zawawi <ahmad.zawawi@gmail.com>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2010 by Ahmad M. Zawawi.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut