diff --git a/Prima/Classes.pm b/Prima/Classes.pm index 858810cf..df77edbf 100644 --- a/Prima/Classes.pm +++ b/Prima/Classes.pm @@ -1254,6 +1254,8 @@ my %RNT = ( KeyUp => nt::Command, Leave => nt::Default, Menu => nt::Default, + MenuEnter => nt::Default, + MenuLeave => nt::Default, MenuSelect => nt::Default, MouseClick => nt::Command, MouseDown => nt::Command, diff --git a/Prima/Menus.pm b/Prima/Menus.pm index 472b2563..84bdbfb8 100644 --- a/Prima/Menus.pm +++ b/Prima/Menus.pm @@ -486,8 +486,8 @@ sub _export_constants { my %RNT = ( %{Prima::Widget-> notification_types()}, - Select => nt::Default, - Submenu => nt::Default, + MenuSelect => nt::Default, + Menu => nt::Default, ); sub notification_types { return \%RNT; } @@ -611,7 +611,7 @@ sub selectedItem $self->invalidate_rect( $self->get_item_rect($old) ) if $old >= 0; $self->invalidate_rect( $self->get_item_rect($i) ) if $i >= 0; if ( defined ( my $itemid = $self->{cache}->[$i]->[ITEMID] )) { - $self->root->notify(qw(Select), $itemid); + $self->root->notify(qw(MenuSelect), $itemid); } } @@ -637,7 +637,7 @@ sub enter_submenu $index = $self-> parentIndex + @{ $self->{cache} } - 1; } - $self->root->notify(qw(Submenu), $itemid); + $self->root->notify(qw(Menu), $itemid); return unless $self->alive; $self->{submenu_index} = $i; diff --git a/Prima/VB/Classes.pm b/Prima/VB/Classes.pm index dbc3f282..c8d7bfa2 100644 --- a/Prima/VB/Classes.pm +++ b/Prima/VB/Classes.pm @@ -1091,7 +1091,10 @@ sub prf_events onHint => 'my ($self, $show) = @_;', onKeyDown => 'my ($self, $code, $key, $mod, $repeat) = @_;', onKeyUp => 'my ($self, $code, $key, $mod) = @_;', - onMenu => 'my ($self, $menu, $variable) = @_;', + onMenu => 'my ($self, $menu, $item) = @_;', + onMenuEnter => 'my ($self, $menu) = @_;', + onMenuLeave => 'my ($self, $menu) = @_;', + onMenuSelect => 'my ($self, $menu, $item) = @_;', onMouseDown => 'my ($self, $btn, $mod, $x, $y) = @_;', onMouseUp => 'my ($self, $btn, $mod, $x, $y) = @_;', onMouseClick => 'my ($self, $btn, $mod, $x, $y, $dblclk) = @_;', diff --git a/class/Widget/events.c b/class/Widget/events.c index f0f80786..5a86e3ea 100644 --- a/class/Widget/events.c +++ b/class/Widget/events.c @@ -498,15 +498,20 @@ void Widget_handle_event( Handle self, PEvent event) apc_menu_get_font( event-> gen. source, &var-> popupFont); break; case cmMenu: - if ( event-> gen. H) { - if ( event-> gen.i >= 0 ) { - char buffer[16], *context; - context = ((( PAbstractMenu) event-> gen. H)-> self)-> make_id_context( event-> gen. H, event-> gen. i, buffer); - my-> notify( self, " gen. H, context); - } else - my-> notify( self, " gen. H, &PL_sv_undef); + if ( event-> gen. H ) { + char buffer[16], *context; + context = ((( PAbstractMenu) event-> gen. H)-> self)-> make_id_context( event-> gen. H, event-> gen. i, buffer); + my-> notify( self, " gen. H, context); } break; + case cmMenuEnter: + if ( event-> gen. H) + my-> notify( self, " gen. H); + break; + case cmMenuLeave: + if ( event-> gen. H) + my-> notify( self, " gen. H); + break; case cmMenuSelect: if ( event-> gen. H) { char buffer[16], *context; @@ -727,6 +732,9 @@ void Widget_on_enter( Handle self) {} void Widget_on_keydown( Handle self, int code , int key , int shiftState, int repeat ) {} void Widget_on_keyup( Handle self, int code , int key , int shiftState ) {} void Widget_on_menu( Handle self, Handle menu, char * variable) {} +void Widget_on_menuselect( Handle self, Handle menu, char * variable) {} +void Widget_on_menuenter( Handle self, Handle menu) {} +void Widget_on_menuleave( Handle self, Handle menu) {} void Widget_on_setup( Handle self) {} void Widget_on_size( Handle self, Point oldSize, Point newSize) {} void Widget_on_move( Handle self, Point oldPos, Point newPos) {} diff --git a/examples/menu.pl b/examples/menu.pl index 80fd1dca..265c4b0f 100644 --- a/examples/menu.pl +++ b/examples/menu.pl @@ -281,14 +281,17 @@ sub on_menuselect $self->Hint->text( $menu->hint($item) // '' ); } -sub on_menu +sub on_menuenter { - my ( $self, $menu, $item ) = @_; - if ( defined $item ) { - $self->Hint->{saved} //= $self->Hint->text; - } else { - $self->Hint->text( delete $self->Hint->{saved} ); - } + my ( $self ) = @_; + $self->Hint->{saved} = $self->Hint->text; +} + +sub on_menuleave +{ + my ( $self ) = @_; + warn; + $self->Hint->text( delete $self->Hint->{saved} ); } package UserInit; @@ -312,7 +315,7 @@ package UserInit; onMenuLeave => sub { $w->Hint->text( delete $w->Hint->{saved} ); }, - onSelect => sub { + onMenuSelect => sub { my ( $self, $item ) = @_; $w->Hint->text( $self->menu->hint($item) // '' ); }, diff --git a/include/apricot.h b/include/apricot.h index 3865d4fd..45fa0ec4 100644 --- a/include/apricot.h +++ b/include/apricot.h @@ -797,6 +797,10 @@ CM(MenuItemPaint) CM(Clipboard) #define cmMenuSelect 0x00000030 /* window notification to menu highlight */ CM(MenuSelect) +#define cmMenuEnter 0x00000031 /* start menu session */ +CM(MenuEnter) +#define cmMenuLeave 0x00000032 /* stop menu session */ +CM(MenuLeave) #define cmMenuCmd 0x00000050 /* interactive menu command */ CM(MenuCmd) diff --git a/pod/Prima/Widget.pod b/pod/Prima/Widget.pod index 3b51ae6a..1fd1e722 100644 --- a/pod/Prima/Widget.pod +++ b/pod/Prima/Widget.pod @@ -2874,11 +2874,11 @@ Called when the input focus is removed from the widget See also: C, C, C -=item Menu MENU VAR_NAME +=item Menu MENU, ITEM Called before the user-navigated menu ( pop-up or pull-down ) is about to show another level of submenu on the screen. MENU is a Prima::AbstractMenu -descendant, that is also a direct child to the widget. VAR_NAME is the name of +descendant, that is also a direct child to the widget. ITEM is the name of the menu item that is about to be shown. Can be used for making dynamic changes in the menu structures, f.ex. enabling @@ -2887,6 +2887,19 @@ pasted. See also: C +=item MenuEnter MENU + +Called before the user invokes a menu or a popup + +=item MenuLeave MENU + +Called after the user ends a menu or a popup session + +=item MenuSelect MENU, ITEM + +Called when the user selects (but not executes) a menu item. ITEM is the name +of the menu item that is about to be shown. + =item MouseClick BUTTON, MOD, X, Y, NTH Called when the mouse click ( a button is pressed, then released, within the diff --git a/unix/menu.c b/unix/menu.c index 25db20d8..dca97a22 100644 --- a/unix/menu.c +++ b/unix/menu.c @@ -678,7 +678,7 @@ menu_item_size( PMenuSysData XX, PMenuWindow w, int index) } static Bool -send_command( Handle self, PMenuItemReg m, int cmd) +send_command( Handle self, int cmd, PMenuItemReg m) { Event ev; Handle owner = PComponent( self)-> owner; @@ -696,8 +696,6 @@ send_command( Handle self, PMenuItemReg m, int cmd) return true; } -#define send_cmMenu(s,m) send_command(s,m,cmMenu) - static void menu_select_item( Handle self, PMenuWindow w, int index) { @@ -728,12 +726,9 @@ menu_select_item( Handle self, PMenuWindow w, int index) if (index >= 0) { PMenuItemReg m = w->m; while (index--) m = m->next; - send_command( self, m, cmMenuSelect ); - } else if (index == -100) { - MenuItemReg m; - m.id = -1; - send_cmMenu(self, &m); - } + send_command( self, cmMenuSelect, m ); + } else if (index == -100) + send_command(self, cmMenuLeave, NULL); } } @@ -766,7 +761,7 @@ menu_enter_item( PMenuSysData XX, PMenuWindow w, int index, int type) } if ( index != w-> last + 1) { - if ( !send_cmMenu( w-> self, m)) return false; + if ( !send_command( w-> self, cmMenu, m)) return false; m = m-> down; } @@ -1747,7 +1742,7 @@ handle_menu_button( XEvent *ev, XWindow win, Handle self) } XSetInputFocus( DISP, XX-> w-> w, RevertToNone, CurrentTime); guts. currentMenu = self; - if ( first && ( ev-> type == ButtonPress) && ( !send_cmMenu( self, NULL))) + if ( first && ( ev-> type == ButtonPress) && ( !send_command( self, cmMenuEnter, NULL))) return; if ( !first && ( ev-> type == ButtonPress)) return; apc_timer_stop( MENU_TIMER); @@ -2473,7 +2468,7 @@ apc_popup( Handle self, int x, int y, Rect *anchor) prima_end_menu(); if (!(m=TREE)) return false; guts. currentMenu = self; - if ( !send_cmMenu( self, NULL)) return false; + if ( !send_command( self, cmMenuEnter, NULL)) return false; if (!(w = get_window(self,m))) return false; update_menu_window(XX, w); if ( anchor-> left == 0 && anchor-> right == 0 && anchor-> top == 0 && anchor-> bottom == 0) { diff --git a/win32/global.c b/win32/global.c index 0a4bd065..ebd3dbf5 100644 --- a/win32/global.c +++ b/win32/global.c @@ -780,9 +780,13 @@ handle_widget_initmenu_events(dWM_HANDLER, UINT msg) if ( mwd && mwd-> menu && ( PAbstractMenu(mwd-> menu)->stage <= csNormal)) { m = ( PMenuItemReg) AbstractMenu_first_that( mwd-> menu, find_oid, INT2PTR(void*,mwd->id), true); hiStage = true; - ev->cmd = cmMenu; ev->gen. H = mwd-> menu; - ev->gen. i = m ? m-> id : 0; + if ( m ) { + ev->cmd = cmMenuEnter; + } else { + ev->cmd = cmMenu; + ev->gen. i = m-> id; + } } if (( msg == WM_INITMENUPOPUP) && ( m == NULL)) ev->cmd = 0; @@ -1029,9 +1033,8 @@ handle_widget_wm_menuselect( dWM_HANDLER ) return; if ( HIWORD(mp1) == 0xffff && mp2 == 0 ) { - ev-> cmd = cmMenu; + ev-> cmd = cmMenuLeave; ev-> gen.H = sys last_menu; - ev-> gen.i = -1; return; }