On 02/13/13 14:41, Johan Vromans wrote:
Dave Hayes <d...@jetcafe.org> writes:
Apparently when you call ShowModal(), new frames are disabled just
like the parent frame of the dialog.
So if I have a dialog invoked with ShowModal() and an event comes
along that wants to create a new frame, how can I enable the new frame
to receive events?
A modal dialog is intended, by design, to block all other processing.
Are you sure you want a modal dialog in the first place?
I'm pretty sure I do, since the dialog is intended to edit a set of
values and do something once all the values are changed, including
refresh the parent window with data from the new values. I don't want
multiple instances of this editor around either, so even if I don't use
modality I'd be disabling the parent window anyway.
I'm sure there's an aspect of strict "modality" I don't know, so why
wouldn't I want modality? :D
Here's a test case of what I'm doing. Maybe there's another way?
--
Dave Hayes - Consultant - Altadena CA, USA - d...@jetcafe.org
>>>> *The opinions expressed above are entirely my own* <<<<
The mastery of nature is vainly believed to be an
adequate substitute for self-mastery. --Reinhold Neibuhr
#!/usr/local/bin/perl
use strict;
use warnings;
package MyDialog;
use Wx qw(:everything);
use base qw(Wx::Dialog);
use Wx::Event qw(
EVT_CHAR
EVT_BUTTON
EVT_LISTBOX
EVT_ENTER_WINDOW
EVT_LEAVE_WINDOW
EVT_SET_FOCUS
EVT_KILL_FOCUS
);
use File::Slurp qw(read_file);
use Data::Dumper;
my @fruits = qw(
Apple Apricot Avocado Banana Breadfruit Bilberry Blackberry
Blackcurrant
Blueberry Currant Cherry Cherimoya Clementine Coconut
Date Damson Dragonfruit
Durian Eggplant Elderberry Feijoa Fig Gooseberry Grape
Grapefruit Guava Huckleberry
Honeydew Jackfruit Jettamelon Jambul Kiwi Kumquat
Legume Lemon Lime Loquat Lychee
Mandarine Mango Melon Nectarine Nut Orange Peach
Pear Persimmon Physalis Plum
Pineapple Pomegranate Pomelo Raspberry Rambutan
Redcurrant Salal Strawberry
Tangerine Tomato Ugli Watermelon
);
my $DIALOG = 'my dialog';
sub new {
my $class = shift;
my $parent = shift;
my $self = $class->SUPER::new(
$parent, -1, "Enter a fruit name. TAB to autocomplete",
wxDefaultPosition, wxDefaultSize,
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxSTAY_ON_TOP
);
my $textwin = Wx::TextCtrl->new(
$self, -1, '',
wxDefaultPosition, [ 400, 35 ],
wxTE_DONTWRAP | wxTE_PROCESS_ENTER | wxTE_PROCESS_TAB,
);
$textwin->{$DIALOG} = $self;
warn "$textwin -- dialog is ".$textwin->{$DIALOG}."\n";
$self->{'mywidget'} = $textwin; # I know it's a circular reference. This is
a test app.
EVT_CHAR($textwin, \&OnChar);
EVT_SET_FOCUS($textwin,
sub {
my ($widget, $event) = @_;
warn "Focused text widget\n";
$event->Skip(1);
});
EVT_KILL_FOCUS($textwin,
sub {
my ($widget, $event) = @_;
warn "Unfocused text widget\n";
$event->Skip(1);
});
my $dialogContainer = Wx::BoxSizer->new(wxVERTICAL);
$dialogContainer->Add($textwin, 0, wxEXPAND | wxALL, 4);
my $bottom = Wx::Button->new($self, wxID_CLOSE, "Close");
$dialogContainer->Add($bottom, 1, wxALIGN_CENTER_HORIZONTAL | wxEXPAND |
wxALL, 2);
$bottom->{'dialog'} = $self;
EVT_BUTTON($bottom, $bottom,
sub {
my ($button, $event) = @_;
$button->{'dialog'}->Close();
});
$self->SetSizer($dialogContainer);
$dialogContainer->Fit($self);
$dialogContainer->SetSizeHints($self);
$self->SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY);
return $self;
}
sub enterKeyPressed {
my ($self, $widget, $event) = @_;
warn "Value is ".$widget->GetValue()."\n";
}
sub handleTab {
my ($self, $widget, $event) = @_;
warn "TAB!\n";
$self->populateMenu($widget);
return 1;
}
sub handleKey {
my ($self, $widget, $event) = @_;
warn "KEY!\n";
return 0;
}
my $POPUP = 'popup widget because popup menus dont appear to get events';
sub populateMenu {
my ($self, $widget) = @_;
if (defined($self->{$POPUP})) {
$self->{$POPUP}->Destroy();
$self->{$POPUP} = undef;
}
my $lookupMax = 20;
my $current = $widget->GetValue();
my $r = qr/^$current/i;
my @options = grep($_ =~ /$r/, @fruits);
if ( $#options == -1) { # no values found that match
Wx::Bell;
warn "No matching value\n";
} elsif ($#options == 0) { # single value
$widget->SetValue($options[0]);
warn "One matching value\n";
} elsif ($#options > $lookupMax) { # too many values
Wx::Bell;
warn "Too many matching values\n";
} else { # enough values to menu them
my $curSize = [ $widget->GetSizeWH() ];
my $curPos = $widget->GetScreenPosition();
my $x = $curPos->x; my $y = $curPos->y;
$curPos = [ $x + 2 , $y + $curSize->[1] + 2 ];
my $newSize = [ int($curSize->[0] / 3) , ( $curSize->[1] * 3 ) + 1 ];
my $popup = $self->{$POPUP} = Wx::Frame->new(
$self, -1, '', $curPos , $newSize,
wxFRAME_FLOAT_ON_PARENT | wxFRAME_NO_TASKBAR,
);
$popup->SetExtraStyle(wxWS_EX_TRANSIENT);
my $listmenu = Wx::ListBox->new(
$popup, -1, wxDefaultPosition, $newSize,
[ @options ],
wxLB_SINGLE | wxLB_NEEDED_SB | wxWANTS_CHARS,
);
$listmenu->SetExtraStyle(wxWS_EX_TRANSIENT);
EVT_ENTER_WINDOW($listmenu,
sub { my ($list, $event) = @_;
warn "Entered list\n";
$event->Skip(1);
});
EVT_LEAVE_WINDOW($listmenu,
sub { my ($list, $event) = @_;
warn "Left the list\n";
$event->Skip(1);
});
EVT_LISTBOX($listmenu, $listmenu,
sub {
my ($listmenu, $event) = @_;
my ($selected) = ($listmenu->GetSelections());
warn "Select ($selected)\n";
$widget->SetValue($selected);
});
my $panelContainer = Wx::BoxSizer->new(wxHORIZONTAL);
$panelContainer->Add($listmenu, 1, wxEXPAND, 0);
$popup->SetSizerAndFit($panelContainer);
$popup->Layout();
$popup->Show(1);
$popup->Enable(1);
}
}
sub OnChar {
my ($widget, $event) = @_;
my $evob = $event->GetEventObject();
warn "Event object $evob\n";
my $self = $evob->{$DIALOG};
my $keycode = $event->GetKeyCode();
if ($keycode == WXK_RETURN) {
$self->enterKeyPressed($widget, $event);
$event->Skip(1);
} elsif ($keycode == WXK_TAB) {
$event->Skip(1) unless ($self->handleTab($widget, $event));
} else {
$event->Skip(1) unless ($self->handleKey($widget, $event));
}
return 1;
}
package MyApp;
use base qw(Wx::App);
use Wx qw(:everything);
use Wx::Event qw(EVT_BUTTON);
sub new {
my $self = shift;
$self = $self->SUPER::new();
return $self;
}
sub OnInit {
my( $self ) = @_;
Wx::InitAllImageHandlers();
my $topframe = $self->{'topframe'} =
Wx::Frame->new( undef, -1, "MyApp", [200, 200], [ 100, 100 ]);
my $sizer = Wx::BoxSizer->new(wxVERTICAL);
$self->SetTopWindow($topframe);
my $bottom = Wx::Button->new($topframe, -1, "Display");
EVT_BUTTON($bottom, $bottom,
sub {
my ($button, $event) = @_;
my $dialog = MyDialog->new($topframe);
$dialog->ShowModal();
});
$topframe->Show(1);
return 1;
}
package main;
my $app = MyApp->new();
$app->MainLoop();
die "Exiting main loop\n";