00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "ui_main.h"
00026 #include "ui_internal.h"
00027 #include "ui_actions.h"
00028 #include "ui_input.h"
00029 #include "ui_internal.h"
00030 #include "ui_nodes.h"
00031 #include "ui_parse.h"
00032 #include "ui_draw.h"
00033 #include "ui_dragndrop.h"
00034 #include "ui_sound.h"
00035
00036 #include "../input/cl_keys.h"
00037 #include "../input/cl_input.h"
00038
00042 static uiNode_t* focusNode;
00043
00050 static uiNode_t* hoveredNode;
00051
00055 static uiNode_t *oldHoveredNode;
00056
00060 static int oldMousePosX, oldMousePosY;
00061
00070 static uiNode_t* capturedNode;
00071
00078 static qboolean UI_FocusExecuteActionNode (void)
00079 {
00080 #if 0
00081 if (mouseSpace != MS_UI)
00082 return qfalse;
00083
00084 if (UI_GetMouseCapture())
00085 return qfalse;
00086
00087 if (focusNode) {
00088 if (focusNode->onClick) {
00089 UI_ExecuteEventActions(focusNode, focusNode->onClick);
00090 }
00091 UI_ExecuteEventActions(focusNode, focusNode->onMouseLeave);
00092 focusNode = NULL;
00093 return qtrue;
00094 }
00095 #endif
00096 return qfalse;
00097 }
00098
00099 #if 0
00104 static uiNode_t *UI_GetNextActionNode (uiNode_t* node)
00105 {
00106 if (node)
00107 node = node->next;
00108 while (node) {
00109 if (UI_CheckVisibility(node) && !node->invis
00110 && ((node->onClick && node->onMouseEnter) || node->onMouseEnter))
00111 return node;
00112 node = node->next;
00113 }
00114 return NULL;
00115 }
00116 #endif
00117
00124 static qboolean UI_FocusNextActionNode (void)
00125 {
00126 #if 0
00127 static int i = UI_MAX_WINDOWSTACK + 1;
00128
00129 if (mouseSpace != MS_UI)
00130 return qfalse;
00131
00132 if (UI_GetMouseCapture())
00133 return qfalse;
00134
00135 if (i >= ui_global.windowStackPos)
00136 i = UI_GetLastFullScreenWindow();
00137
00138 assert(i >= 0);
00139
00140 if (focusNode) {
00141 uiNode_t *node = UI_GetNextActionNode(focusNode);
00142 if (node)
00143 return UI_FocusSetNode(node);
00144 }
00145
00146 while (i < ui_global.windowStackPos) {
00147 uiNode_t* window;
00148 window = ui_global.windowStack[i++];
00149 if (UI_FocusSetNode(UI_GetNextActionNode(window->firstChild)))
00150 return qtrue;
00151 }
00152 i = UI_GetLastFullScreenWindow();
00153
00154
00155 UI_RemoveFocus();
00156 #endif
00157 return qfalse;
00158 }
00159
00163 void UI_RequestFocus (uiNode_t* node)
00164 {
00165 uiNode_t* tmp;
00166 assert(node);
00167 if (node == focusNode)
00168 return;
00169
00170
00171 tmp = focusNode;
00172 focusNode = NULL;
00173
00174
00175 if (tmp && tmp->behaviour->focusLost) {
00176 tmp->behaviour->focusLost(tmp);
00177 }
00178
00179
00180 focusNode = node;
00181 if (focusNode->behaviour->focusGained) {
00182 focusNode->behaviour->focusGained(focusNode);
00183 }
00184 }
00185
00189 qboolean UI_HasFocus (const uiNode_t* node)
00190 {
00191 return node == focusNode;
00192 }
00193
00200 void UI_RemoveFocus (void)
00201 {
00202 uiNode_t* tmp;
00203
00204 if (UI_GetMouseCapture())
00205 return;
00206
00207 if (!focusNode)
00208 return;
00209
00210
00211 tmp = focusNode;
00212 focusNode = NULL;
00213
00214
00215 if (tmp->behaviour->focusLost) {
00216 tmp->behaviour->focusLost(tmp);
00217 }
00218 }
00219
00220 static uiKeyBinding_t* UI_AllocStaticKeyBinding (void)
00221 {
00222 uiKeyBinding_t* result;
00223 if (ui_global.numKeyBindings >= UI_MAX_KEYBINDING)
00224 Com_Error(ERR_FATAL, "UI_AllocStaticKeyBinding: UI_MAX_KEYBINDING hit");
00225
00226 result = &ui_global.keyBindings[ui_global.numKeyBindings];
00227 ui_global.numKeyBindings++;
00228
00229 memset(result, 0, sizeof(*result));
00230 return result;
00231 }
00232
00233 int UI_GetKeyBindingCount (void)
00234 {
00235 return ui_global.numKeyBindings;
00236 }
00237
00238 uiKeyBinding_t* UI_GetKeyBindingByIndex (int index)
00239 {
00240 return &ui_global.keyBindings[index];
00241 }
00242
00248 void UI_SetKeyBinding (const char* path, int key)
00249 {
00250 uiNode_t *node;
00251 uiKeyBinding_t *binding;
00252 const value_t *property = NULL;
00253
00254 UI_ReadNodePath(path, NULL, &node, &property);
00255 if (node == NULL) {
00256 Com_Printf("UI_SetKeyBinding: node \"%s\" not found.\n", path);
00257 return;
00258 }
00259
00260 if (property != NULL && property->type != V_UI_NODEMETHOD)
00261 Com_Error(ERR_FATAL, "UI_SetKeyBinding: Only node and method are supported. Property @%s not found in path \"%s\".", property->string, path);
00262
00263
00264 binding = UI_AllocStaticKeyBinding();
00265 binding->node = node;
00266 binding->property = property;
00267 binding->key = key;
00268 node->key = binding;
00269 UI_WindowNodeRegisterKeyBinding(node->root, binding);
00270 }
00271
00275 static qboolean UI_KeyPressedInWindow (unsigned int key, const uiNode_t *window)
00276 {
00277 uiNode_t *node;
00278 const uiKeyBinding_t *binding;
00279
00280
00281 binding = UI_WindowNodeGetKeyBinding(window, key);
00282 if (!binding)
00283 return qfalse;
00284
00285
00286 node = binding->node;
00287 while (node) {
00288 if (node->disabled || node->invis)
00289 return qfalse;
00290 node = node->parent;
00291 }
00292
00293
00294 node = binding->node;
00295 if (binding->property == NULL)
00296 node->behaviour->activate(node);
00297 else if (binding->property->type == V_UI_NODEMETHOD) {
00298 uiCallContext_t newContext;
00299 uiNodeMethod_t func = (uiNodeMethod_t) binding->property->ofs;
00300 newContext.source = node;
00301 newContext.useCmdParam = qfalse;
00302 func(node, &newContext);
00303 } else
00304 Com_Printf("UI_KeyPressedInWindow: @%s not supported.", binding->property->string);
00305
00306 return qtrue;
00307 }
00308
00316 qboolean UI_KeyPressed (unsigned int key, unsigned short unicode)
00317 {
00318 int windowId;
00319 int lastWindowId;
00320
00321 if (UI_DNDIsDragging()) {
00322 if (key == K_ESCAPE)
00323 UI_DNDAbort();
00324 return qtrue;
00325 }
00326
00327
00328 if (focusNode && focusNode->behaviour->keyPressed) {
00329 if (focusNode->behaviour->keyPressed(focusNode, key, unicode))
00330 return qtrue;
00331 }
00332
00333
00334 switch (key) {
00335 case K_TAB:
00336 if (UI_FocusNextActionNode())
00337 return qtrue;
00338 break;
00339 case K_ENTER:
00340 case K_KP_ENTER:
00341 if (UI_FocusExecuteActionNode())
00342 return qtrue;
00343 break;
00344 case K_ESCAPE:
00345 if (UI_GetMouseCapture() != NULL) {
00346 UI_MouseRelease();
00347 return qtrue;
00348 }
00349 UI_PopWindowWithEscKey();
00350 return qtrue;
00351 }
00352
00353 lastWindowId = UI_GetLastFullScreenWindow();
00354 if (lastWindowId < 0)
00355 return qfalse;
00356
00357
00358 for (windowId = ui_global.windowStackPos - 1; windowId >= lastWindowId; windowId--) {
00359 const uiNode_t *window = ui_global.windowStack[windowId];
00360 if (!window)
00361 return qfalse;
00362 if (UI_KeyPressedInWindow(key, window))
00363 return qtrue;
00364 if (UI_WindowIsModal(window))
00365 break;
00366 }
00367
00368 return qfalse;
00369 }
00370
00374 void UI_ReleaseInput (void)
00375 {
00376 UI_RemoveFocus();
00377 UI_MouseRelease();
00378 if (UI_DNDIsDragging())
00379 UI_DNDAbort();
00380 }
00381
00386 uiNode_t* UI_GetMouseCapture (void)
00387 {
00388 return capturedNode;
00389 }
00390
00394 void UI_SetMouseCapture (uiNode_t* node)
00395 {
00396 assert(capturedNode == NULL);
00397 assert(node != NULL);
00398 capturedNode = node;
00399 }
00400
00404 void UI_MouseRelease (void)
00405 {
00406 uiNode_t *tmp = capturedNode;
00407
00408 if (capturedNode == NULL)
00409 return;
00410
00411 capturedNode = NULL;
00412 if (tmp->behaviour->capturedMouseLost)
00413 tmp->behaviour->capturedMouseLost(tmp);
00414
00415 UI_InvalidateMouse();
00416 }
00417
00422 uiNode_t *UI_GetHoveredNode (void)
00423 {
00424 return hoveredNode;
00425 }
00426
00430 void UI_InvalidateMouse (void)
00431 {
00432 oldMousePosX = -1;
00433 oldMousePosY = -1;
00434 }
00435
00439 qboolean UI_CheckMouseMove (void)
00440 {
00441
00442 if (hoveredNode && (hoveredNode->invis || !UI_CheckVisibility(hoveredNode)))
00443 UI_InvalidateMouse();
00444
00445 if (mousePosX != oldMousePosX || mousePosY != oldMousePosY) {
00446 oldMousePosX = mousePosX;
00447 oldMousePosY = mousePosY;
00448 UI_MouseMove(mousePosX, mousePosY);
00449 return qtrue;
00450 }
00451
00452 return qfalse;
00453 }
00454
00458 void UI_MouseMove (int x, int y)
00459 {
00460 if (UI_DNDIsDragging())
00461 return;
00462
00463
00464 if (capturedNode) {
00465 if (capturedNode->behaviour->capturedMouseMove)
00466 capturedNode->behaviour->capturedMouseMove(capturedNode, x, y);
00467 return;
00468 }
00469
00470 hoveredNode = UI_GetNodeAtPosition(x, y);
00471
00472
00473 if (oldHoveredNode != hoveredNode) {
00474 uiNode_t *commonNode = hoveredNode;
00475 uiNode_t *node;
00476
00477
00478 while (commonNode) {
00479 node = oldHoveredNode;
00480 while (node) {
00481 if (node == commonNode)
00482 break;
00483 node = node->parent;
00484 }
00485 if (node != NULL)
00486 break;
00487 commonNode = commonNode->parent;
00488 }
00489
00490
00491 node = oldHoveredNode;
00492 while (node != commonNode) {
00493 UI_ExecuteEventActions(node, node->onMouseLeave);
00494 node = node->parent;
00495 }
00496 if (oldHoveredNode)
00497 oldHoveredNode->state = qfalse;
00498
00499
00500 while (commonNode != hoveredNode) {
00502 node = hoveredNode;
00503 while (node->parent != commonNode)
00504 node = node->parent;
00505 commonNode = node;
00506 UI_ExecuteEventActions(node, node->onMouseEnter);
00507 }
00508 if (hoveredNode) {
00509 hoveredNode->state = qtrue;
00510 UI_ExecuteEventActions(hoveredNode, hoveredNode->onMouseEnter);
00511 }
00512 }
00513 oldHoveredNode = hoveredNode;
00514
00515
00516 if (hoveredNode && hoveredNode->behaviour->mouseMove) {
00517 hoveredNode->behaviour->mouseMove(hoveredNode, x, y);
00518 }
00519 }
00520
00521 #define UI_IsMouseInvalidate (oldMousePosX == -1)
00522
00530 static void UI_LeftClick (int x, int y)
00531 {
00532 qboolean disabled;
00533 if (UI_IsMouseInvalidate)
00534 return;
00535
00536
00537 if (capturedNode) {
00538 if (capturedNode->behaviour->leftClick)
00539 capturedNode->behaviour->leftClick(capturedNode, x, y);
00540 return;
00541 }
00542
00543
00546 if (!hoveredNode && ui_global.windowStackPos != 0) {
00547 uiNode_t *window = ui_global.windowStack[ui_global.windowStackPos - 1];
00548 if (UI_WindowIsDropDown(window)) {
00549 UI_PopWindow(qfalse);
00550 }
00551 }
00552
00553 disabled = (hoveredNode == NULL) || (hoveredNode->disabled) || (hoveredNode->parent && hoveredNode->parent->disabled);
00554 if (!disabled) {
00555 if (hoveredNode->behaviour->leftClick) {
00556 hoveredNode->behaviour->leftClick(hoveredNode, x, y);
00557 } else {
00558 UI_ExecuteEventActions(hoveredNode, hoveredNode->onClick);
00559 }
00560 }
00561 }
00562
00570 static void UI_RightClick (int x, int y)
00571 {
00572 qboolean disabled;
00573 if (UI_IsMouseInvalidate)
00574 return;
00575
00576
00577 if (capturedNode) {
00578 if (capturedNode->behaviour->rightClick)
00579 capturedNode->behaviour->rightClick(capturedNode, x, y);
00580 return;
00581 }
00582
00583 disabled = (hoveredNode == NULL) || (hoveredNode->disabled) || (hoveredNode->parent && hoveredNode->parent->disabled);
00584 if (!disabled) {
00585 if (hoveredNode->behaviour->rightClick) {
00586 hoveredNode->behaviour->rightClick(hoveredNode, x, y);
00587 } else {
00588 UI_ExecuteEventActions(hoveredNode, hoveredNode->onRightClick);
00589 }
00590 }
00591 }
00592
00598 static void UI_MiddleClick (int x, int y)
00599 {
00600 qboolean disabled;
00601 if (UI_IsMouseInvalidate)
00602 return;
00603
00604
00605 if (capturedNode) {
00606 if (capturedNode->behaviour->middleClick)
00607 capturedNode->behaviour->middleClick(capturedNode, x, y);
00608 return;
00609 }
00610
00611 disabled = (hoveredNode == NULL) || (hoveredNode->disabled) || (hoveredNode->parent && hoveredNode->parent->disabled);
00612 if (!disabled) {
00613 if (hoveredNode->behaviour->middleClick) {
00614 hoveredNode->behaviour->middleClick(hoveredNode, x, y);
00615 } else {
00616 UI_ExecuteEventActions(hoveredNode, hoveredNode->onMiddleClick);
00617 }
00618 return;
00619 }
00620 }
00621
00631 void UI_MouseWheel (qboolean down, int x, int y)
00632 {
00633
00634 if (capturedNode) {
00635 if (capturedNode->behaviour->mouseWheel)
00636 capturedNode->behaviour->mouseWheel(capturedNode, down, x, y);
00637 return;
00638 }
00639
00640 if (hoveredNode) {
00641 if (hoveredNode->behaviour->mouseWheel) {
00642 hoveredNode->behaviour->mouseWheel(hoveredNode, down, x, y);
00643 } else {
00644 if (hoveredNode->onWheelUp && !down)
00645 UI_ExecuteEventActions(hoveredNode, hoveredNode->onWheelUp);
00646 if (hoveredNode->onWheelDown && down)
00647 UI_ExecuteEventActions(hoveredNode, hoveredNode->onWheelDown);
00648 else
00649 UI_ExecuteEventActions(hoveredNode, hoveredNode->onWheel);
00650 }
00651 }
00652 }
00653
00662 void UI_MouseDown (int x, int y, int button)
00663 {
00664 uiNode_t *node;
00665
00666
00667 node = capturedNode ? capturedNode : hoveredNode;
00668
00669 if (node != NULL) {
00670 UI_MoveWindowOnTop(node->root);
00671 if (node->behaviour->mouseDown)
00672 node->behaviour->mouseDown(node, x, y, button);
00673 }
00674
00675
00677 switch (button) {
00678 case K_MOUSE1:
00679 UI_LeftClick(x, y);
00680 break;
00681 case K_MOUSE2:
00682 UI_RightClick(x, y);
00683 break;
00684 case K_MOUSE3:
00685 UI_MiddleClick(x, y);
00686 break;
00687 }
00688 UI_PlaySound("click1");
00689 }
00690
00699 void UI_MouseUp (int x, int y, int button)
00700 {
00701 uiNode_t *node;
00702
00703
00704 node = capturedNode ? capturedNode : hoveredNode;
00705
00706 if (node == NULL)
00707 return;
00708
00709 if (node->behaviour->mouseUp)
00710 node->behaviour->mouseUp(node, x, y, button);
00711 }