Files correlati : ba0 ba1 Ricompilazione Demo : [ ] Commento : Aggiunto supporto per scadenza password e nomi utenti lunghi (16 caratteri invece di solo 8) git-svn-id: svn://10.65.10.50/trunk@15170 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			911 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			911 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
#include <controls.h>
 | 
						||
#include <mask.h>
 | 
						||
#include <statbar.h>
 | 
						||
#include <urldefid.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;
 | 
						||
  TAssoc_array* _ignore_list;
 | 
						||
};
 | 
						||
 | 
						||
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();
 | 
						||
 | 
						||
    if (sm.disabled())
 | 
						||
      return FALSE;
 | 
						||
 | 
						||
    TFind_string_data& data = *(TFind_string_data*)jolly;
 | 
						||
    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();
 | 
						||
}
 | 
						||
 | 
						||
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;
 | 
						||
}
 | 
						||
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
// TMenulist_field
 | 
						||
///////////////////////////////////////////////////////////
 | 
						||
 | 
						||
class TMenulist_images : public TCache
 | 
						||
{
 | 
						||
  WINDOW _win;
 | 
						||
  int _max_side;
 | 
						||
 | 
						||
protected:
 | 
						||
	TObject* key2obj(const char* key);
 | 
						||
 | 
						||
public:
 | 
						||
	void set_owner_info(WINDOW win, int max_side);
 | 
						||
	TImage* image(const char* filename);
 | 
						||
	TMenulist_images() : TCache(17), _win(NULL_WIN), _max_side(0) { }
 | 
						||
};
 | 
						||
 | 
						||
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;
 | 
						||
}
 | 
						||
 | 
						||
void TMenulist_images::set_owner_info(WINDOW win, int max_side) 
 | 
						||
{ 
 | 
						||
  _win = win; 
 | 
						||
  _max_side = max_side;
 | 
						||
}
 | 
						||
 | 
						||
TObject* TMenulist_images::key2obj(const char* key)
 | 
						||
{
 | 
						||
  TImage*	img = NULL;
 | 
						||
 | 
						||
  TFilename name;
 | 
						||
  const char* ext[3] = { "jpg", "gif", "bmp" };
 | 
						||
  for (int i = 0; i < 3; i++)
 | 
						||
  {
 | 
						||
    name = key;
 | 
						||
    name << '.' << ext[i];
 | 
						||
    if (name.custom_path())
 | 
						||
      break;
 | 
						||
  }
 | 
						||
 | 
						||
  if (name.exist())
 | 
						||
	{
 | 
						||
		TWait_cursor hourglass;
 | 
						||
		TImage image(name);
 | 
						||
		if (can_be_transparent(image))
 | 
						||
			image.convert_transparent_color(NORMAL_BACK_COLOR);
 | 
						||
 | 
						||
	  RCT rct; xvt_vobj_get_client_rect(_win, &rct);
 | 
						||
    const double max_img = (double)_max_side;
 | 
						||
    const double max_lgo = rct.right - _max_side;
 | 
						||
 | 
						||
    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);
 | 
						||
 | 
						||
     //Sfumatura costante sui lati sx e up
 | 
						||
      const double radius = min(maxx,maxy)/6.0;
 | 
						||
		  for (int y = 0; y < maxy; y++)
 | 
						||
		  {
 | 
						||
			  for (int x = 0; x < maxx; x++)
 | 
						||
			  {
 | 
						||
          if (x <= radius || y <= radius)
 | 
						||
          {
 | 
						||
            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;
 | 
						||
 | 
						||
				    COLOR col = img->get_pixel(x, y);
 | 
						||
				    COLOR bri = blend_colors(col, NORMAL_BACK_COLOR, perc);
 | 
						||
				    img->set_pixel(x, y, bri);
 | 
						||
          }
 | 
						||
        }
 | 
						||
		  }
 | 
						||
    }
 | 
						||
    else    //caso particolare del logo
 | 
						||
    {
 | 
						||
		  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);
 | 
						||
    }
 | 
						||
	}
 | 
						||
	return img;
 | 
						||
}
 | 
						||
 | 
						||
TImage* TMenulist_images::image(const char* name)
 | 
						||
{
 | 
						||
	TObject* obj = objptr(name);
 | 
						||
  if (obj == NULL && 
 | 
						||
      xvt_str_compare_ignoring_case(name, "ba00") != 0 &&
 | 
						||
      xvt_str_compare_ignoring_case(name, "logo") != 0)
 | 
						||
    obj = objptr("ba00");
 | 
						||
	return (TImage*)obj;
 | 
						||
}
 | 
						||
 | 
						||
