2004-04-22 11:15:05 +00:00
|
|
|
|
#include <controls.h>
|
2003-01-28 14:27:05 +00:00
|
|
|
|
#include <mask.h>
|
2004-04-23 08:59:58 +00:00
|
|
|
|
#include <statbar.h>
|
2003-01-28 14:27:05 +00:00
|
|
|
|
#include <urldefid.h>
|
|
|
|
|
#include <utility.h>
|
|
|
|
|
|
|
|
|
|
#include "ba0102.h"
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
// TMenu_tree
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
const TSubmenu& TMenu_tree::curr_submenu() const
|
|
|
|
|
{
|
|
|
|
|
CHECKS(_submenu, "NULL submenu ", (const char*)_curr_id);
|
|
|
|
|
return *_submenu;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const TMenuitem& TMenu_tree::curr_item() const
|
|
|
|
|
{
|
|
|
|
|
const TSubmenu& sm = curr_submenu();
|
|
|
|
|
if (_menuitem < 0 || _menuitem >= sm.items())
|
|
|
|
|
{
|
|
|
|
|
NFCHECK("Invalid submenu item %d in %s", _menuitem, (const char*)sm.name());
|
|
|
|
|
return sm.item(0);
|
|
|
|
|
}
|
|
|
|
|
return sm.item(_menuitem);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct TFind_node_data
|
|
|
|
|
{
|
|
|
|
|
TString _id;
|
|
|
|
|
size_t _count;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct TFind_string_data
|
|
|
|
|
{
|
|
|
|
|
TString _str;
|
2004-05-13 15:12:14 +00:00
|
|
|
|
TAssoc_array* _ignore_list;
|
2003-01-28 14:27:05 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
HIDDEN bool find_string_callback(TTree& tree, void* jolly, word flags)
|
|
|
|
|
{
|
|
|
|
|
if (flags == SCAN_PRE_ORDER)
|
|
|
|
|
{
|
|
|
|
|
TMenu_tree& mt = (TMenu_tree&)tree;
|
|
|
|
|
const TSubmenu& sm = mt.curr_submenu();
|
2003-05-16 13:10:09 +00:00
|
|
|
|
|
|
|
|
|
if (sm.disabled())
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
TFind_string_data& data = *(TFind_string_data*)jolly;
|
2003-01-28 14:27:05 +00:00
|
|
|
|
if (data._ignore_list->is_key(sm.name()))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
TString desc; mt.get_description(desc);
|
|
|
|
|
desc.upper();
|
|
|
|
|
if (desc.find(data._str) >= 0 || desc.match(data._str))
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HIDDEN bool find_node_callback(TTree& tree, void* jolly, word flags)
|
|
|
|
|
{
|
|
|
|
|
if (flags == SCAN_PRE_ORDER)
|
|
|
|
|
{
|
|
|
|
|
TFind_node_data& data = *(TFind_node_data*)jolly;
|
|
|
|
|
data._count++;
|
|
|
|
|
TString id; tree.curr_id(id);
|
|
|
|
|
if (id == data._id)
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HIDDEN bool find_leaf_callback(TTree& tree, void* jolly, word flags)
|
|
|
|
|
{
|
|
|
|
|
if (flags == SCAN_PRE_ORDER)
|
|
|
|
|
{
|
|
|
|
|
const TString& leaf = *(TString*)jolly;
|
|
|
|
|
TString id; tree.curr_id(id);
|
|
|
|
|
const int slash = id.rfind('/');
|
|
|
|
|
if (slash > 0)
|
|
|
|
|
id = id.mid(slash+1);
|
|
|
|
|
if (id == leaf)
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TMenu_tree::find_string(const TString& str)
|
|
|
|
|
{
|
|
|
|
|
TFind_string_data data;
|
|
|
|
|
data._str = str; data._str.upper();
|
|
|
|
|
data._ignore_list = &_menu->search_ignore_list();
|
|
|
|
|
|
|
|
|
|
if (data._str != _menu->last_search_string())
|
|
|
|
|
{
|
|
|
|
|
_menu->last_search_string() = data._str;
|
|
|
|
|
_menu->search_ignore_list().destroy();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
goto_root();
|
|
|
|
|
bool ok = scan_depth_first(find_string_callback, &data, SCAN_PRE_ORDER);
|
|
|
|
|
if (ok)
|
|
|
|
|
_menu->search_ignore_list().add(curr_submenu().name());
|
|
|
|
|
else
|
|
|
|
|
_menu->search_ignore_list().destroy();
|
|
|
|
|
|
|
|
|
|
return ok;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TMenu_tree::find_leaf(const TString& str)
|
|
|
|
|
{
|
|
|
|
|
goto_root();
|
|
|
|
|
bool ok = scan_depth_first(find_leaf_callback, (void *)&str, SCAN_PRE_ORDER);
|
|
|
|
|
return ok;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TMenu_tree::node2id(const TObject* node, TString& id) const
|
|
|
|
|
{
|
|
|
|
|
TString* str = (TString*)node;
|
|
|
|
|
id = *str;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TMenu_tree::goto_root()
|
|
|
|
|
{
|
|
|
|
|
TSubmenu* sm = _menu->find(_root_id);
|
|
|
|
|
if (sm)
|
|
|
|
|
{
|
|
|
|
|
_curr_id = _root_id;
|
|
|
|
|
_curr_id << ".0";
|
|
|
|
|
_submenu = sm;
|
|
|
|
|
_menuitem = 0;
|
|
|
|
|
}
|
|
|
|
|
return sm != NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TMenu_tree::goto_firstson()
|
|
|
|
|
{
|
|
|
|
|
const TMenuitem& mi = curr_item();
|
|
|
|
|
if (mi.is_submenu())
|
|
|
|
|
{
|
|
|
|
|
const TSubmenu* sm = _menu->find(mi.action());
|
|
|
|
|
if (sm && sm->items() > 0)
|
|
|
|
|
{
|
|
|
|
|
_curr_id << '/' << mi.action() << ".0";
|
|
|
|
|
_submenu = sm;
|
|
|
|
|
_menuitem = 0;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TMenu_tree::goto_rbrother()
|
|
|
|
|
{
|
|
|
|
|
if (_menuitem < _submenu->items()-1)
|
|
|
|
|
{
|
|
|
|
|
const int dot = _curr_id.rfind('.');
|
|
|
|
|
_curr_id.cut(dot+1);
|
|
|
|
|
_curr_id << (++_menuitem);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TMenu_tree::goto_node(const TString &id)
|
|
|
|
|
{
|
|
|
|
|
const int dot = id.rfind('.');
|
|
|
|
|
CHECKS(dot > 0, "Invalid tree node ", (const char*)id);
|
|
|
|
|
_menuitem = atoi(id.mid(dot+1));
|
|
|
|
|
_curr_id = id.left(dot);
|
|
|
|
|
const int slash = _curr_id.rfind('/');
|
|
|
|
|
|
|
|
|
|
_curr_id = _curr_id.mid(slash+1);
|
|
|
|
|
_submenu = _menu->find(_curr_id);
|
|
|
|
|
_curr_id = id;
|
|
|
|
|
|
|
|
|
|
return _submenu != NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TMenu_tree::has_son() const
|
|
|
|
|
{
|
|
|
|
|
const TMenuitem& mi = curr_item();
|
|
|
|
|
return mi.is_submenu();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TMenu_tree::has_rbrother() const
|
|
|
|
|
{
|
|
|
|
|
return _menuitem < _submenu->items()-1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TMenu_tree::has_root() const
|
|
|
|
|
{
|
|
|
|
|
return _root_id.not_empty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TMenu_tree::has_father() const
|
|
|
|
|
{
|
|
|
|
|
return _curr_id.find('/') > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TMenu_tree::has_lbrother() const
|
|
|
|
|
{
|
|
|
|
|
return _menuitem > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TMenu_tree::goto_father()
|
|
|
|
|
{
|
|
|
|
|
const int slash = _curr_id.rfind('/');
|
|
|
|
|
if (slash > 0)
|
|
|
|
|
{
|
|
|
|
|
const TString id = _curr_id.left(slash);
|
|
|
|
|
return goto_node(id);
|
|
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TMenu_tree::goto_lbrother()
|
|
|
|
|
{
|
|
|
|
|
if (_menuitem > 0)
|
|
|
|
|
{
|
|
|
|
|
const int dot = _curr_id.rfind('.');
|
|
|
|
|
_curr_id.cut(dot+1);
|
|
|
|
|
_curr_id << (--_menuitem);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TObject* TMenu_tree::curr_node() const
|
|
|
|
|
{
|
|
|
|
|
return &((TMenu_tree*)this)->_curr_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TMenu_tree::get_description(TString& desc) const
|
|
|
|
|
{
|
|
|
|
|
const TMenuitem& mi = curr_item();
|
|
|
|
|
desc = mi.caption();
|
|
|
|
|
return desc.not_empty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TImage* TMenu_tree::image(bool selected) const
|
|
|
|
|
{
|
|
|
|
|
const TMenuitem& mi = curr_item();
|
|
|
|
|
if (mi.disabled())
|
|
|
|
|
return get_res_image(BMP_STOP);
|
|
|
|
|
return TTree::image(selected);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
long TMenu_tree::find_node(const TString& id)
|
|
|
|
|
{
|
|
|
|
|
TFind_node_data data;
|
|
|
|
|
data._id = id;
|
|
|
|
|
data._count = 0;
|
|
|
|
|
goto_root();
|
|
|
|
|
scan_depth_first(find_node_callback, &data,
|
|
|
|
|
SCAN_PRE_ORDER | SCAN_IGNORING_UNEXPANDED);
|
|
|
|
|
return data._count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TMenu_tree::TMenu_tree(TMenu& menu)
|
|
|
|
|
: _menu(&menu), _curr_id(128, '/')
|
|
|
|
|
{
|
|
|
|
|
_root_id = _menu->current().name();
|
|
|
|
|
goto_root();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
// Utility
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
void synchronize_tree_field(TTree_field& tf)
|
|
|
|
|
{
|
|
|
|
|
TMenu_tree& mt = *(TMenu_tree*)tf.tree();
|
|
|
|
|
|
|
|
|
|
tf.select_current();
|
|
|
|
|
TString id; mt.curr_id(id); // Memorizza nodo corrente
|
|
|
|
|
|
|
|
|
|
mt.shrink_all();
|
|
|
|
|
mt.goto_node(id);
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
mt.expand();
|
|
|
|
|
}
|
|
|
|
|
while (mt.goto_father());
|
|
|
|
|
|
|
|
|
|
mt.goto_node(id);
|
|
|
|
|
tf.set_tree(&mt); // Azzera origine
|
|
|
|
|
|
|
|
|
|
TField_window& win = tf.win();
|
|
|
|
|
win.force_update();
|
|
|
|
|
}
|
|
|
|
|
|
2004-04-21 15:49:15 +00:00
|
|
|
|
bool can_be_transparent(const TImage& i)
|
|
|
|
|
{
|
|
|
|
|
const int w = i.width()-1;
|
|
|
|
|
const int h = i.height()-1;
|
|
|
|
|
const COLOR col = i.get_pixel(0,0);
|
|
|
|
|
if (i.get_pixel(w,0) != col)
|
|
|
|
|
return FALSE;
|
|
|
|
|
if (i.get_pixel(w,h) != col)
|
|
|
|
|
return FALSE;
|
|
|
|
|
if (i.get_pixel(0,h) != col)
|
|
|
|
|
return FALSE;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-28 14:27:05 +00:00
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
// TMenulist_field
|
|
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
class TMenulist_images : public TCache
|
|
|
|
|
{
|
|
|
|
|
WINDOW _win;
|
2004-04-22 11:15:05 +00:00
|
|
|
|
int _max_side;
|
2003-01-28 14:27:05 +00:00
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
TObject* key2obj(const char* key);
|
|
|
|
|
|
|
|
|
|
public:
|
2004-04-22 11:15:05 +00:00
|
|
|
|
void set_owner_info(WINDOW win, int max_side);
|
2004-04-23 08:59:58 +00:00
|
|
|
|
TImage* image(const char* filename);
|
2004-04-22 11:15:05 +00:00
|
|
|
|
TMenulist_images() : TCache(17), _win(NULL_WIN), _max_side(0) { }
|
2003-01-28 14:27:05 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
inline int fast_hypot(int x, int y)
|
|
|
|
|
{
|
|
|
|
|
// loop unrolled
|
|
|
|
|
#define TEST(s, h, i) { const int k = h+i; if (k*k <= s) h = k; }
|
|
|
|
|
const int s = x*x + y*y;
|
|
|
|
|
int h = 0;
|
|
|
|
|
TEST(s, h, 512); TEST(s, h, 256); TEST(s, h, 128);
|
|
|
|
|
TEST(s, h, 64); TEST(s, h, 32); TEST(s, h, 16);
|
|
|
|
|
TEST(s, h, 8); TEST(s, h, 4); TEST(s, h, 2); TEST(s, h, 1);
|
|
|
|
|
return h;
|
|
|
|
|
}
|
|
|
|
|
|
2004-04-22 11:15:05 +00:00
|
|
|
|
void TMenulist_images::set_owner_info(WINDOW win, int max_side)
|
|
|
|
|
{
|
|
|
|
|
_win = win;
|
|
|
|
|
_max_side = max_side;
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-28 14:27:05 +00:00
|
|
|
|
TObject* TMenulist_images::key2obj(const char* key)
|
|
|
|
|
{
|
|
|
|
|
TImage* img = NULL;
|
|
|
|
|
|
2003-05-14 13:35:51 +00:00
|
|
|
|
TFilename name;
|
|
|
|
|
const char* ext[3] = { "jpg", "gif", "bmp" };
|
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
|
|
|
{
|
|
|
|
|
name = key;
|
|
|
|
|
name << '.' << ext[i];
|
2005-03-17 18:21:37 +00:00
|
|
|
|
if (name.custom_path())
|
2003-05-14 13:35:51 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (name.exist())
|
2003-01-28 14:27:05 +00:00
|
|
|
|
{
|
|
|
|
|
TWait_cursor hourglass;
|
2003-03-11 11:09:18 +00:00
|
|
|
|
TImage image(name);
|
2003-01-28 14:27:05 +00:00
|
|
|
|
if (can_be_transparent(image))
|
|
|
|
|
image.convert_transparent_color(NORMAL_BACK_COLOR);
|
|
|
|
|
|
2004-04-21 15:49:15 +00:00
|
|
|
|
RCT rct; xvt_vobj_get_client_rect(_win, &rct);
|
2004-04-22 11:15:05 +00:00
|
|
|
|
const double max_img = (double)_max_side;
|
|
|
|
|
const double max_lgo = rct.right - _max_side;
|
2004-04-21 15:49:15 +00:00
|
|
|
|
|
|
|
|
|
if (strcmp(key,"logo") != 0)
|
|
|
|
|
{
|
|
|
|
|
const double ratiox = max_img / image.width();
|
|
|
|
|
const double ratioy = max_img / image.height();
|
|
|
|
|
const double ratio = min(ratiox, ratioy);
|
|
|
|
|
const int maxx = int(ratio * image.width());
|
|
|
|
|
const int maxy = int(ratio * image.height());
|
|
|
|
|
img = new TImage(image, maxx, maxy);
|
|
|
|
|
|
2004-04-23 08:59:58 +00:00
|
|
|
|
//Sfumatura costante sui lati sx e up
|
|
|
|
|
const double radius = min(maxx,maxy)/6.0;
|
2004-04-21 15:49:15 +00:00
|
|
|
|
for (int y = 0; y < maxy; y++)
|
|
|
|
|
{
|
|
|
|
|
for (int x = 0; x < maxx; x++)
|
|
|
|
|
{
|
|
|
|
|
if (x <= radius || y <= radius)
|
2003-10-14 13:44:01 +00:00
|
|
|
|
{
|
2004-04-22 11:15:05 +00:00
|
|
|
|
double perc = 1.0;
|
|
|
|
|
if (x <= radius && y <= radius)
|
|
|
|
|
{
|
|
|
|
|
const int r = fast_hypot(int(radius-x),int(radius-y));
|
|
|
|
|
if (r <= radius)
|
|
|
|
|
perc = 1.0-r/radius;
|
|
|
|
|
else
|
|
|
|
|
perc = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
perc = min(x,y)/radius;
|
|
|
|
|
|
2004-04-21 15:49:15 +00:00
|
|
|
|
COLOR col = img->get_pixel(x, y);
|
2003-10-14 13:44:01 +00:00
|
|
|
|
COLOR bri = blend_colors(col, NORMAL_BACK_COLOR, perc);
|
2004-04-21 15:49:15 +00:00
|
|
|
|
img->set_pixel(x, y, bri);
|
2003-10-14 13:44:01 +00:00
|
|
|
|
}
|
2003-03-11 11:09:18 +00:00
|
|
|
|
}
|
2004-04-21 15:49:15 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2004-04-22 11:15:05 +00:00
|
|
|
|
else //caso particolare del logo
|
2004-04-21 15:49:15 +00:00
|
|
|
|
{
|
|
|
|
|
const double ratio = max_lgo / image.width();
|
|
|
|
|
const int maxx = int(ratio * image.width());
|
|
|
|
|
const int maxy = int(ratio * image.height());
|
|
|
|
|
img = new TImage(image, maxx, maxy);
|
|
|
|
|
}
|
2003-01-28 14:27:05 +00:00
|
|
|
|
}
|
|
|
|
|
return img;
|
|
|
|
|
}
|
|
|
|
|
|
2004-04-23 08:59:58 +00:00
|
|
|
|
TImage* TMenulist_images::image(const char* name)
|
2003-01-28 14:27:05 +00:00
|
|
|
|
{
|
2004-04-23 08:59:58 +00:00
|
|
|
|
TObject* obj = objptr(name);
|
|
|
|
|
if (obj == NULL &&
|
|
|
|
|
xvt_str_compare_ignoring_case(name, "ba00") != 0 &&
|
|
|
|
|
xvt_str_compare_ignoring_case(name, "logo") != 0)
|
2003-05-14 13:35:51 +00:00
|
|
|
|
obj = objptr("ba00");
|
2003-01-28 14:27:05 +00:00
|
|
|
|
return (TImage*)obj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class TMenulist_window : public TField_window
|
|
|
|
|
{
|
|
|
|
|
private:
|
2004-04-28 20:14:14 +00:00
|
|
|
|
TMenu_tree* _tree;
|
2004-04-22 11:15:05 +00:00
|
|
|
|
size_t MENU_COLS, MENU_ROWS;
|
|
|
|
|
|
2003-01-28 14:27:05 +00:00
|
|
|
|
TString _curr_node;
|
|
|
|
|
bool _can_go_back;
|
|
|
|
|
|
|
|
|
|
TMenulist_images _images;
|
|
|
|
|
TString _image_name;
|
|
|
|
|
|
|
|
|
|
int _selected;
|
|
|
|
|
TPointer_array _sorted;
|
|
|
|
|
|
2004-04-23 08:59:58 +00:00
|
|
|
|
clock_t _last_update;
|
|
|
|
|
|
2003-01-28 14:27:05 +00:00
|
|
|
|
protected:
|
|
|
|
|
virtual void update();
|
|
|
|
|
virtual void handler(WINDOW win, EVENT* ep);
|
|
|
|
|
virtual bool on_key(KEY k);
|
2004-04-23 08:59:58 +00:00
|
|
|
|
virtual void on_idle();
|
2003-01-28 14:27:05 +00:00
|
|
|
|
|
|
|
|
|
void synchronize_buddy_tree() const;
|
|
|
|
|
void draw_item(int i);
|
2004-04-23 08:59:58 +00:00
|
|
|
|
void draw_menu_caption(COLOR rgb);
|
2003-01-28 14:27:05 +00:00
|
|
|
|
void click_on(int index);
|
|
|
|
|
void select(int s, int direction);
|
|
|
|
|
|
|
|
|
|
public:
|
2003-10-14 13:44:01 +00:00
|
|
|
|
void curr_item(TToken_string& id) const;
|
2003-01-28 14:27:05 +00:00
|
|
|
|
void set_menu(TMenu_tree& mt);
|
|
|
|
|
|
|
|
|
|
TMenulist_window(int x, int y, int dx, int dy, WINDOW parent, TMenulist_field* owner);
|
|
|
|
|
virtual ~TMenulist_window();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void TMenulist_window::draw_item(int i)
|
|
|
|
|
{
|
|
|
|
|
if (i < 0 && i >= _sorted.items())
|
|
|
|
|
return; // Scarta elementi non validi
|
|
|
|
|
|
|
|
|
|
RCT rct; xvt_vobj_get_client_rect(win(), &rct);
|
|
|
|
|
const int width = rct.right - rct.left;
|
|
|
|
|
const int height = rct.bottom - rct.top;
|
|
|
|
|
|
|
|
|
|
xvt_set_font(win(), NULL, 0, 0); // Set default font
|
|
|
|
|
set_opaque_text(TRUE);
|
|
|
|
|
|
|
|
|
|
const TMenuitem& item = (const TMenuitem&)_sorted[i];
|
|
|
|
|
if (i == _selected && item.enabled())
|
2003-10-03 08:12:08 +00:00
|
|
|
|
{
|
2004-04-22 11:15:05 +00:00
|
|
|
|
//testo nero su sfondo con colore del focus se la voce e' selezionata
|
2003-01-28 14:27:05 +00:00
|
|
|
|
set_color(item.color(), FOCUS_BACK_COLOR);
|
2003-10-03 08:12:08 +00:00
|
|
|
|
}
|
2003-01-28 14:27:05 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
2004-04-22 11:15:05 +00:00
|
|
|
|
set_color(item.color(), NORMAL_BACK_COLOR); //testo nero su sfondo trasparente x voci non selezionate
|
2003-01-28 14:27:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const int row = i / MENU_COLS;
|
|
|
|
|
const int col = i % MENU_COLS;
|
|
|
|
|
const int left = col * width / MENU_COLS;
|
|
|
|
|
const int right = (col+1) * width / MENU_COLS;
|
|
|
|
|
const int top = row * height / MENU_ROWS;
|
2004-03-31 12:48:16 +00:00
|
|
|
|
// const int bottom = (row+1) * height / MENU_ROWS;
|
2003-01-28 14:27:05 +00:00
|
|
|
|
|
|
|
|
|
const int maxchars = (right-left)/CHARX - 1;
|
|
|
|
|
const int cx = (left+right)/2;
|
2004-03-31 12:48:16 +00:00
|
|
|
|
// const int cy = (top+bottom)/2; verificare
|
2003-01-28 14:27:05 +00:00
|
|
|
|
|
|
|
|
|
const int ico = item.enabled() ? item.icon() : 0;
|
|
|
|
|
const int ix = cx-16;
|
|
|
|
|
const int iy = top+2;
|
|
|
|
|
if (item.is_submenu())
|
|
|
|
|
{
|
|
|
|
|
xvt_dwin_draw_icon(win(), ix, iy, 10202);
|
|
|
|
|
if ( ico > 0)
|
|
|
|
|
xvt_dwin_draw_icon(win(), ix, iy+4, ico);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
xvt_dwin_draw_icon(win(), ix, iy, ico > 0 ? ico : ICON_RSRC);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TString str = item.caption();
|
|
|
|
|
if (i == 0 && _can_go_back)
|
2004-04-22 11:15:05 +00:00
|
|
|
|
str = "(..)";
|
2003-01-28 14:27:05 +00:00
|
|
|
|
|
|
|
|
|
TParagraph_string para(str, maxchars);
|
|
|
|
|
int y = iy + 32 + CHARY-2;
|
|
|
|
|
FOR_EACH_TOKEN(para, line)
|
|
|
|
|
{
|
|
|
|
|
const int ll = xvt_dwin_get_text_width(win(), line, -1);
|
|
|
|
|
const int x = cx - ll/2;
|
|
|
|
|
xvt_dwin_draw_text(win(), x, y, line, -1);
|
|
|
|
|
y += CHARY-2;
|
|
|
|
|
}
|
|
|
|
|
if (item.disabled())
|
|
|
|
|
xvt_dwin_draw_icon(win(), ix+4, iy+4, 10203); // Stop icon
|
|
|
|
|
}
|
|
|
|
|
|
2004-04-23 08:59:58 +00:00
|
|
|
|
//scrive la voce di menu corrente a video
|
|
|
|
|
void TMenulist_window::draw_menu_caption(COLOR rgb)
|
|
|
|
|
{
|
|
|
|
|
const char* caption = "";
|
|
|
|
|
if (_sorted.items() > 1)
|
|
|
|
|
{
|
|
|
|
|
const TMenuitem& mi = (const TMenuitem&)_sorted[1];
|
|
|
|
|
const TSubmenu& sm = mi.submenu();
|
|
|
|
|
caption = sm.caption();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
const TMenuitem& mi = (const TMenuitem&)_sorted[0];
|
|
|
|
|
caption = mi.caption();
|
|
|
|
|
}
|
|
|
|
|
RCT rct; xvt_vobj_get_client_rect(win(), &rct);
|
|
|
|
|
const int x = rct.left+2;
|
|
|
|
|
int y = rct.bottom-CHARY;
|
|
|
|
|
if (ADVANCED_GRAPHICS)
|
|
|
|
|
{
|
|
|
|
|
const TImage* logo = _images.image("logo");
|
|
|
|
|
if (logo != NULL)
|
2004-05-17 15:39:53 +00:00
|
|
|
|
y -= logo->height() + ROWY; //+ROWY per staccare scritta dal logo
|
2004-04-23 08:59:58 +00:00
|
|
|
|
}
|
2004-05-13 15:12:14 +00:00
|
|
|
|
XVT_FNTID font_menu = xvt_font_create();
|
|
|
|
|
xvt_font_copy(font_menu, xvt_default_font(true), XVT_FA_ALL);
|
|
|
|
|
const int size = xvt_font_get_size(font_menu);
|
2004-05-17 15:39:53 +00:00
|
|
|
|
xvt_font_set_size(font_menu, 130 * size / 100); //altezza font il 30% maggiore di quello di menu
|
2004-05-13 15:12:14 +00:00
|
|
|
|
|
|
|
|
|
xvt_dwin_set_font(win(), font_menu);
|
2004-04-23 08:59:58 +00:00
|
|
|
|
set_color(rgb, NORMAL_BACK_COLOR);
|
|
|
|
|
xvt_dwin_draw_text(win(), x, y, caption, -1);
|
|
|
|
|
|
2004-05-13 15:12:14 +00:00
|
|
|
|
xvt_font_destroy(font_menu);
|
|
|
|
|
|
2004-04-23 08:59:58 +00:00
|
|
|
|
statbar_set_title(TASK_WIN, caption);
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-28 14:27:05 +00:00
|
|
|
|
void TMenulist_window::update()
|
2003-05-26 13:00:26 +00:00
|
|
|
|
{
|
|
|
|
|
const bool db = _tree != NULL && ADVANCED_GRAPHICS;
|
|
|
|
|
TImage* img = db ? _images.image(_image_name) : NULL; // Delay time before clearing
|
2003-01-28 14:27:05 +00:00
|
|
|
|
|
|
|
|
|
TField_window::update();
|
|
|
|
|
if (_tree == NULL)
|
|
|
|
|
return; // Nothing to draw
|
|
|
|
|
|
|
|
|
|
if (img != NULL)
|
|
|
|
|
{
|
|
|
|
|
RCT rct; xvt_vobj_get_client_rect(win(), &rct);
|
2004-04-21 15:49:15 +00:00
|
|
|
|
const int x = (rct.right - img->width());
|
|
|
|
|
const int y = (rct.bottom - img->height());
|
2003-01-28 14:27:05 +00:00
|
|
|
|
img->draw(win(), x, y);
|
|
|
|
|
}
|
|
|
|
|
|
2004-04-21 15:49:15 +00:00
|
|
|
|
TImage* logo = db ? _images.image("logo") : NULL; //logo del programma
|
|
|
|
|
if (logo != NULL) //disegna il logo
|
|
|
|
|
{
|
|
|
|
|
RCT rct; xvt_vobj_get_client_rect(win(), &rct);
|
|
|
|
|
const int x = rct.left;
|
|
|
|
|
const int y = rct.bottom - logo->height();
|
|
|
|
|
logo->draw(win(), x, y);
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-28 14:27:05 +00:00
|
|
|
|
for (int i = 0; i < _sorted.items(); i++)
|
|
|
|
|
draw_item(i);
|
2004-04-22 11:15:05 +00:00
|
|
|
|
|
2004-04-23 08:59:58 +00:00
|
|
|
|
if (ADVANCED_GRAPHICS)
|
|
|
|
|
_last_update = clock();
|
2004-04-22 11:15:05 +00:00
|
|
|
|
else
|
2004-04-23 08:59:58 +00:00
|
|
|
|
draw_menu_caption(NORMAL_COLOR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TMenulist_window::on_idle()
|
|
|
|
|
{
|
|
|
|
|
if (ADVANCED_GRAPHICS)
|
2004-04-22 11:15:05 +00:00
|
|
|
|
{
|
2004-04-30 22:08:29 +00:00
|
|
|
|
#ifdef LINUX
|
|
|
|
|
const clock_t max_clock = (3*CLOCKS_PER_SEC) / 10;
|
|
|
|
|
#else
|
2004-04-23 08:59:58 +00:00
|
|
|
|
const clock_t max_clock = 3*CLOCKS_PER_SEC;
|
2004-04-30 22:08:29 +00:00
|
|
|
|
#endif
|
2004-04-23 08:59:58 +00:00
|
|
|
|
const clock_t elapsed = clock() - _last_update;
|
|
|
|
|
if (elapsed <= max_clock)
|
|
|
|
|
{
|
|
|
|
|
const double perc = double(elapsed) / double(max_clock);
|
|
|
|
|
const COLOR rgb = blend_colors(NORMAL_COLOR, NORMAL_BACK_COLOR, perc);
|
|
|
|
|
draw_menu_caption(rgb);
|
|
|
|
|
}
|
2004-04-22 11:15:05 +00:00
|
|
|
|
}
|
2003-01-28 14:27:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TMenulist_window::click_on(int index)
|
|
|
|
|
{
|
|
|
|
|
if (index >= 0 && index < _sorted.items())
|
|
|
|
|
{
|
|
|
|
|
const TMenuitem& mi = (const TMenuitem&)_sorted[index];
|
|
|
|
|
if (mi.enabled())
|
|
|
|
|
{
|
2003-10-14 13:44:01 +00:00
|
|
|
|
if (xvt_vobj_get_attr(NULL_WIN, ATTR_SPEECH_MODE) & (1<<7))
|
|
|
|
|
{
|
|
|
|
|
const TString& str = mi.caption();
|
|
|
|
|
if (str.find("..") < 0)
|
|
|
|
|
xvt_dm_post_speech(str, 7, TRUE);
|
|
|
|
|
}
|
2003-01-28 14:27:05 +00:00
|
|
|
|
if (mi.is_submenu())
|
|
|
|
|
{
|
|
|
|
|
if (index == 0 && _can_go_back) // S<> di un livello
|
|
|
|
|
{
|
|
|
|
|
_tree->goto_node(_curr_node);
|
|
|
|
|
_tree->goto_father();
|
|
|
|
|
set_menu(*_tree);
|
|
|
|
|
}
|
|
|
|
|
else // Gi<47> di un livello
|
|
|
|
|
{
|
|
|
|
|
if (mi.perform()) // Eventuale richiesta ditta
|
|
|
|
|
{
|
|
|
|
|
_tree->goto_node(_curr_node);
|
|
|
|
|
const TSubmenu& mnu = _tree->curr_submenu();
|
|
|
|
|
for (int i = 0; i < mnu.items(); i++)
|
|
|
|
|
{
|
|
|
|
|
const TMenuitem& ti = mnu[i];
|
|
|
|
|
if (ti.action() == mi.action())
|
|
|
|
|
{
|
|
|
|
|
_tree->goto_firstson();
|
|
|
|
|
set_menu(*_tree);
|
|
|
|
|
synchronize_buddy_tree();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
_tree->goto_rbrother();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
mi.perform();
|
|
|
|
|
}
|
|
|
|
|
set_focus();
|
|
|
|
|
}
|
2003-10-14 13:44:01 +00:00
|
|
|
|
else
|
|
|
|
|
xvt_sys_beep(1);
|
2003-01-28 14:27:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TMenulist_window::handler(WINDOW win, EVENT* ep)
|
|
|
|
|
{
|
|
|
|
|
switch (ep->type)
|
|
|
|
|
{
|
|
|
|
|
case E_MOUSE_DOWN:
|
|
|
|
|
{
|
2003-12-19 14:34:56 +00:00
|
|
|
|
RCT rct; xvt_vobj_get_client_rect(win, &rct);
|
|
|
|
|
const int row = ep->v.mouse.where.v * MENU_ROWS / rct.bottom;
|
|
|
|
|
const int col = ep->v.mouse.where.h * MENU_COLS / rct.right;
|
2004-03-31 12:48:16 +00:00
|
|
|
|
const int index = row * MENU_COLS + col;
|
2003-12-19 14:34:56 +00:00
|
|
|
|
if (ep->v.mouse.button > 0) // Tasto destro
|
2003-01-28 14:27:05 +00:00
|
|
|
|
{
|
2003-12-19 14:34:56 +00:00
|
|
|
|
if (index < _sorted.items())
|
|
|
|
|
{
|
|
|
|
|
const TMenuitem& mi = (const TMenuitem&)_sorted[index];
|
|
|
|
|
message_box(mi.action());
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (_can_go_back)
|
|
|
|
|
click_on(0);
|
|
|
|
|
}
|
2003-01-28 14:27:05 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2003-12-19 14:34:56 +00:00
|
|
|
|
click_on(index); // Tasto sinistro
|
2003-01-28 14:27:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TField_window::handler(win, ep);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TMenulist_window::select(int s, int direction)
|
|
|
|
|
{
|
|
|
|
|
const int old_selection = _selected;
|
|
|
|
|
|
|
|
|
|
if (s < 0)
|
|
|
|
|
s = 0;
|
|
|
|
|
if (s >= _sorted.items())
|
|
|
|
|
s = _sorted.last();
|
|
|
|
|
|
|
|
|
|
_selected = s;
|
|
|
|
|
const TMenuitem& mi = (const TMenuitem&)_sorted[_selected];
|
|
|
|
|
if (!mi.enabled())
|
|
|
|
|
{
|
|
|
|
|
for (_selected += direction; ; _selected += direction)
|
|
|
|
|
{
|
|
|
|
|
if (_selected < 0)
|
|
|
|
|
_selected = _sorted.last();
|
|
|
|
|
if (_selected >= _sorted.items())
|
|
|
|
|
_selected = 0;
|
|
|
|
|
if (_selected == s) // Ho rifatto l'intero giro!
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
const TMenuitem& item = (const TMenuitem&)_sorted[_selected];
|
|
|
|
|
if (item.enabled())
|
|
|
|
|
break; // Ho trovato un elemento abilitato!
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
draw_item(old_selection);
|
|
|
|
|
draw_item(_selected);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool TMenulist_window::on_key(KEY k)
|
|
|
|
|
{
|
|
|
|
|
switch (k)
|
|
|
|
|
{
|
|
|
|
|
case K_ESC:
|
|
|
|
|
case K_BACKSPACE:
|
|
|
|
|
if (_tree != NULL && _can_go_back) // S<> di un livello
|
|
|
|
|
click_on(0);
|
|
|
|
|
break;
|
|
|
|
|
case K_ENTER:
|
|
|
|
|
case K_SPACE:
|
|
|
|
|
click_on(_selected);
|
|
|
|
|
break;
|
|
|
|
|
case K_HOME:
|
|
|
|
|
select(0, +1);
|
|
|
|
|
break;
|
|
|
|
|
case K_UP:
|
|
|
|
|
case K_PREV:
|
|
|
|
|
select(_selected - MENU_COLS, -1);
|
|
|
|
|
break;
|
|
|
|
|
case K_DOWN:
|
|
|
|
|
case K_NEXT:
|
|
|
|
|
select(_selected + MENU_COLS, +1);
|
|
|
|
|
break;
|
|
|
|
|
case K_LEFT:
|
2003-05-16 13:10:09 +00:00
|
|
|
|
case K_BTAB:
|
2003-01-28 14:27:05 +00:00
|
|
|
|
select(_selected-1, -1);
|
|
|
|
|
break;
|
|
|
|
|
case K_RIGHT:
|
2003-05-16 13:10:09 +00:00
|
|
|
|
case K_TAB:
|
2003-01-28 14:27:05 +00:00
|
|
|
|
select(_selected+1, +1);
|
|
|
|
|
break;
|
|
|
|
|
case K_END:
|
|
|
|
|
select(_sorted.last(), -1);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TMenulist_window::synchronize_buddy_tree() const
|
|
|
|
|
{
|
|
|
|
|
TMask& m = owner().mask();
|
|
|
|
|
for (int i = 0; i < m.fields(); i++)
|
|
|
|
|
{
|
|
|
|
|
TMask_field& mf = m.fld(i);
|
|
|
|
|
if (mf.is_kind_of(CLASS_TREE_FIELD))
|
|
|
|
|
{
|
|
|
|
|
TTree_field& tf = (TTree_field&)mf;
|
|
|
|
|
synchronize_tree_field(tf);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-10-14 13:44:01 +00:00
|
|
|
|
void TMenulist_window::curr_item(TToken_string& id) const
|
|
|
|
|
{
|
|
|
|
|
if (_selected >= 0 && _selected < _sorted.items())
|
|
|
|
|
{
|
|
|
|
|
const TMenuitem& item = (const TMenuitem&)_sorted[_selected];
|
|
|
|
|
const TSubmenu& sm = item.submenu();
|
|
|
|
|
const int index = sm.find(item);
|
|
|
|
|
id = item.caption();
|
|
|
|
|
id.add(sm.name());
|
|
|
|
|
id << '.' << index;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-28 14:27:05 +00:00
|
|
|
|
void TMenulist_window::set_menu(TMenu_tree& tree)
|
|
|
|
|
{
|
|
|
|
|
_tree = &tree;
|
|
|
|
|
|
|
|
|
|
tree.curr_id(_curr_node);
|
|
|
|
|
const int dot = _curr_node.rfind('.')+1;
|
|
|
|
|
|
|
|
|
|
int sel = -1;
|
|
|
|
|
if (dot > 0)
|
|
|
|
|
{
|
|
|
|
|
sel = atoi(_curr_node.mid(dot));
|
|
|
|
|
_curr_node.overwrite("0", dot);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_sorted.destroy();
|
|
|
|
|
_can_go_back = tree.goto_father();
|
|
|
|
|
if (_can_go_back)
|
|
|
|
|
{
|
|
|
|
|
_sorted.add(tree.curr_item());
|
|
|
|
|
tree.goto_node(_curr_node);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int folders = _sorted.items();
|
|
|
|
|
|
|
|
|
|
// Lista riordinata dei menu items
|
|
|
|
|
const TSubmenu& mnu = tree.curr_submenu();
|
|
|
|
|
for (int i = 0; i < mnu.items(); i++)
|
|
|
|
|
{
|
|
|
|
|
const TMenuitem& item = mnu[i];
|
|
|
|
|
if (item.is_submenu())
|
|
|
|
|
_sorted.insert(item, folders++);
|
|
|
|
|
else
|
|
|
|
|
_sorted.add(item);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TString80 sel_act;
|
|
|
|
|
if (sel >= 0 && sel < mnu.items())
|
|
|
|
|
sel_act= mnu[sel].action();
|
|
|
|
|
|
|
|
|
|
for (_selected = _sorted.last(); _selected > 0; _selected--)
|
|
|
|
|
{
|
|
|
|
|
const TMenuitem& sm = (const TMenuitem&)_sorted[_selected];
|
|
|
|
|
if (sm.enabled() && sm.action() == sel_act)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_image_name = mnu.picture();
|
|
|
|
|
|
|
|
|
|
force_update();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TMenulist_window::TMenulist_window(int x, int y, int dx, int dy, WINDOW parent, TMenulist_field* owner)
|
2004-04-22 11:15:05 +00:00
|
|
|
|
: TField_window(x, y, dx, dy, parent, owner), _tree(NULL), MENU_COLS(4), MENU_ROWS(5)
|
2003-01-28 14:27:05 +00:00
|
|
|
|
{
|
|
|
|
|
set_scroll_max(0, 0); // Get rid of that useless scrollbars
|
2004-04-22 11:15:05 +00:00
|
|
|
|
|
|
|
|
|
RCT rct; xvt_vobj_get_client_rect(win(), &rct);
|
|
|
|
|
const size_t rh = 32 + 3 * CHARY;
|
|
|
|
|
const size_t mr = rct.bottom / rh;
|
|
|
|
|
if (mr > MENU_ROWS)
|
|
|
|
|
MENU_ROWS = mr;
|
|
|
|
|
|
|
|
|
|
int ms = rct.bottom - 3 * rh;
|
|
|
|
|
_images.set_owner_info(win(), ms);
|
2003-01-28 14:27:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TMenulist_window::~TMenulist_window()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TField_window* TMenulist_field::create_window(int x, int y, int dx, int dy, WINDOW parent)
|
|
|
|
|
{
|
|
|
|
|
return new TMenulist_window(x, y, dx, dy, parent, this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TMenulist_field::create(short dlg, int x, int y, int dx, int dy)
|
|
|
|
|
{
|
|
|
|
|
_dlg = dlg;
|
|
|
|
|
_win = create_window(x, y, dx, dy, mask().win());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TMenulist_field::set_menu(TMenu_tree& mt)
|
|
|
|
|
{
|
|
|
|
|
TMenulist_window& w = (TMenulist_window&)win();
|
|
|
|
|
w.set_menu(mt);
|
|
|
|
|
}
|
2003-10-14 13:44:01 +00:00
|
|
|
|
|
|
|
|
|
void TMenulist_field::curr_item(TToken_string& id) const
|
|
|
|
|
{
|
|
|
|
|
TMenulist_window& w = (TMenulist_window&)win();
|
|
|
|
|
w.curr_item(id);
|
|
|
|
|
}
|