Skip to content

Commit

Permalink
first shot at menuselect actions
Browse files Browse the repository at this point in the history
  • Loading branch information
dk committed Oct 5, 2024
1 parent 73d0449 commit 1ab13be
Show file tree
Hide file tree
Showing 10 changed files with 163 additions and 27 deletions.
3 changes: 2 additions & 1 deletion Prima/Classes.pm
Original file line number Diff line number Diff line change
Expand Up @@ -1254,6 +1254,7 @@ my %RNT = (
KeyUp => nt::Command,
Leave => nt::Default,
Menu => nt::Default,
MenuSelect => nt::Default,
MouseClick => nt::Command,
MouseDown => nt::Command,
MouseUp => nt::Command,
Expand Down Expand Up @@ -2122,7 +2123,6 @@ sub effect
}
}


package Prima::Dialog;
use vars qw(@ISA);
@ISA = qw(Prima::Window);
Expand Down Expand Up @@ -2207,6 +2207,7 @@ sub key { my $self = shift;return $self-> {menu}-> key ( $self-> {id}, @_
sub submenu { my $self = shift;return $self-> {menu}-> submenu( $self-> {id}, @_);}
sub text { my $self = shift;return $self-> {menu}-> text ( $self-> {id}, @_);}
sub group { my $self = shift;return $self-> {menu}-> group ( $self-> {id}, @_);}
sub hint { my $self = shift;return $self-> {menu}-> hint ( $self-> {id}, @_);}
sub items { my $i = shift; ( @_) ? $i-> { menu}-> set_items ( $i-> { id}, @_):return $i-> {menu}-> get_items ( $i-> { id}); }
sub enable { $_[0]-> {menu}-> enabled( $_[0]-> { id}, 1) };
sub disable { $_[0]-> {menu}-> enabled( $_[0]-> { id}, 0) };
Expand Down
98 changes: 77 additions & 21 deletions class/AbstractMenu.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,11 @@ AbstractMenu_new_menu( Handle self, SV * sv, int level, void * _avt)
r-> group = pget_i(group);
pdelete(group);
}
if ( pexist( hint )) {
r-> hint = pget_sv(hint);
r-> hint = newSVsv(r->hint);
pdelete(hint);
}
}
r-> options = newSVsv( *holder);
}
Expand Down Expand Up @@ -502,6 +507,37 @@ AbstractMenu_set( Handle self, HV * profile)
if ( select) my-> set_selected( self, true);
}

static SV *
new_options( PMenuItemReg m )
{
dPROFILE;
SV * sv;
HV * profile, *dst;
if ( !m->options && m->group == 0 && m->icon == NULL_HANDLE && m->hint == NULL )
return NULL;

dst = profile = newHV();
if ( m->group > 0 ) pset_i ( group, m->group );
if ( m->icon ) pset_H ( icon, m->icon );
if ( m->hint ) pset_sv( hint, m->hint );

profile = m->options ? (HV*) SvRV(m->options) : NULL;
if ( profile && pexist( onMeasure )) {
sv = pget_sv(onMeasure);
profile = dst;
pset_sv(onMeasure, sv);
}

profile = m->options ? (HV*) SvRV(m->options) : NULL;
if ( profile && pexist( onPaint )) {
sv = pget_sv(onPaint);
profile = dst;
pset_sv(onPaint, sv);
}

return (SV*) profile;
}

static SV *
new_av( PMenuItemReg m, int level, Bool fullTree);

Expand Down Expand Up @@ -585,8 +621,11 @@ new_av_entry( PMenuItemReg m, int level, Bool fullTree)
av_push( loc, newSVpv( "", 0));
}

