1 /**
2  * @file
3  * @todo manage disabled option
4  */
5 
6 /*
7 Copyright (C) 2002-2013 UFO: Alien Invasion.
8 
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 
18 See the GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23 
24 */
25 
26 #include "../ui_main.h"
27 #include "../ui_internal.h"
28 #include "../ui_parse.h"
29 #include "../ui_draw.h"
30 #include "../ui_data.h"
31 #include "ui_node_abstractoption.h"
32 #include "ui_node_abstractnode.h"
33 
34 #define EXTRADATA_TYPE abstractOptionExtraData_t
35 #define EXTRADATA(node) UI_EXTRADATA(node, EXTRADATA_TYPE)
36 
37 /**
38  * @brief Sort options by alphabet
39  */
UI_OptionNodeSortOptions(uiNode_t * node)40 void UI_OptionNodeSortOptions (uiNode_t* node)
41 {
42 	uiNode_t* option;
43 	assert(UI_Node_IsOptionContainer(node));
44 	UI_SortOptions(&node->firstChild);
45 
46 	/** update lastChild */
47 	/** @todo the sort option should do it itself */
48 	option = node->firstChild;
49 	while (option->next)
50 		option = option->next;
51 	node->lastChild = option;
52 }
53 
UI_AbstractOptionGetCurrentValue(uiNode_t * node)54 const char* UI_AbstractOptionGetCurrentValue (uiNode_t* node)
55 {
56 	/* no cvar given? */
57 	if (!EXTRADATA(node).cvar || !*EXTRADATA(node).cvar) {
58 		Com_Printf("UI_AbstractOptionGetCurrentValue: node '%s' doesn't have a valid cvar assigned\n", UI_GetPath(node));
59 		return nullptr;
60 	}
61 
62 	/* not a cvar? */
63 	if (!Q_strstart(EXTRADATA(node).cvar, "*cvar:"))
64 		return nullptr;
65 
66 	return UI_GetReferenceString(node, EXTRADATA(node).cvar);
67 }
68 
UI_AbstractOptionSetCurrentValue(uiNode_t * node,const char * value)69 void UI_AbstractOptionSetCurrentValue(uiNode_t* node, const char* value)
70 {
71 	const char* cvarName = &EXTRADATA(node).cvar[6];
72 	Cvar_Set(cvarName, "%s", value);
73 	if (node->onChange)
74 		UI_ExecuteEventActions(node, node->onChange);
75 }
76 
doLayout(uiNode_t * node)77 void uiAbstractOptionNode::doLayout (uiNode_t* node)
78 {
79 	uiNode_t* option = node->firstChild;
80 
81 	if (EXTRADATA(node).dataId == 0) {
82 		int count = 0;
83 		while (option && option->behaviour == ui_optionBehaviour) {
84 			UI_Validate(option);
85 			if (!option->invis)
86 				count++;
87 			option = option->next;
88 		}
89 
90 		EXTRADATA(node).count = count;
91 	}
92 
93 	node->invalidated = false;
94 }
95 
96 /**
97  * @brief Return the first option of the node
98  * @todo check versionId and update cached data, and fire events
99  */
UI_AbstractOptionGetFirstOption(uiNode_t * node)100 uiNode_t* UI_AbstractOptionGetFirstOption (uiNode_t* node)
101 {
102 	if (node->firstChild && node->firstChild->behaviour == ui_optionBehaviour) {
103 		return node->firstChild;
104 	} else {
105 		const int v = UI_GetDataVersion(EXTRADATA(node).dataId);
106 		if (v != EXTRADATA(node).versionId) {
107 			int count = 0;
108 			uiNode_t* option = UI_GetOption(EXTRADATA(node).dataId);
109 			while (option) {
110 				if (!option->invis)
111 					count++;
112 				option = option->next;
113 			}
114 			EXTRADATA(node).count = count;
115 			EXTRADATA(node).versionId = v;
116 		}
117 		return UI_GetOption(EXTRADATA(node).dataId);
118 	}
119 }
120 
121 /**
122  * @brief Return size of the cell, which is the size (in virtual "pixel") which represents 1 in the scroll values.
123  * Here expect the widget can scroll pixel per pixel.
124  * @return Size in pixel.
125  */
getCellWidth(uiNode_t * node)126 int uiAbstractOptionNode::getCellWidth (uiNode_t* node)
127 {
128 	return 1;
129 }
130 
131 /**
132  * @brief Return size of the cell, which is the size (in virtual "pixel") which represents 1 in the scroll values.
133  * Here we guess the widget can scroll pixel per pixel.
134  * @return Size in pixel.
135  */
getCellHeight(uiNode_t * node)136 int uiAbstractOptionNode::getCellHeight (uiNode_t* node)
137 {
138 	return 1;
139 }
140 
UI_RegisterAbstractOptionNode(uiBehaviour_t * behaviour)141 void UI_RegisterAbstractOptionNode (uiBehaviour_t* behaviour)
142 {
143 	behaviour->name = "abstractoption";
144 	behaviour->isAbstract = true;
145 	behaviour->extraDataSize = sizeof(EXTRADATA_TYPE);
146 	behaviour->drawItselfChild = true;
147 	behaviour->manager = UINodePtr(new uiAbstractOptionNode());
148 
149 	/** Optional. Data ID we want to use. It must be an option list. It substitute to the inline options */
150 	UI_RegisterExtradataNodeProperty(behaviour, "dataid", V_UI_DATAID, EXTRADATA_TYPE, dataId);
151 	/** Optional. We can define the height of the block containing an option. */
152 	UI_RegisterExtradataNodeProperty(behaviour, "lineheight", V_INT, EXTRADATA_TYPE, lineHeight);
153 
154 	/* position of the vertical view (into the full number of elements the node contain) */
155 	UI_RegisterExtradataNodeProperty(behaviour, "viewpos", V_INT, EXTRADATA_TYPE, scrollY.viewPos);
156 	/* size of the vertical view (proportional to the number of elements the node can display without moving) */
157 	UI_RegisterExtradataNodeProperty(behaviour, "viewsize", V_INT, EXTRADATA_TYPE, scrollY.viewSize);
158 	/* full vertical size (proportional to the number of elements the node contain) */
159 	UI_RegisterExtradataNodeProperty(behaviour, "fullsize", V_INT, EXTRADATA_TYPE, scrollY.fullSize);
160 
161 	/* number of elements contain the node */
162 	UI_RegisterExtradataNodeProperty(behaviour, "count", V_INT, EXTRADATA_TYPE, count);
163 
164 	/* Define the cvar containing the value of the current selected option */
165 	UI_RegisterExtradataNodeProperty(behaviour, "cvar", V_UI_CVAR, EXTRADATA_TYPE, cvar);
166 
167 	/* Called when one of the properties viewpos/viewsize/fullsize change */
168 	UI_RegisterExtradataNodeProperty(behaviour, "onviewchange", V_UI_ACTION, EXTRADATA_TYPE, onViewChange);
169 }
170