element.cpp

Go to the documentation of this file.
00001 /*
00002  * element.cpp
00003  *
00004  * Copyright (C) 2008-2009  Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the <organization> nor the
00016  *       names of its contributors may be used to endorse or promote products
00017  *       derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY
00020  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY
00023  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  *
00031  * Central parsing and registry for dialog elements.
00032  */
00033 
00034 // includes --------------------------------------------------------------------
00035 #include "element.h"            // always include our own header first!
00036 #include "dialog.h"
00037 
00038 #include "common/wave_ex.h"
00039 
00040 #include "datahash/datahash_util.h"
00041 
00042 #include "perf/perf.h"
00043 
00044 
00045 namespace dialog {
00046 
00047 
00048 Factory::~Factory(void) throw() { }
00049 
00050 // Element base class implementation
00051 Element::~Element(void) throw() { }
00052 
00053 
00054 const char *
00055 Element::keyboard
00056 (
00057 IN int key,
00058 IN int mods
00059 )
00060 {
00061         // nothing to do!
00062         return NULL;
00063 }
00064 
00065 
00066 
00067 Element *
00068 Element::getFocus
00069 (
00070 IN const point_t& pos
00071 )
00072 {
00073         return NULL;    // no one gets focus
00074 }
00075 
00076 
00077 
00078 void
00079 Element::notifyFocus
00080 (
00081 IN bool haveFocus
00082 )
00083 {
00084 }
00085 
00086 
00087 
00088 void
00089 Element::addData
00090 (
00091 IN crypto::DESKey * key,
00092 IN Datahash * data
00093 )
00094 {
00095         // nothing to do
00096 }
00097 
00098 
00099 
00100 typedef smart_ptr<Element> (*construct_fn_t)(IN Manager * mgr,
00101                                 IN const Datahash * hash);
00102 
00103 
00104 struct type_entry_t {
00105         const char *            name;           // type name
00106         construct_fn_t          fn;             // constructor
00107 };
00108 
00109 
00110 #define DECLARE_FN( type )                                              \
00111         smart_ptr<Element> create ## type ## Element (                  \
00112                 IN Manager * mgr,                                       \
00113                 IN const Datahash * hash );
00114 
00115 DECLARE_FN(Button)
00116 DECLARE_FN(Container)
00117 DECLARE_FN(Label)
00118 DECLARE_FN(Textbox)
00119 
00120 
00121 
00122 static const type_entry_t entries[] = {
00123 
00124         { "button",             createButtonElement },
00125         { "container",          createContainerElement },
00126         { "label",              createLabelElement },
00127         { "textbox",            createTextboxElement },
00128 
00129         // must be last
00130         { NULL, NULL }
00131 };
00132 
00133 
00134 ////////////////////////////////////////////////////////////////////////////////
00135 //
00136 //      static helper methods
00137 //
00138 ////////////////////////////////////////////////////////////////////////////////
00139 
00140 static construct_fn_t
00141 getFn
00142 (
00143 IN const char * type_name
00144 )
00145 {
00146         ASSERT(type_name, "null");
00147 
00148         for (const type_entry_t * p = entries; p->name; ++p) {
00149                 if (!strcmp(p->name, type_name)) {
00150                         return p->fn;
00151                 }
00152         }
00153 
00154         // not found!
00155         return NULL;
00156 }
00157 
00158 
00159 
00160 ////////////////////////////////////////////////////////////////////////////////
00161 //
00162 //      DFactory -- default dialog::Factory object
00163 //
00164 ////////////////////////////////////////////////////////////////////////////////
00165 
00166 class DFactory : public Factory {
00167 public:
00168         // constructor, destructor ---------------------------------------------
00169         ~DFactory(void) throw() { }
00170 
00171         // public class methods ------------------------------------------------
00172         void initialize(void) throw() { }
00173 
00174         // dialog::Factory class interface methods -----------------------------
00175         smart_ptr<Element> createElement(IN const char * type,
00176                                 IN Manager * mgr,
00177                                 IN const Datahash * data);
00178 private:
00179 };
00180 
00181 
00182 
00183 smart_ptr<Element>
00184 DFactory::createElement
00185 (
00186 IN const char * type,
00187 IN Manager * mgr,
00188 IN const Datahash * data
00189 )
00190 {
00191         ASSERT(type, "null");
00192         ASSERT(mgr, "null");
00193         ASSERT(data, "null");
00194 
00195         // see if we've got this registered in our table of base objects
00196         construct_fn_t fn = getFn(type);
00197         ASSERT_THROW(fn, "No default construction function for element type: "
00198             << type);
00199         return fn(mgr, data);
00200 }
00201 
00202 
00203 
00204 ////////////////////////////////////////////////////////////////////////////////
00205 //
00206 //      public API
00207 //
00208 ////////////////////////////////////////////////////////////////////////////////
00209 
00210 smart_ptr<Element>
00211 constructElementTree
00212 (
00213 IN Manager * mgr,
00214 IN const Datahash * hash
00215 )
00216 {
00217         perf::Timer timer("constructElementTree");
00218         ASSERT(mgr, "null");
00219         ASSERT(hash, "null");
00220 
00221         // DPRINTF("In constructElementTree()...");
00222 
00223         // Get the type, and its registered constructor
00224         const char * type = getString(hash, "type");
00225         // DPRINTF("Constructing element of type '%s'", type);
00226         Factory * factory = mgr->getFactory(type);
00227         ASSERT_THROW(factory,
00228             "No factory registered for dialog element of type '" <<
00229             type << "'");
00230 
00231         return factory->createElement(type, mgr, hash);
00232 }
00233 
00234 
00235 
00236 smart_ptr<Factory>
00237 getDefaultFactory
00238 (
00239 void
00240 )
00241 {
00242         smart_ptr<DFactory> local = new DFactory;
00243         ASSERT(local, "out of memory");
00244 
00245         local->initialize();
00246 
00247         return local;
00248 }
00249 
00250 
00251 
00252 void
00253 registerDefaultFactories
00254 (
00255 IN Manager * mgr
00256 )
00257 {
00258         ASSERT(mgr, "null");
00259 
00260         smart_ptr<Factory> factory = getDefaultFactory();
00261         ASSERT(factory, "null");
00262 
00263         for (const type_entry_t * p = entries; p->name; ++p) {
00264                 mgr->registerFactory(p->name, factory);
00265         }
00266 }
00267 
00268 
00269 
00270 };      // dialog namespace
00271