if ( m-> options)
av_push( loc, newSVsv(m->options));
{
SV* options = new_options(m);
if ( options )
av_push( loc, newRV_noinc(options));
}
} else {
/* divider */
if ( m-> variable) {
Expand Down Expand Up @@ -816,7 +855,7 @@ AbstractMenu_accel( Handle self, Bool set, char * varName, SV * accel)
if ( m-> id > 0) {
if ( var-> stage <= csNormal && var-> system)
apc_menu_item_set_accel( self, m);
notify( self, "<ssUS", "Change", "accel",
notify( self, "<ssUi", "Change", "accel",
m->variable ? m-> variable : varName,
m->variable ? m-> flags.utf8_variable : 0,
accel);
Expand Down Expand Up @@ -878,7 +917,7 @@ AbstractMenu_autoToggle( Handle self, Bool set, char * varName, Bool autotoggle)
if ( m-> id > 0) {
if ( var-> stage <= csNormal && var-> system)
apc_menu_item_set_autotoggle( self, m);
notify( self, "<ssUi", "Change", "autoToggle",
notify( self, "<ssUi", "Change", "autoToggle",
m->variable ? m-> variable : varName,
m->variable ? m-> flags.utf8_variable : 0,
autotoggle);
Expand Down Expand Up @@ -938,13 +977,28 @@ AbstractMenu_group( Handle self, Bool set, char * varName, int group)
if ( !set) return m-> group;
if ( m-> group == group ) return group;
m-> group = group;
notify( self, "<ssUS", "Change", "group",
notify( self, "<ssUi", "Change", "group",
m->variable ? m-> variable : varName,
m->variable ? m-> flags.utf8_variable : 0,
group);
return group;
}

SV*
AbstractMenu_hint( Handle self, Bool set, char * varName, SV* hint)
{
PMenuItemReg m;
if ( var-> stage > csFrozen) return 0;
m = find_menuitem( self, varName, true);
if ( m == NULL) return 0;
if ( !set) return m-> hint ? newSVsv(m->hint) : &PL_sv_undef;
m-> hint = (hint && SvOK(hint)) ? newSVsv(hint) : NULL;
notify( self, "<ssUS", "Change", "hint",
m->variable ? m-> variable : varName,
m->variable ? m-> flags.utf8_variable : 0,
m->hint ? m->hint : &PL_sv_undef);
return m->hint;
}

Bool
AbstractMenu_enabled( Handle self, Bool set, char * varName, Bool enabled)
Expand All @@ -961,7 +1015,7 @@ AbstractMenu_enabled( Handle self, Bool set, char * varName, Bool enabled)
if ( m-> id > 0) {
if ( var-> stage <= csNormal && var-> system)
apc_menu_item_set_enabled( self, m);
notify( self, "<ssUi", "Change", "enabled",
notify( self, "<ssUi", "Change", "enabled",
m->variable ? m-> variable : varName,
m->variable ? m-> flags.utf8_variable : 0,
enabled);
Expand Down Expand Up @@ -1023,7 +1077,7 @@ AbstractMenu_image( Handle self, Bool set, char * varName, Handle image)
if ( m-> id > 0) {
if ( var-> stage <= csNormal && var-> system)
apc_menu_item_set_image( self, m);
notify( self, "<ssUH", "Change", "image",
notify( self, "<ssUH", "Change", "image",
m->variable ? m-> variable : varName,
m->variable ? m-> flags.utf8_variable : 0,
image);
Expand All @@ -1040,13 +1094,8 @@ AbstractMenu_options( Handle self, Bool set, char * varName, SV * options)
m = find_menuitem( self, varName, true);
if ( m == NULL) return NULL_SV;
if ( !set) {
HV * profile;
if ( m->options )
return newSVsv( m-> options);
profile = newHV();
if ( m-> icon ) pset_H(icon, m->icon);
if ( m-> group != 0 ) pset_i(group, m->group);
return newRV_noinc((SV*)profile);
SV *options = new_options(m);
return options ? newRV_noinc(options) : &PL_sv_undef;
}

if (!SvOK( SvRV( options))) {
Expand All @@ -1073,7 +1122,14 @@ AbstractMenu_options( Handle self, Bool set, char * varName, SV * options)
warn("Cannot set group on a divider item");
else
my->group(self, true, varName, pget_i(group));
pdelete(icon);
pdelete(group);
}
if ( pexist(hint)) {
if ( m-> flags. divider )
warn("Cannot set hint on a divider item");
else
my->hint(self, true, varName, pget_sv(hint));
pdelete(hint);
}
}
notify( self, "<ssUS", "Change", "options",
Expand Down Expand Up @@ -1102,7 +1158,7 @@ AbstractMenu_submenu( Handle self, Bool set, char * varName, SV * submenu)
m-> down = ( PMenuItemReg) my-> new_menu( self, submenu, 1, NULL);
if ( var-> stage <= csNormal && var-> system)
apc_menu_update( self, m-> down, m-> down);
notify( self, "<ssU", "Change", "submenu",
notify( self, "<ssU", "Change", "submenu",
m->variable ? m-> variable : varName,
m->variable ? m-> flags.utf8_variable : 0);

Expand All @@ -1129,7 +1185,7 @@ AbstractMenu_text( Handle self, Bool set, char * varName, SV * text)
if ( m-> id > 0) {
if ( var-> stage <= csNormal && var-> system)
apc_menu_item_set_text( self, m);
notify( self, "<ssUS", "Change", "text",
notify( self, "<ssUs", "Change", "text",
m->variable ? m-> variable : varName,
m->variable ? m-> flags.utf8_variable : 0,
text);
Expand All @@ -1152,7 +1208,7 @@ AbstractMenu_key( Handle self, Bool set, char * varName, SV * key)
if ( m-> id > 0) {
if ( var-> stage <= csNormal && var-> system)
apc_menu_item_set_key( self, m);
notify( self, "<ssUi", "Change", "key",
notify( self, "<ssUi", "Change", "key",
m->variable ? m-> variable : varName,
m->variable ? m-> flags.utf8_variable : 0,
m->key);
Expand All @@ -1168,8 +1224,8 @@ AbstractMenu_set_variable( Handle self, char * varName, SV * newName)
m = find_menuitem( self, varName, true);
if ( m == NULL) return;

notify( self, "<ssUS", "Change", "rename",
m->variable ? m-> variable : varName,
notify( self, "<ssUS", "Change", "rename",
m->variable ? m-> variable : varName,
m->variable ? m-> flags.utf8_variable : 0,
newName);

Expand Down Expand Up @@ -1331,7 +1387,7 @@ AbstractMenu_remove( Handle self, char * varName)
if ( prev) prev-> next = m-> next;
if ( m == var-> tree) var-> tree = m-> next;
m-> next = NULL;
notify( self, "<ssU", "Change", "remove",
notify( self, "<ssU", "Change", "remove",
m->variable ? m-> variable : varName,
m->variable ? m-> flags.utf8_variable : 0);
my-> dispose_menu( self, m);
Expand Down
1 change: 1 addition & 0 deletions class/AbstractMenu.cls
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ object Prima::AbstractMenu ( Prima::Component)
property Bool checked( char * varName);
property Handle icon ( char * varName);
property int group ( char * varName);
property SV * hint ( char * varName);
property SV * options( char * varName);
property Bool enabled( char * varName);
property Handle image ( char * varName);
Expand Down
2 changes: 2 additions & 0 deletions class/Widget.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ extern "C" {

#undef set_text
#undef get_text
#undef set_hint
#undef get_hint
#undef my
#define inherited CDrawable
#define enter_method PWidget_vmt selfvmt = ((( PWidget) self)-> self)
Expand Down
14 changes: 12 additions & 2 deletions class/Widget/events.c
Original file line number Diff line number Diff line change
Expand Up @@ -498,10 +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, "<sHs", "Menu", event-> gen. H, context);
} else
my-> notify( self, "<sHS", "Menu", event-> gen. H, &PL_sv_undef);
}
break;
case cmMenuSelect:
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, "<sHs", "Menu", event-> gen. H, context);
context = ((( PAbstractMenu) event->gen.H)-> self)-> make_id_context( event->gen.H, event->gen.i, buffer);
my-> notify( self, "<sHs", "MenuSelect", event->gen.H, context);
}
break;
case cmMouseClick:
Expand Down
29 changes: 26 additions & 3 deletions examples/menu.pl
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@ =head1 FEATURES

use strict;
use warnings;
use Prima qw( InputLine Label Application StdBitmap );
use Prima qw( InputLine Label Application StdBitmap);
use Prima::Menus;

package TestWindow;
use vars qw(@ISA);
@ISA = qw(Prima::MainWindow);
use Prima::Drawable::Markup q(M);

sub create_images_menu
{
Expand Down Expand Up @@ -113,6 +114,7 @@ sub create_custom_menu
$x1 + (( $isz > $i-> width ) ? ( $menu-> check_icon_size - $i-> width) / 2 : 0),
($y2 + $y1 - $i->height) / 2, $i);
},
hint => M 'Hints can be B<bold> and I<italic>',
} ];
}

Expand Down Expand Up @@ -175,7 +177,7 @@ sub create_menu
}],
["~Duplicate menu"=>sub{ TestWindow-> new( menu=>$_[0]-> menu)}],
]],
[ "~Input line" => [
[ il => "~Input line" => [
[ "Print ~text" => "Text"],
[ "Print ~selected" => "Selected"],
[ "Try \"selText\"" => "SelText"],
Expand All @@ -186,7 +188,7 @@ sub create_menu
[ coexistentor => "Coexistentor"=> ""],
]],
[], # divisor in main menu opens
[ "~Clusters" => [ # right-adjacent part
[ cl => "~Clusters" => [ # right-adjacent part
[ "*".checker => "Checking Item" => "Check" ],
[ "@" => "Auto Checking Item" => sub {print "new state: $_[2]\n" } ],
[],
Expand Down Expand Up @@ -273,6 +275,22 @@ sub BorderMode
$e-> borderWidth (( $e-> borderWidth == 1) ? 0 : 1);
}

sub on_menuselect
{
my ( $self, $menu, $item ) = @_;
$self->Hint->text( $menu->hint($item) // '' );
my $r = $menu->hint($item) // '';
}

sub on_menu
{
my ( $self, $menu, $item ) = @_;
if ( defined $item ) {
$self->Hint->{saved} //= $self->Hint->text;
} else {
$self->Hint->text( delete $self->Hint->{saved} );
}
}

package UserInit;

Expand All @@ -282,6 +300,9 @@ package UserInit;
menuItems => TestWindow::create_menu,
designScale => [ 7, 16 ],
);
$w->menu->ef->hint("This is menu containing editing commands");
$w->menu->il->hint("Do stuff with the input line");
$w->menu->cl->hint("Various selectors");

$w-> insert( "Prima::Menu::Bar",
pack => { pady => 20, padx => 20, fill => 'x', expand => 1},
Expand All @@ -300,11 +321,13 @@ package UserInit;
);

$w-> insert( "Label",
name => 'Hint',
pack => { pady => 20, padx => 20, fill => 'both', expand => 1},
text => "Type here something",
backColor => cl::Green,
valignment => ta::Center,
focusLink => $w-> InputLine1,
);
$w-> popupItems( $w-> menuItems);

run Prima;
3 changes: 3 additions & 0 deletions include/apricot.h
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,8 @@ CM(MenuItemMeasure)
CM(MenuItemPaint)
#define cmClipboard 0x0000002F /* called on X11 to precise type of data to be pasted */
CM(Clipboard)
#define cmMenuSelect 0x00000030 /* window notification to menu highlight */
CM(MenuSelect)

#define cmMenuCmd 0x00000050 /* interactive menu command */
CM(MenuCmd)
Expand Down Expand Up @@ -2852,6 +2854,7 @@ typedef struct _MenuItemReg { /* Menu item registration record */
Handle bitmap; /* bitmap if not NULL */
SV * code; /* code if not NULL */
SV * options; /* use options if not NULL */
SV * hint; /* hint if not NULL */
Handle icon; /* custom checked bitmap */
int group; /* radio group */
struct _MenuItemReg* down; /* pointer to submenu */
Expand Down
4 changes: 4 additions & 0 deletions pod/Prima/Menu.pod
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,10 @@ Same as the C<group> property.

Is used to replace the default checkmark bitmap on a menu item

=item hint SCALAR

Can be used to display a hint when menu item is highlighted

=item onMeasure MENUITEM, REF

Required when the custom painting is requested. It is called when the system
Expand Down
Loading

0 comments on commit 1ab13be

Please sign in to comment.