1 /**
2 * @file
3 */
4
5 /*
6 Copyright (C) 2002-2013 UFO: Alien Invasion.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
17 See the GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23 */
24
25 #include "../ui_main.h"
26 #include "../ui_parse.h"
27 #include "../ui_behaviour.h"
28 #include "ui_node_abstractnode.h"
29 #include "ui_node_option.h"
30
31 #include "../../client.h" /* gettext _() */
32
33 /**
34 * Allow to check if a node is an option without string check
35 */
36 const uiBehaviour_t* ui_optionBehaviour = nullptr;
37
38 #define EXTRADATA_TYPE optionExtraData_t
39 #define EXTRADATA(node) UI_EXTRADATA(node, EXTRADATA_TYPE)
40 #define EXTRADATACONST(node) UI_EXTRADATACONST(node, EXTRADATA_TYPE)
41
42 static const value_t* propertyCollapsed;
43
44
45 /**
46 * @brief update option cache about child, according to collapse and visible status
47 * @note can be a common function for all option node
48 * @return number of visible elements
49 */
UI_OptionUpdateCache(uiNode_t * option)50 int UI_OptionUpdateCache (uiNode_t* option)
51 {
52 int count = 0;
53 while (option) {
54 int localCount = 0;
55 assert(option->behaviour == ui_optionBehaviour);
56 if (option->invis) {
57 option = option->next;
58 continue;
59 }
60 if (OPTIONEXTRADATA(option).collapsed) {
61 OPTIONEXTRADATA(option).childCount = 0;
62 option = option->next;
63 count++;
64 continue;
65 }
66 if (option->firstChild)
67 localCount = UI_OptionUpdateCache(option->firstChild);
68 OPTIONEXTRADATA(option).childCount = localCount;
69 count += 1 + localCount;
70 option = option->next;
71 }
72 return count;
73 }
74
doLayout(uiNode_t * node)75 void uiOptionNode::doLayout (uiNode_t* node)
76 {
77 uiNode_t* child = node->firstChild;
78 int count = 0;
79
80 while (child && child->behaviour == ui_optionBehaviour) {
81 UI_Validate(child);
82 if (!child->invis) {
83 if (EXTRADATA(child).collapsed)
84 count += 1 + EXTRADATA(child).childCount;
85 else
86 count += 1;
87 }
88 child = child->next;
89 }
90 EXTRADATA(node).childCount = count;
91 node->invalidated = false;
92 }
93
onPropertyChanged(uiNode_t * node,const value_t * property)94 void uiOptionNode::onPropertyChanged (uiNode_t* node, const value_t* property)
95 {
96 if (property == propertyCollapsed) {
97 UI_Invalidate(node);
98 return;
99 }
100 uiLocatedNode::onPropertyChanged(node, property);
101 }
102
103 /**
104 * @brief Initializes an option with a very little set of values.
105 * @param[in] option Context option
106 * @param[in] label label displayed
107 * @param[in] value value used when this option is selected
108 */
UI_InitOption(uiNode_t * option,const char * label,const char * value)109 static void UI_InitOption (uiNode_t* option, const char* label, const char* value)
110 {
111 assert(option);
112 assert(option->behaviour == ui_optionBehaviour);
113 Q_strncpyz(OPTIONEXTRADATA(option).label, label, sizeof(OPTIONEXTRADATA(option).label));
114 Q_strncpyz(OPTIONEXTRADATA(option).value, value, sizeof(OPTIONEXTRADATA(option).value));
115 }
116
117 /**
118 * @brief Initializes an option with a very little set of values.
119 * @param[in] name The name of the new node
120 * @param[in] label label displayed
121 * @param[in] value value used when this option is selected
122 */
UI_AllocOptionNode(const char * name,const char * label,const char * value)123 uiNode_t* UI_AllocOptionNode (const char* name, const char* label, const char* value)
124 {
125 uiNode_t* option;
126 option = UI_AllocNode(name, "option", true);
127 UI_InitOption(option, label, value);
128 return option;
129 }
130
UI_RegisterOptionNode(uiBehaviour_t * behaviour)131 void UI_RegisterOptionNode (uiBehaviour_t* behaviour)
132 {
133 behaviour->name = "option";
134 behaviour->extraDataSize = sizeof(EXTRADATA_TYPE);
135 behaviour->manager = UINodePtr(new uiOptionNode());
136
137 /**
138 * Displayed text
139 */
140 UI_RegisterExtradataNodeProperty(behaviour, "label", V_STRING, EXTRADATA_TYPE, label);
141
142 /**
143 * Value of the option
144 */
145 UI_RegisterExtradataNodeProperty(behaviour, "value", V_STRING, EXTRADATA_TYPE, value);
146
147 /**
148 * If true, child are not displayed
149 */
150 propertyCollapsed = UI_RegisterExtradataNodeProperty(behaviour, "collapsed", V_BOOL, EXTRADATA_TYPE, collapsed);
151
152 /* Icon used to display the node
153 */
154 UI_RegisterExtradataNodeProperty(behaviour, "icon", V_UI_SPRITEREF, EXTRADATA_TYPE, icon);
155 UI_RegisterExtradataNodeProperty(behaviour, "flipicon", V_BOOL, EXTRADATA_TYPE, flipIcon);
156
157 ui_optionBehaviour = behaviour;
158 }
159