package
CORBA::MICO::CMenu;
use
Carp;
#--------------------------------------------------------------------
# Dynamic menu. Supports a single menu for several
# objects. Each time an object becomes active
# CMenu automatically rebuilds menu so as it becomes appropriate
# for active object.
#--------------------------------------------------------------------
use
Gtk 0.7006;
#--------------------------------------------------------------------
# Create new menu
# In: $topwindow - toplevel widget
#--------------------------------------------------------------------
sub
new {
my
(
$type
,
$topwindow
) =
@_
;
my
$class
=
ref
(
$type
) ||
$type
;
my
$accel_group
= new Gtk::AccelGroup;
my
$menu_name
=
"<menu_$serial>"
;
++
$serial
;
my
$item_factory
= new Gtk::ItemFactory(
'Gtk::MenuBar'
,
$menu_name
,
$accel_group
);
$accel_group
->attach(
$topwindow
);
my
$self
= {
'FACTORY'
=>
$item_factory
,
'NAME'
=>
$menu_name
,
'ACCEL_GROUP'
=>
$accel_group
,
'LAST_ACTION'
=> 0,
'CURR_ID'
=>
''
,
'WIDGET'
=>
$item_factory
->get_widget(
$menu_name
),
'ITEMS'
=> {} };
bless
$self
,
$class
;
return
$self
;
}
#--------------------------------------------------------------------
# widget - return main menu widget
#--------------------------------------------------------------------
sub
widget {
my
$self
=
shift
;
return
$self
->{
'WIDGET'
};
}
#--------------------------------------------------------------------
# Add a menu item
# In: $id - ID of object, empty string if item is going to be a global one
# $path - name of item (as in GtkItemFactoryEntry)
# $hotkey - hotkey (as accelerator in GtkItemFactoryEntry)
# $callback - callback
# $cb_data - callback data
#--------------------------------------------------------------------
sub
add_item {
my
(
$self
,
$id
,
$path
,
$hotkey
,
$callback
,
$cb_data
) =
@_
;
prepare_item(
$self
,
$id
,
$path
,
$hotkey
,
'Item'
,
$callback
,
$cb_data
);
}
#--------------------------------------------------------------------
# Create menu item if it doesn't exist yet
# Return control structure for it
# In: $id - ID of object, empty string if item is going to be a global one
# $path - name of item (as in GtkItemFactoryEntry)
# $hotkey - hotkey (as accelerator in GtkItemFactoryEntry)
# $type - item type: Item/Branch/LastBranch
# $callback - callback
# $cb_data - callback data
#--------------------------------------------------------------------
sub
prepare_item {
my
(
$self
,
$id
,
$path
,
$hotkey
,
$type
,
$callback
,
$cb_data
) =
@_
;
my
$items
=
$self
->{
'ITEMS'
};
my
$curr_item
;
if
( not
exists
(
$items
->{
$path
}) ) {
$curr_item
= {
'TYPE'
=>
$type
};
$items
->{
$path
} =
$curr_item
;
my
$action
= (
$type
eq
'Item'
) ? ++
$self
->{
'LAST_ACTION'
} : 0;
$curr_item
->{
'ACTION'
} =
$action
;
if
(
$path
=~ m
#(^/.*)/[^/]*$# ) { # dirname
$self
->prepare_item(
''
, $1,
undef
,
'Branch'
,
undef
,
undef
);
}
$type
=
'LastBranch'
if
$path
=~ m
#^/_?Help$#i;
$self
->{
'FACTORY'
}->create_item([
$path
,
$hotkey
,
$action
,
"<$type>"
],
sub
{
$self
->item_activated(
$curr_item
,
@_
) } );
}
else
{
$curr_item
=
$items
->{
$path
};
if
(
$curr_item
->{
'TYPE'
} ne
$type
) {
carp
"$self->{MENU_NAME}:$path already defined as a $type"
;
return
undef
;
}
}
if
(
$id
and
exists
(
$curr_item
->{
$id
}) ) {
carp
"ID $id already defined in menu item $self->{MENU_NAME}:$path"
;
return
;
}
$curr_item
->{
$id
} = [
$callback
,
$cb_data
];
return
$items
;
}
#--------------------------------------------------------------------
# Make unsensitive all menu items except ones having given ID
#--------------------------------------------------------------------
sub
activate_id {
my
(
$self
,
$id
) =
@_
;
my
$item_factory
=
$self
->{
'FACTORY'
};
my
(
$key
,
$items
);
while
( (
$key
,
$item
) =
each
%{
$self
->{
'ITEMS'
}} ) {
my
$sflag
= (
$item
->{
'TYPE'
} eq
'Item'
and not
exists
$item
->{
$id
})? 0: 1;
$self
->mask_item(
$key
,
$sflag
);
}
$self
->{
'CURR_ID'
} =
$id
;
}
#--------------------------------------------------------------------
# make menu item sensitive/unsensitive
# In: $name - item name
# $flag - TRUE - sensitive, FALSE-unsensitive
#--------------------------------------------------------------------
sub
mask_item {
my
(
$self
,
$name
,
$flag
) =
@_
;
my
$item_factory
=
$self
->{
'FACTORY'
};
my
$item
=
$self
->{
'ITEMS'
}->{
$name
};
if
( not
defined
(
$item
) ) {
carp
"No menu item $name"
;
return
;
}
return
if
exists
$item
->{
''
};
# do not mask field if it is global
my
$widget
=
$item_factory
->get_widget_by_action(
$item
->{
'ACTION'
});
$widget
->set_sensitive(
$flag
);
}
#--------------------------------------------------------------------
# Menu callback: item activated
#--------------------------------------------------------------------
sub
item_activated {
my
(
$self
,
$item
,
$widget
,
$action
) =
@_
;
$id
=
$self
->{
'CURR_ID'
};
my
$cb
=
$item
->{
$id
};
if
(
defined
(
$cb
) ) {
&{
$cb
->[0]}(
$cb
->[1]);
}
elsif
(
$id
ne
''
) {
# global item: quit, help, etc
$cb
=
$item
->{
''
};
&{
$cb
->[0]}(
$cb
->[1])
if
defined
(
$cb
);
}
}
$serial
= 1;
1;