core/vgui/vgui_menu.cxx
Go to the documentation of this file.
00001 // This is core/vgui/vgui_menu.cxx
00002 #include "vgui_menu.h"
00003 //:
00004 // \file
00005 // \author fsm
00006 // \brief  See vgui_menu.h for a description of this file.
00007 
00008 #include <vcl_iostream.h>
00009 #include <vgui/vgui_command.h>
00010 
00011 //--------------------------------------------------------------------------------
00012 
00013 vgui_menu_item::vgui_menu_item()
00014   : name("[]")
00015   , menu(0)
00016 {
00017   short_cut.mod = vgui_MODIFIER_NULL;
00018   short_cut.key = vgui_KEY_NULL;
00019 }
00020 
00021 vgui_menu_item::vgui_menu_item(vgui_menu_item const &that)
00022   : name(that.name)
00023   , cmnd(that.cmnd)
00024   , menu(that.menu)
00025   , short_cut(that.short_cut)
00026 {
00027   if (menu)
00028     menu = new vgui_menu( *menu ); // make a copy.
00029 }
00030 
00031 vgui_menu_item::~vgui_menu_item()
00032 {
00033   if (menu)
00034     delete menu;
00035   menu = 0;
00036 }
00037 
00038 bool vgui_menu_item::is_toggle_button() const
00039 {
00040   // The use of dynamic_cast is forbidden by the VXL
00041   // guidelines. However, the alternative here is to implement our own
00042   // RTTI in vgui_command using a virtual function like
00043   // is_a_toggle_command. However, this is GUI code. It's not
00044   // performance critical, and mostly requires RTTI and threads and
00045   // all kinds of things. Let's just use the compiler generated
00046   // version until we run into a real problem.
00047   //
00048   return name!="" &&  (bool)cmnd && (menu == 0) &&  dynamic_cast<vgui_command_toggle*>(cmnd.ptr()) != 0;
00049 }
00050 
00051 //--------------------------------------------------------------------------------
00052 
00053 vgui_menu::vgui_menu(vgui_menu const &that)
00054 {
00055   operator=(that);
00056 }
00057 
00058 vgui_menu& vgui_menu::operator=(vgui_menu const &that)
00059 {
00060   if (this != &that) {
00061     clear();
00062     this->include(that);
00063   }
00064   return *this;
00065 }
00066 
00067 //--------------------------------------------------------------------------------
00068 
00069 #define im_here do { /* vcl_cerr << __FILE__ " : " << __LINE__ << vcl_endl; */ } while (false)
00070 
00071 void vgui_menu::add(vcl_string const &n,
00072                     vgui_command_sptr c,
00073                     vgui_key key,
00074                     vgui_modifier modifiers)
00075 {
00076   im_here;
00077   vgui_menu_item i;
00078   i.name = n;
00079   i.cmnd = c;
00080   i.short_cut.key = key;
00081   i.short_cut.mod = modifiers;
00082   items.push_back(i);
00083 }
00084 
00085 void vgui_menu::add(vcl_string const &n,
00086                     vgui_menu_callback f,
00087                     void const* client_data,
00088                     vgui_key key,
00089                     vgui_modifier modifiers)
00090 {
00091   im_here;
00092   vgui_command* cfunc = new vgui_command_cfunc(f, client_data); //KYM fix for SunPro
00093   add(n, /* (vgui_command*) */cfunc, key, modifiers);
00094 }
00095 
00096 void vgui_menu::add(vcl_string const &n,
00097                     vgui_menu_callback_no_client_data f,
00098                     vgui_key key,
00099                     vgui_modifier modifiers)
00100 {
00101   im_here;
00102   vgui_command* cfunc = new vgui_command_cfunc(f);  //KYM fix for SunPro
00103   add(n, /* (vgui_command*) */cfunc, key, modifiers);
00104 }
00105 
00106 void vgui_menu::add(vcl_string const &n,
00107                     vgui_menu const &m,
00108                     vgui_key key,
00109                     vgui_modifier modifiers)
00110 {
00111   im_here;
00112   vgui_menu_item i;
00113   i.name = n;
00114   i.menu = new vgui_menu(m);
00115   i.short_cut.key = key;
00116   i.short_cut.mod = modifiers;
00117   items.push_back(i);
00118 }
00119 
00120 void vgui_menu::separator()
00121 {
00122   vgui_menu_item i;
00123   i.name = "";
00124   items.push_back(i);
00125 }
00126 
00127 void vgui_menu::include(vgui_menu const &that)
00128 {
00129   items.reserve(items.size() + that.items.size());
00130 
00131   for (unsigned i=0; i<that.size(); ++i)
00132     items.push_back( that.items[i] );
00133 }
00134 
00135 //--------------------------------------------------------------------------------
00136 
00137 // Helper function for operator<<. Apart from the menu to print and the
00138 // destination stream, the 'pre' argument is the prefix to print on every
00139 // new line (usually spaces for indentation).
00140 // This could be a member function, but that would just clutter
00141 // the interface even more.
00142 static void dump(vgui_menu const &This, vcl_ostream &os, vcl_string const &pre)
00143 {
00144   for (unsigned i=0;i<This.size();i++) {
00145     // name
00146     os << pre << " \"" << This[i].name << "\" ";
00147 
00148     // shortcut
00149     if (This[i].short_cut.mod & vgui_CTRL)
00150       os << "CTRL+";
00151     if (This[i].short_cut.mod & vgui_SHIFT)
00152       os << "SHIFT+";
00153     if (This[i].short_cut.mod & vgui_META)
00154       os << "META+";
00155     if (This[i].short_cut.mod & vgui_ALT)
00156       os << "ALT+";
00157     if (This[i].short_cut.key)
00158       os << '\'' << char(This[i].short_cut.key) << '\'';
00159     else
00160       os << "\'\'"; //"(none)";
00161     os << ' ';
00162 
00163     // what it does
00164     if (This[i].is_command())
00165       os << "command(" << static_cast<void*>(This[i].cmnd.as_pointer()) << ")\n";
00166     else if (This[i].is_submenu()) {
00167       os << "submenu:\n";
00168       dump(* This[i].menu,os,pre+"  ");
00169     }
00170     else if (This[i].is_toggle_button()) {
00171       vgui_command_toggle *c = static_cast<vgui_command_toggle*>(This[i].cmnd.as_pointer());
00172       os << "toggle (" << (c->state ? "on" : "off") << ")\n";
00173     }
00174     else if (This[i].is_separator())
00175       os << "(----- separator -----)\n";
00176     else
00177       os << "[unknown menuitem]\n"; //
00178   }
00179 }
00180 
00181 vcl_ostream &operator<<(vcl_ostream &os, vgui_menu const &m)
00182 {
00183   dump(m, os, "  ");
00184   return os;
00185 }
00186 
00187 //--------------------------------------------------------------------------------