class TMenulist_window : public TField_window
 | 
						||
{
 | 
						||
private:
 | 
						||
  TMenu_tree* _tree;
 | 
						||
	size_t MENU_COLS, MENU_ROWS;
 | 
						||
 | 
						||
	TString _curr_node;
 | 
						||
	bool _can_go_back;
 | 
						||
 | 
						||
	TMenulist_images _images;
 | 
						||
	TString _image_name;
 | 
						||
 | 
						||
	int _selected;
 | 
						||
	TPointer_array _sorted;
 | 
						||
 | 
						||
  clock_t _last_update;
 | 
						||
 | 
						||
protected:
 | 
						||
	virtual void update();
 | 
						||
	virtual void handler(WINDOW win, EVENT* ep);
 | 
						||
  virtual bool on_key(KEY k);
 | 
						||
  virtual void on_idle();
 | 
						||
 | 
						||
	void synchronize_buddy_tree() const;
 | 
						||
  void draw_item(int i);
 | 
						||
  void draw_menu_caption(COLOR rgb);
 | 
						||
  void click_on(int index);
 | 
						||
  void select(int s, int direction);
 | 
						||
 | 
						||
public:
 | 
						||
  void curr_item(TToken_string& id) const;
 | 
						||
	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;
 | 
						||
	
 | 
						||
	xvtil_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())
 | 
						||
  {
 | 
						||
  //testo nero su sfondo con colore del focus se la voce e' selezionata
 | 
						||
		set_color(item.color(), FOCUS_BACK_COLOR);
 | 
						||
  }
 | 
						||
	else
 | 
						||
	{
 | 
						||
    set_color(item.color(), NORMAL_BACK_COLOR); //testo nero su sfondo trasparente x voci non selezionate
 | 
						||
	}
 | 
						||
 | 
						||
	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;
 | 
						||
//	const int bottom = (row+1) * height / MENU_ROWS;
 | 
						||
	
 | 
						||
	const int maxchars = (right-left)/CHARX - 1;
 | 
						||
	const int cx = (left+right)/2;
 | 
						||
//	const int cy = (top+bottom)/2; verificare
 | 
						||
 | 
						||
	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);
 | 
						||
  }
 | 
						||
 | 
						||
  TString80 str = item.caption();
 | 
						||
  if (i == 0 && _can_go_back)
 | 
						||
		str = "(..)";
 | 
						||
 | 
						||
	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
 | 
						||
}
 | 
						||
 | 
						||
//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) 
 | 
						||
      y -= logo->height() + ROWY; //+ROWY per staccare scritta dal logo
 | 
						||
  }
 | 
						||
  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);
 | 
						||
  xvt_font_set_size(font_menu, 130 * size / 100); //altezza font il 30% maggiore di quello di menu
 | 
						||
 | 
						||
  xvt_dwin_set_font(win(), font_menu);
 | 
						||
  set_color(rgb, NORMAL_BACK_COLOR);
 | 
						||
  xvt_dwin_draw_text(win(), x, y, caption, -1);
 | 
						||
 | 
						||
  xvt_font_destroy(font_menu);
 | 
						||
 | 
						||
  statbar_set_title(TASK_WIN, caption);
 | 
						||
}
 | 
						||
 | 
						||
void TMenulist_window::update()
 | 
						||
{ 
 | 
						||
  const bool db = _tree != NULL && ADVANCED_GRAPHICS;
 | 
						||
  TImage* img = db ? _images.image(_image_name) : NULL; // Delay time before clearing
 | 
						||
 | 
						||
  TField_window::update();
 | 
						||
  if (_tree == NULL)
 | 
						||
		return; // Nothing to draw
 | 
						||
 | 
						||
	if (img != NULL)
 | 
						||
	{
 | 
						||
		RCT rct; xvt_vobj_get_client_rect(win(), &rct);
 | 
						||
    const int x = (rct.right - img->width());
 | 
						||
    const int y = (rct.bottom - img->height());
 | 
						||
		img->draw(win(), x, y);
 | 
						||
  }
 | 
						||
 | 
						||
  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);
 | 
						||
  }
 | 
						||
 | 
						||
	for (int i = 0; i < _sorted.items(); i++)
 | 
						||
		draw_item(i);
 | 
						||
 | 
						||
  if (ADVANCED_GRAPHICS)
 | 
						||
    _last_update = clock();
 | 
						||
  else
 | 
						||
    draw_menu_caption(NORMAL_COLOR);
 | 
						||
}
 | 
						||
 | 
						||
