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