Panda3D
 All Classes Functions Variables Enumerations
buttonRegistry.cxx
00001 // Filename: buttonRegistry.cxx
00002 // Created by:  drose (01Mar00)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "buttonRegistry.h"
00016 #include "config_util.h"
00017 
00018 #include <stdio.h>
00019 
00020 // In general, we use the util_cat->info() syntax in this file
00021 // (instead of util_cat.info()), because much of this work is done at
00022 // static init time, and we must use the arrow syntax to force
00023 // initialization of the util_cat category.
00024 
00025 ButtonRegistry *ButtonRegistry::_global_pointer = NULL;
00026 
00027 
00028 ////////////////////////////////////////////////////////////////////
00029 //     Function: ButtonRegistry::register_button
00030 //       Access: Public
00031 //  Description: Registers a new ButtonHandle with the indicated name,
00032 //               and if specified, the indicated ASCII equivalent.
00033 //               Returns true if the button was registered, or false
00034 //               it was already registered; in either case, the new
00035 //               ButtonHandle is loaded into the first parameter.
00036 //
00037 //               If the alias is not ButtonHandle::none(), it
00038 //               indicates an alias (alternate name) for the same
00039 //               button.  Each button is allowed to have one alias,
00040 //               and multiple different buttons can refer to the same
00041 //               alias.  The alias should be the more general name for
00042 //               the button, for instance, shift is an alias for
00043 //               lshift, but not vice-versa.
00044 //
00045 //               This defines a new kind of button matching the
00046 //               indicated name.  The ButtonHandle can then be passed
00047 //               around to devices as a button in its own right.
00048 ////////////////////////////////////////////////////////////////////
00049 bool ButtonRegistry::
00050 register_button(ButtonHandle &button_handle, const string &name,
00051                 ButtonHandle alias, char ascii_equivalent) {
00052   NameRegistry::iterator ri;
00053   ri = _name_registry.find(name);
00054 
00055   if (ri == _name_registry.end()) {
00056     // The name was not already used; this is the first time this
00057     // button has been defined.
00058 
00059     int index = -1;
00060     if (ascii_equivalent != '\0') {
00061       if (_handle_registry[ascii_equivalent] == (RegistryNode *)NULL) {
00062         index = ascii_equivalent;
00063       } else {
00064         util_cat->error()
00065           << "Attempt to register multiple buttons under ASCII equivalent "
00066           << ascii_equivalent << "\n";
00067       }
00068     }
00069 
00070 #ifdef NOTIFY_DEBUG
00071     // This code runs at static init time, so cannot use the
00072     // util_cat.is_spam() syntax.
00073     if (util_cat->is_spam()) {
00074       util_cat->spam()
00075         << "Registering button " << name << "\n";
00076     }
00077 #endif
00078 
00079     if (index == -1) {
00080       // It's not an ASCII equivalent; make up a new number.
00081       index = _handle_registry.size();
00082       _handle_registry.push_back(NULL);
00083     }
00084 
00085     ButtonHandle new_handle;
00086     new_handle._index = index;
00087 
00088     RegistryNode *rnode = new RegistryNode(new_handle, alias, name);
00089     _handle_registry[index] = rnode;
00090     _name_registry[name] = rnode;
00091 
00092     button_handle = new_handle;
00093     return true;
00094   }
00095 
00096   RegistryNode *rnode = (*ri).second;
00097   nassertr(rnode->_name == (*ri).first, false);
00098   nassertr(rnode->_handle._index >= 0 &&
00099            rnode->_handle._index < (int)_handle_registry.size(), false);
00100   nassertr(_handle_registry[rnode->_handle._index] == rnode, false);
00101   nassertr(rnode->_handle._index != 0, false);
00102 
00103   if (button_handle != rnode->_handle) {
00104     // Hmm, we seem to have a contradictory button registration!
00105     util_cat->warning()
00106       << "Attempt to register button " << name << " more than once!\n";
00107 
00108     button_handle = rnode->_handle;
00109   }
00110   return false;
00111 }
00112 
00113 ////////////////////////////////////////////////////////////////////
00114 //     Function: ButtonRegistry::get_button
00115 //       Access: Published
00116 //  Description: Finds a ButtonHandle in the registry matching the
00117 //               indicated name.  If there is no such ButtonHandle,
00118 //               registers a new one and returns it.
00119 ////////////////////////////////////////////////////////////////////
00120 ButtonHandle ButtonRegistry::
00121 get_button(const string &name) {
00122   NameRegistry::const_iterator ri;
00123   ri = _name_registry.find(name);
00124 
00125   if (ri != _name_registry.end()) {
00126     return (*ri).second->_handle;
00127   }
00128 
00129   ButtonHandle button;
00130   register_button(button, name);
00131   return button;
00132 }
00133 
00134 ////////////////////////////////////////////////////////////////////
00135 //     Function: ButtonRegistry::find_ascii_button
00136 //       Access: Published
00137 //  Description: Finds a ButtonHandle in the registry matching the
00138 //               indicated ASCII equivalent character.  If there is no
00139 //               such ButtonHandle, returns ButtonHandle::none().
00140 ////////////////////////////////////////////////////////////////////
00141 ButtonHandle ButtonRegistry::
00142 find_ascii_button(char ascii_equivalent) const {
00143   if (_handle_registry[ascii_equivalent] == (RegistryNode *)NULL) {
00144     return ButtonHandle::none();
00145   }
00146   return _handle_registry[ascii_equivalent]->_handle;
00147 }
00148 
00149 ////////////////////////////////////////////////////////////////////
00150 //     Function: ButtonRegistry::write
00151 //       Access: Published
00152 //  Description:
00153 ////////////////////////////////////////////////////////////////////
00154 void ButtonRegistry::
00155 write(ostream &out) const {
00156   out << "ASCII equivalents:\n";
00157   for (int i = 1; i < 128; i++) {
00158     if (_handle_registry[i] != (RegistryNode *)NULL) {
00159       char hex[12];
00160       sprintf(hex, "%02x", (unsigned int)i);
00161       nassertv(strlen(hex) < 12);
00162 
00163       out << "  " << hex << " " << _handle_registry[i]->_name << "\n";
00164     }
00165   }
00166 
00167   out << "\nOther buttons:\n";
00168   NameRegistry::const_iterator ri;
00169   for (ri = _name_registry.begin(); ri != _name_registry.end(); ++ri) {
00170     if (!(*ri).second->_handle.has_ascii_equivalent()) {
00171       out << "  " << (*ri).second->_name;
00172       if ((*ri).second->_alias != ButtonHandle::none()) {
00173         out << " (alias " << (*ri).second->_alias << ")";
00174       }
00175       out << "\n";
00176     }
00177   }
00178 }
00179 
00180 
00181 ////////////////////////////////////////////////////////////////////
00182 //     Function: ButtonRegistry::Constructor
00183 //       Access: Private
00184 //  Description:
00185 ////////////////////////////////////////////////////////////////////
00186 ButtonRegistry::
00187 ButtonRegistry() {
00188   // We'll start by filling up the handle_registry with 128 entries
00189   // for ButtonHandle::none(), as well as for all the ASCII
00190   // equivalents.
00191 
00192   _handle_registry.reserve(128);
00193   int i;
00194   for (i = 0; i < 128; i++) {
00195     _handle_registry.push_back(NULL);
00196   }
00197 }
00198 
00199 ////////////////////////////////////////////////////////////////////
00200 //     Function: ButtonRegistry::init_global_pointer
00201 //       Access: Private, Static
00202 //  Description: Constructs the ButtonRegistry object for the first
00203 //               time.
00204 ////////////////////////////////////////////////////////////////////
00205 void ButtonRegistry::
00206 init_global_pointer() {
00207   _global_pointer = new ButtonRegistry;
00208 }
00209 
00210 
00211 ////////////////////////////////////////////////////////////////////
00212 //     Function: ButtonRegistry::look_up
00213 //       Access: Private
00214 //  Description:
00215 ////////////////////////////////////////////////////////////////////
00216 ButtonRegistry::RegistryNode *ButtonRegistry::
00217 look_up(ButtonHandle handle) const {
00218   nassertr(handle._index != 0, NULL);
00219 
00220   if (handle._index < 0 ||
00221       handle._index >= (int)_handle_registry.size()) {
00222     util_cat->fatal()
00223       << "Invalid ButtonHandle index " << handle._index
00224       << "!  Is memory corrupt?\n";
00225     return (RegistryNode *)NULL;
00226   }
00227 
00228   return _handle_registry[handle._index];
00229 }
 All Classes Functions Variables Enumerations