void TMenulist_window::on_idle()
 | 
						||
{
 | 
						||
  if (ADVANCED_GRAPHICS)
 | 
						||
  {
 | 
						||
#ifdef LINUX
 | 
						||
    const clock_t max_clock = (3*CLOCKS_PER_SEC) / 10;
 | 
						||
#else
 | 
						||
    const clock_t max_clock = 3*CLOCKS_PER_SEC;
 | 
						||
#endif
 | 
						||
    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);
 | 
						||
    }
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
void TMenulist_window::click_on(int index)
 | 
						||
{
 | 
						||
	if (index >= 0 && index < _sorted.items())
 | 
						||
	{
 | 
						||
    const TMenuitem& mi = (const TMenuitem&)_sorted[index];
 | 
						||
		if (mi.enabled())
 | 
						||
		{
 | 
						||
      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);
 | 
						||
      }
 | 
						||
			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();
 | 
						||
		}
 | 
						||
    else
 | 
						||
      xvt_sys_beep(1);
 | 
						||
	}
 | 
						||
}
 | 
						||
 | 
						||
void TMenulist_window::handler(WINDOW w, EVENT* ep)
 | 
						||
{
 | 
						||
  switch (ep->type)
 | 
						||
	{
 | 
						||
  case E_MOUSE_DOWN:
 | 
						||
		{
 | 
						||
  		RCT rct; xvt_vobj_get_client_rect(w, &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;
 | 
						||
			const int index = row * MENU_COLS + col;
 | 
						||
			if (ep->v.mouse.button > 0) // Tasto destro
 | 
						||
			{
 | 
						||
        if (index < _sorted.items())
 | 
						||
        {
 | 
						||
          const TMenuitem& mi = (const TMenuitem&)_sorted[index];
 | 
						||
          message_box(mi.action());
 | 
						||
        }
 | 
						||
        else
 | 
						||
        {
 | 
						||
          if (_can_go_back)
 | 
						||
            click_on(0);
 | 
						||
        }
 | 
						||
			}
 | 
						||
			else
 | 
						||
			{
 | 
						||
  			click_on(index); // Tasto sinistro
 | 
						||
			}
 | 
						||
    }
 | 
						||
		break;
 | 
						||
  case E_MOUSE_MOVE:
 | 
						||
    if (ADVANCED_GRAPHICS)
 | 
						||
    {
 | 
						||
      EVENT e = *ep;
 | 
						||
      xvt_vobj_translate_points(w, parent(), &e.v.mouse.where, 1);
 | 
						||
      xvt_win_dispatch_event(parent(), &e);
 | 
						||
    }
 | 
						||
    break;
 | 
						||
	default: 
 | 
						||
		break;
 | 
						||
	}
 | 
						||
 | 
						||
	TField_window::handler(w, 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:
 | 
						||
  case K_BTAB:
 | 
						||
		select(_selected-1, -1);
 | 
						||
		break;
 | 
						||
  case K_RIGHT:
 | 
						||
  case K_TAB:
 | 
						||
		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_EACH_MASK_FIELD(m, i, f) 
 | 
						||
	{
 | 
						||
    if (f->is_kind_of(CLASS_TREE_FIELD))
 | 
						||
    {
 | 
						||
			TTree_field& tf = (TTree_field&)*f;
 | 
						||
      synchronize_tree_field(tf);
 | 
						||
			break;
 | 
						||
		}
 | 
						||
	}
 | 
						||
}
 | 
						||
 | 
						||
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;
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
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)
 | 
						||
                : TField_window(x, y, dx, dy, parent, owner), _tree(NULL), MENU_COLS(4), MENU_ROWS(5)
 | 
						||
{
 | 
						||
	set_scroll_max(0, 0);  // Get rid of that useless scrollbars
 | 
						||
 | 
						||
	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);
 | 
						||
}
 | 
						||
 | 
						||
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);
 | 
						||
}
 | 
						||
 | 
						||
void TMenulist_field::curr_item(TToken_string& id) const
 | 
						||
{
 | 
						||
  TMenulist_window& w = (TMenulist_window&)win();
 | 
						||
  w.curr_item(id);
 | 
						||
}
 |