ui_input.c

Go to the documentation of this file.
00001 
00005 /*
00006 Copyright (C) 2002-2010 UFO: Alien Invasion.
00007 
00008 This program is free software; you can redistribute it and/or
00009 modify it under the terms of the GNU General Public License
00010 as published by the Free Software Foundation; either version 2
00011 of the License, or (at your option) any later version.
00012 
00013 This program is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00016 
00017 See the GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with this program; if not, write to the Free Software
00021 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
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;  /* to cycle between all windows */
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     /* no node to focus */
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     /* invalidate the data before calling the event */
00171     tmp = focusNode;
00172     focusNode = NULL;
00173 
00174     /* lost the focus */
00175     if (tmp && tmp->behaviour->focusLost) {
00176         tmp->behaviour->focusLost(tmp);
00177     }
00178 
00179     /* get the focus */
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     /* invalidate the data before calling the event */
00211     tmp = focusNode;
00212     focusNode = NULL;
00213 
00214     /* callback the lost of the focus */
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     /* init and link the keybinding */
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     /* search requested key binding */
00281     binding = UI_WindowNodeGetKeyBinding(window, key);
00282     if (!binding)
00283         return qfalse;
00284 
00285     /* check node visibility */
00286     node = binding->node;
00287     while (node) {
00288         if (node->disabled || node->invis)
00289             return qfalse;
00290         node = node->parent;
00291     }
00292 
00293     /* execute event */
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     /* translate event into the node with focus */
00328     if (focusNode && focusNode->behaviour->keyPressed) {
00329         if (focusNode->behaviour->keyPressed(focusNode, key, unicode))
00330             return qtrue;
00331     }
00332 
00333     /* else use common behaviour */
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     /* check "active" window from top to down */
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     /* is hovered node no more draw */
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     /* send the captured move mouse event */
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     /* update nodes: send 'in' and 'out' event */
00473     if (oldHoveredNode != hoveredNode) {
00474         uiNode_t *commonNode = hoveredNode;
00475         uiNode_t *node;
00476 
00477         /* search the common node */
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         /* send 'leave' event from old node to common node */
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         /* send 'enter' event from common node to new node */
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     /* send the move event */
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     /* send it to the captured mouse node */
00537     if (capturedNode) {
00538         if (capturedNode->behaviour->leftClick)
00539             capturedNode->behaviour->leftClick(capturedNode, x, y);
00540         return;
00541     }
00542 
00543     /* if we click outside a dropdown window, we close it */
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     /* send it to the captured mouse node */
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     /* send it to the captured mouse node */
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     /* send it to the captured mouse node */
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     /* captured or hover node */
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     /* click event */
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     /* captured or hover node */
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 }

Generated by  doxygen 1.6.2