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";




Reply via email to