00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "dialog.h"
00036
00037 #include "container.h"
00038 #include "request.h"
00039
00040 #include "common/wave_ex.h"
00041 #include "datahash/datahash_text.h"
00042 #include "datahash/datahash_util.h"
00043 #include "perf/perf.h"
00044
00045
00046 namespace dialog {
00047
00048
00049
00050
00051
00052
00053 Manager::~Manager(void) throw() { }
00054
00055
00056 Host::~Host(void) throw() { }
00057
00058
00059 struct dialog_record_t {
00060 rect_t bounds;
00061 Host * host;
00062 smart_ptr<Element> root;
00063 };
00064
00065
00066 typedef std::map<std::string, dialog_record_t > dialog_map_t;
00067
00068
00069
00070
00071
00072
00073
00074
00075 smart_ptr<Datahash>
00076 ContainerRequest::getDatahash
00077 (
00078 void
00079 )
00080 {
00081 this->close();
00082 std::istringstream iss(this->get());
00083
00084 return readHashFromStream("dialog", iss);
00085 }
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 class Mgr : public Manager {
00096 public:
00097 ~Mgr(void) throw() { }
00098
00099
00100 void initialize(IN smart_ptr<crypto::DESKey>& desKey,
00101 IN smart_ptr<Drawer>& drawer);
00102
00103
00104 smart_ptr<Drawer> getDrawer(void) { return m_drawer; }
00105 void registerFactory(IN const char * type,
00106 IN smart_ptr<Factory>& factory);
00107 Factory * getFactory(IN const char * type);
00108 void display(IN int screen_w, IN int screen_h);
00109 void cursor(IN int x, IN int y);
00110 void button(IN int button, IN int state, IN int x, IN int y);
00111 void keyboard(IN int key, IN int mods);
00112 bool createDialog(IN const char * id,
00113 IN int x, IN int y,
00114 IN const Datahash * form,
00115 IN Host * host);
00116 bool doesDialogExist(IN const char * id);
00117 void destroyDialog(IN const char * id);
00118
00119 private:
00120
00121 typedef std::map<std::string, smart_ptr<Factory> > factory_map_t;
00122
00123
00124 dialog_record_t * getDialog(IN const char * id);
00125 void submit(IN const char * id, IN const char * result);
00126
00127
00128 factory_map_t m_factories;
00129 dialog_map_t m_dialogs;
00130 rect_t m_viewport;
00131 std::string m_cursorTag;
00132 bool m_cursorDown;
00133 std::string m_dragId;
00134 point_t m_dragStart;
00135 Element * m_focus;
00136 std::string m_focusId;
00137 smart_ptr<crypto::DESKey> m_desKey;
00138 smart_ptr<Drawer> m_drawer;
00139 };
00140
00141
00142
00143 void
00144 Mgr::initialize
00145 (
00146 IN smart_ptr<crypto::DESKey>& desKey,
00147 IN smart_ptr<Drawer>& drawer
00148 )
00149 {
00150
00151 m_desKey = desKey;
00152
00153 ASSERT(drawer, "null");
00154 ASSERT(!m_drawer, "already have a drawer?");
00155 m_drawer = drawer;
00156
00157
00158 m_cursorDown = false;
00159 m_cursorTag = "";
00160 m_dragId = "";
00161 m_focus = NULL;
00162
00163
00164 registerDefaultFactories(this);
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 void
00176 Mgr::registerFactory
00177 (
00178 IN const char * type,
00179 IN smart_ptr<Factory>& factory
00180 )
00181 {
00182 ASSERT(type, "null");
00183 ASSERT(factory, "null");
00184
00185
00186 m_factories[type] = factory;
00187 }
00188
00189
00190
00191 void
00192 Mgr::display
00193 (
00194 IN int screen_w,
00195 IN int screen_h
00196 )
00197 {
00198
00199 for (dialog_map_t::iterator i = m_dialogs.begin(); i != m_dialogs.end();
00200 ++i) {
00201 dialog_record_t& dr = i->second;
00202 ASSERT(dr.root, "null");
00203
00204
00205 int width = dr.bounds.right - dr.bounds.left;
00206 int height = dr.bounds.bottom - dr.bounds.top;
00207
00208
00209
00210
00211
00212 int minX = screen_w - width;
00213 if (minX > 0) {
00214 minX = 0;
00215 }
00216 int minY = screen_h - height;
00217 if (minY > 0) {
00218 minY = 0;
00219 }
00220
00221
00222 int dx, dy;
00223 dx = dy = 0;
00224 if (dr.bounds.left < minX) {
00225 dx = minX - dr.bounds.left;
00226 }
00227 if (dr.bounds.top < minY) {
00228 dy = minY - dr.bounds.top;
00229 }
00230 dr.bounds.shift(dx, dy);
00231
00232
00233 int maxX = screen_w - width;
00234 if (maxX < 0)
00235 maxX = 0;
00236 int maxY = screen_h - height;
00237 if (maxY < 0)
00238 maxY = 0;
00239 if (dr.bounds.left > maxX) {
00240 dx = maxX - dr.bounds.left;
00241 }
00242 if (dr.bounds.top > maxY) {
00243 dy = maxY - dr.bounds.top;
00244 }
00245 dr.bounds.shift(dx, dy);
00246
00247
00248 m_drawer->drawRectWithBorder(eElement_Dialog, dr.bounds);
00249
00250
00251 dr.root->draw(dr.bounds.getTopLeft());
00252 }
00253 }
00254
00255
00256
00257
00258 void
00259 Mgr::button
00260 (
00261 IN int button,
00262 IN int state,
00263 IN int x,
00264 IN int y
00265 )
00266 {
00267
00268
00269 if (button)
00270 return;
00271
00272 point_t pos(x, y);
00273
00274 const char * result = NULL;
00275 const char * id = NULL;
00276 for (dialog_map_t::iterator i = m_dialogs.begin(); i != m_dialogs.end();
00277 ++i) {
00278 dialog_record_t& dr = i->second;
00279 ASSERT(dr.root, "null");
00280
00281 if (!dr.bounds.contains(pos))
00282 continue;
00283
00284
00285 result = dr.root->button(button, state,
00286 pos - dr.bounds.getTopLeft());
00287 id = i->first.c_str();
00288
00289
00290 if (!state) {
00291 Element * focus =
00292 dr.root->getFocus(pos - dr.bounds.getTopLeft());
00293 DPRINTF("Focus: %p", m_focus);
00294 if (focus) {
00295 if (m_focus) {
00296 m_focus->notifyFocus(false);
00297 }
00298 m_focus = focus;
00299 m_focus->notifyFocus(true);
00300 m_focusId = id;
00301 }
00302 }
00303 }
00304
00305
00306 if (state) {
00307
00308 const char * oldTag = m_cursorTag.c_str();
00309 if (result && !strcmp(result, oldTag)) {
00310 DPRINTF("Cursor down + up on same element!");
00311 this->submit(id, result);
00312 }
00313
00314
00315 m_cursorTag = "";
00316 m_cursorDown = false;
00317 m_dragId = "";
00318 } else {
00319
00320 m_cursorTag = result ? result : "";
00321 m_cursorDown = true;
00322
00323
00324 if (!result && id) {
00325 m_dragId = id;
00326 m_dragStart.set(x, y);
00327 }
00328 }
00329
00330
00331
00332
00333
00334
00335 }
00336
00337
00338
00339 void
00340 Mgr::cursor
00341 (
00342 IN int x,
00343 IN int y
00344 )
00345 {
00346
00347 if (m_cursorDown && !m_dragId.empty()) {
00348
00349 point_t delta = point_t(x, y) - m_dragStart;
00350 m_dragStart.set(x, y);
00351
00352
00353 dialog_record_t * pdr = this->getDialog(m_dragId.c_str());
00354 if (!pdr) {
00355
00356 m_dragId = "";
00357 } else {
00358 pdr->bounds.shift(delta.x, delta.y);
00359
00360 }
00361 }
00362 }
00363
00364
00365
00366 void
00367 Mgr::keyboard
00368 (
00369 IN int key,
00370 IN int mods
00371 )
00372 {
00373
00374 if (m_focus) {
00375 DPRINTF(" Someone has focus!");
00376 const char * result = m_focus->keyboard(key, mods);
00377 if (result) {
00378 DPRINTF("Submit after key event! '%s'", result);
00379 this->submit(m_focusId.c_str(), result);
00380 }
00381 }
00382 }
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392 dialog_record_t *
00393 Mgr::getDialog
00394 (
00395 IN const char * id
00396 )
00397 {
00398 ASSERT(id, "null");
00399
00400 dialog_map_t::iterator i = m_dialogs.find(id);
00401 if (m_dialogs.end() == i) {
00402 return NULL;
00403 }
00404
00405 return &i->second;
00406 }
00407
00408
00409
00410 void
00411 Mgr::submit
00412 (
00413 IN const char * id,
00414 IN const char * result
00415 )
00416 {
00417 ASSERT(id, "null");
00418 ASSERT(result, "null");
00419
00420 dialog_record_t * pdr = this->getDialog(id);
00421 if (!pdr || !pdr->host)
00422 return;
00423 ASSERT(pdr->root, "null root");
00424
00425
00426 smart_ptr<Datahash> data = Datahash::create();
00427 ASSERT(data, "failed to create empty hash");
00428 data->insert("submit", result);
00429 pdr->root->addData(m_desKey, data);
00430 pdr->host->notifySubmit(id, data);
00431
00432
00433 m_focus = NULL;
00434 m_focusId = "";
00435 }
00436
00437
00438
00439
00440
00441
00442
00443
00444 bool
00445 Mgr::createDialog
00446 (
00447 IN const char * id,
00448 IN int x,
00449 IN int y,
00450 IN const Datahash * data,
00451 IN Host * host
00452 )
00453 {
00454 perf::Timer timer("createDialog");
00455 ASSERT(id, "null");
00456 ASSERT(data, "null");
00457
00458
00459
00460
00461
00462 if (!*id) {
00463 DPRINTF("Don't allow empty IDs...");
00464 return false;
00465 }
00466
00467
00468
00469
00470
00471 dialog_record_t * pdr = this->getDialog(id);
00472 if (pdr) {
00473
00474 x = pdr->bounds.left;
00475 y = pdr->bounds.top;
00476 }
00477
00478 dialog_record_t dr;
00479 dr.host = host;
00480 dr.root = constructElementTree(this, data);
00481 ASSERT(dr.root, "failed to construct dialog element tree");
00482
00483
00484 int w = dr.root->getWidth();
00485 int h = dr.root->getHeight();
00486 ASSERT(w > 0 && h > 0, "Bad dialog width or height: %d x %d", w, h);
00487 dr.bounds.set(x, y, x + w, y + h);
00488
00489
00490 m_dialogs[id] = dr;
00491
00492 return true;
00493 }
00494
00495
00496
00497 bool
00498 Mgr::doesDialogExist
00499 (
00500 IN const char * id
00501 )
00502 {
00503 ASSERT(id, "null");
00504
00505 return this->getDialog(id) ? true : false;
00506 }
00507
00508
00509
00510 void
00511 Mgr::destroyDialog
00512 (
00513 IN const char * id
00514 )
00515 {
00516 ASSERT(id, "null");
00517
00518 dialog_map_t::iterator i = m_dialogs.find(id);
00519 if (m_dialogs.end() == i) {
00520 DPRINTF("No dialog to destroy! Id='%s'", id);
00521 return;
00522 }
00523
00524
00525 m_focus = NULL;
00526 m_focusId = "";
00527
00528 m_dialogs.erase(i);
00529 }
00530
00531
00532
00533 Factory *
00534 Mgr::getFactory
00535 (
00536 IN const char * type
00537 )
00538 {
00539 ASSERT(type, "null");
00540
00541 factory_map_t::iterator i = m_factories.find(type);
00542 if (m_factories.end() == i) {
00543 DPRINTF("No factory found for dialog element type: '%s'", type);
00544 return NULL;
00545 }
00546 ASSERT(i->second, "null factory in map");
00547 return i->second;
00548 }
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558 smart_ptr<Manager>
00559 Manager::create
00560 (
00561 IN smart_ptr<crypto::DESKey>& desKey,
00562 IN smart_ptr<Drawer>& drawer
00563 )
00564 {
00565
00566 ASSERT(drawer, "null");
00567
00568 smart_ptr<Mgr> local = new Mgr;
00569 ASSERT(local, "out of memory");
00570
00571 local->initialize(desKey, drawer);
00572
00573 return local;
00574 }
00575
00576
00577
00578 };
00579