Line data Source code
1 : /* File: gui_sketch_nav_tree.inl; Copyright and License: see below */
2 :
3 : #include "u8/u8_log.h"
4 :
5 0 : static inline data_row_t gui_sketch_nav_tree_get_root_diagram_id ( const gui_sketch_nav_tree_t *this_ )
6 : {
7 0 : assert( (*this_).ancestors_count <= GUI_SKETCH_NAV_TREE_CONST_MAX_ANCESTORS );
8 : data_row_t result;
9 :
10 0 : if ( (*this_).ancestors_count == 0 )
11 : {
12 0 : result = DATA_ROW_VOID;
13 : }
14 : else
15 : {
16 0 : result = data_diagram_get_row_id ( &((*this_).ancestor_diagrams[(*this_).ancestors_count-1]) );
17 : }
18 :
19 0 : return result;
20 : }
21 :
22 0 : static inline int32_t gui_sketch_nav_tree_get_siblings_highest_order ( const gui_sketch_nav_tree_t *this_ )
23 : {
24 0 : assert( (*this_).siblings_count <= GUI_SKETCH_NAV_TREE_CONST_MAX_SIBLINGS );
25 : int32_t result;
26 :
27 0 : if ( (*this_).siblings_count == 0 )
28 : {
29 0 : result = 0;
30 : }
31 : else
32 : {
33 0 : result = data_diagram_get_list_order ( &((*this_).sibling_diagrams[(*this_).siblings_count-1]) );
34 : }
35 :
36 0 : return result;
37 : }
38 :
39 0 : static inline int32_t gui_sketch_nav_tree_get_children_highest_order ( const gui_sketch_nav_tree_t *this_ )
40 : {
41 0 : assert( (*this_).children_count <= GUI_SKETCH_NAV_TREE_CONST_MAX_CHILDREN );
42 :
43 : int32_t result;
44 :
45 0 : if ( (*this_).children_count == 0 )
46 : {
47 0 : result = 0;
48 : }
49 : else
50 : {
51 0 : result = data_diagram_get_list_order ( &((*this_).child_diagrams[(*this_).children_count-1]) );
52 : }
53 :
54 0 : return result;
55 : }
56 :
57 0 : static inline gui_error_t gui_sketch_nav_tree_is_descendant ( const gui_sketch_nav_tree_t *this_,
58 : data_row_t probe_ancestor_id,
59 : data_row_t probe_descendant_id,
60 : bool *out_is_descendant )
61 : {
62 0 : assert( (*this_).ancestors_count <= GUI_SKETCH_NAV_TREE_CONST_MAX_ANCESTORS );
63 0 : assert( (*this_).siblings_count <= GUI_SKETCH_NAV_TREE_CONST_MAX_SIBLINGS );
64 0 : assert( (*this_).children_count <= GUI_SKETCH_NAV_TREE_CONST_MAX_CHILDREN );
65 :
66 : gui_error_t result;
67 :
68 : /* search the two ids in the diagram lists */
69 0 : int_fast32_t probe_anc_in_anc_idx = -1;
70 0 : int_fast32_t probe_anc_in_sib_idx = -1;
71 0 : int_fast32_t probe_anc_in_child_idx = -1;
72 0 : int_fast32_t probe_desc_in_anc_idx = -1;
73 0 : int_fast32_t probe_desc_in_sib_idx = -1;
74 0 : int_fast32_t probe_desc_in_child_idx = -1;
75 :
76 0 : for ( uint_fast32_t anc_idx = 0; anc_idx < (*this_).ancestors_count; anc_idx ++ )
77 : {
78 0 : if ( probe_ancestor_id == data_diagram_get_row_id ( &((*this_).ancestor_diagrams[anc_idx]) ) )
79 : {
80 0 : probe_anc_in_anc_idx = anc_idx;
81 : }
82 0 : if ( probe_descendant_id == data_diagram_get_row_id ( &((*this_).ancestor_diagrams[anc_idx]) ) )
83 : {
84 0 : probe_desc_in_anc_idx = anc_idx;
85 : }
86 : }
87 0 : for ( uint_fast32_t sib_idx = 0; sib_idx < (*this_).siblings_count; sib_idx ++ )
88 : {
89 0 : if ( probe_ancestor_id == data_diagram_get_row_id ( &((*this_).sibling_diagrams[sib_idx]) ) )
90 : {
91 0 : probe_anc_in_sib_idx = sib_idx;
92 : }
93 0 : if ( probe_descendant_id == data_diagram_get_row_id ( &((*this_).sibling_diagrams[sib_idx]) ) )
94 : {
95 0 : probe_desc_in_sib_idx = sib_idx;
96 : }
97 : }
98 0 : for ( uint_fast32_t child_idx = 0; child_idx < (*this_).children_count; child_idx ++ )
99 : {
100 0 : if ( probe_ancestor_id == data_diagram_get_row_id ( &((*this_).child_diagrams[child_idx]) ) )
101 : {
102 0 : probe_anc_in_child_idx = child_idx;
103 : }
104 0 : if ( probe_descendant_id == data_diagram_get_row_id ( &((*this_).child_diagrams[child_idx]) ) )
105 : {
106 0 : probe_desc_in_child_idx = child_idx;
107 : }
108 : }
109 :
110 : /* define the return value */
111 0 : if (( probe_anc_in_anc_idx == -1 )&&( probe_anc_in_sib_idx == -1 )&&( probe_anc_in_child_idx == -1 ))
112 : {
113 : /* probe_ancestor_id not found */
114 0 : result = GUI_ERROR_UNKNOWN_OBJECT;
115 0 : *out_is_descendant = false; /* avoid "uninitialzed" warnings */
116 : }
117 0 : else if (( probe_desc_in_anc_idx == -1 )&&( probe_desc_in_sib_idx == -1 )&&( probe_desc_in_child_idx == -1 ))
118 : {
119 : /* probe_descendant_id not found */
120 0 : result = GUI_ERROR_UNKNOWN_OBJECT;
121 0 : *out_is_descendant = false; /* avoid "uninitialzed" warnings */
122 : }
123 : else
124 : {
125 0 : result = GUI_ERROR_NONE;
126 :
127 0 : if ( probe_anc_in_anc_idx != -1 )
128 : {
129 0 : if ( probe_desc_in_anc_idx != -1 )
130 : {
131 0 : *out_is_descendant = ( probe_anc_in_anc_idx > probe_desc_in_anc_idx ); /* root is last in list */
132 : }
133 : else
134 : {
135 0 : assert( ( probe_desc_in_sib_idx != -1 )||( probe_desc_in_child_idx != -1 ) );
136 0 : *out_is_descendant = true;
137 : }
138 : }
139 0 : else if ( probe_anc_in_sib_idx != -1 )
140 : {
141 0 : if ( probe_desc_in_child_idx != -1 )
142 : {
143 0 : *out_is_descendant = ( probe_anc_in_sib_idx == (*this_).siblings_self_index );
144 : }
145 : else
146 : {
147 0 : assert( ( probe_desc_in_anc_idx != -1 )||( probe_desc_in_sib_idx != -1 ) );
148 0 : *out_is_descendant = false; /* probe_descendant_id is ancestor or sibling to probe_ancestor_id, not descendant */
149 : }
150 : }
151 : else
152 : {
153 0 : assert ( probe_anc_in_child_idx != -1 );
154 0 : *out_is_descendant = false; /* probe_descendant_id is sibling or ancestor to probe_ancestor_id, not descendant */
155 : }
156 : }
157 :
158 0 : return result;
159 : }
160 :
161 : static inline shape_int_rectangle_t gui_sketch_nav_tree_get_bounds( const gui_sketch_nav_tree_t *this_ )
162 : {
163 : return (*this_).bounds;
164 : }
165 :
166 4 : static inline void gui_sketch_nav_tree_set_bounds( gui_sketch_nav_tree_t *this_, shape_int_rectangle_t bounds )
167 : {
168 4 : (*this_).bounds = bounds;
169 4 : }
170 :
171 0 : static inline bool gui_sketch_nav_tree_is_visible( const gui_sketch_nav_tree_t *this_ )
172 : {
173 0 : return (*this_).visible;
174 : }
175 :
176 0 : static inline void gui_sketch_nav_tree_set_visible( gui_sketch_nav_tree_t *this_, bool visible )
177 : {
178 0 : (*this_).visible = visible;
179 0 : }
180 :
181 0 : static inline const data_diagram_t *gui_sketch_nav_tree_get_diagram_ptr ( const gui_sketch_nav_tree_t *this_ )
182 : {
183 0 : return &((*this_).ancestor_diagrams[0]);
184 : }
185 :
186 17 : static inline void gui_sketch_nav_tree_get_button_at_pos ( const gui_sketch_nav_tree_t *this_,
187 : int32_t x,
188 : int32_t y,
189 : gui_sketch_action_t *out_action_id )
190 : {
191 17 : assert ( NULL != out_action_id );
192 :
193 : /* default in case no object found */
194 : {
195 17 : *out_action_id = GUI_SKETCH_ACTION_NONE;
196 : }
197 :
198 : /* search object */
199 17 : if ( shape_int_rectangle_contains( &((*this_).bounds), x, y ) )
200 : {
201 16 : const unsigned int count = (*this_).node_count;
202 16 : assert( count <= GUI_SKETCH_NAV_TREE_CONST_MAX_NODES );
203 96 : for ( unsigned int idx = 0; idx < count; idx ++ )
204 : {
205 80 : const pos_nav_tree_node_t *const node = &((*this_).node_pos[idx]);
206 80 : const shape_int_rectangle_t *icon_box = pos_nav_tree_node_get_icon_box_const( node );
207 80 : const shape_int_rectangle_t *label_box = pos_nav_tree_node_get_label_box_const( node );
208 :
209 80 : if ( shape_int_rectangle_contains( icon_box, x, y ) || shape_int_rectangle_contains( label_box, x, y ) )
210 : {
211 15 : const pos_nav_tree_node_type_t node_type = pos_nav_tree_node_get_type( node );
212 15 : switch( node_type )
213 : {
214 1 : case POS_NAV_TREE_NODE_TYPE_NEW_ROOT:
215 : {
216 1 : *out_action_id = GUI_SKETCH_ACTION_NEW_ROOT_DIAGRAM;
217 : }
218 1 : break;
219 :
220 2 : case POS_NAV_TREE_NODE_TYPE_NEW_SIBLING:
221 : {
222 2 : *out_action_id = GUI_SKETCH_ACTION_NEW_SIBLING_DIAGRAM;
223 : }
224 2 : break;
225 :
226 3 : case POS_NAV_TREE_NODE_TYPE_NEW_CHILD:
227 : {
228 3 : *out_action_id = GUI_SKETCH_ACTION_NEW_CHILD_DIAGRAM;
229 : }
230 3 : break;
231 :
232 80 : default:
233 : {
234 : }
235 : }
236 : }
237 : }
238 : }
239 17 : }
240 :
241 15 : static inline const pos_nav_tree_node_t *gui_sketch_nav_tree_get_node_pos_const ( const gui_sketch_nav_tree_t *this_,
242 : uint32_t index )
243 : {
244 15 : assert( index < (*this_).node_count );
245 15 : return &((*this_).node_pos[index]);
246 : }
247 :
248 19 : static inline uint32_t gui_sketch_nav_tree_get_node_count ( const gui_sketch_nav_tree_t *this_ )
249 : {
250 19 : assert( (*this_).node_count <= GUI_SKETCH_NAV_TREE_CONST_MAX_NODES );
251 19 : return (*this_).node_count;
252 : }
253 :
254 : static inline const pos_nav_tree_gap_t *gui_sketch_nav_tree_get_gap_pos_const ( const gui_sketch_nav_tree_t *this_,
255 : uint32_t index )
256 : {
257 : assert( index < (*this_).gap_count );
258 : return &((*this_).gap_pos[index]);
259 : }
260 :
261 : static inline uint32_t gui_sketch_nav_tree_get_gap_count ( const gui_sketch_nav_tree_t *this_ )
262 : {
263 : assert( (*this_).gap_count <= GUI_SKETCH_NAV_TREE_CONST_MAX_GAPS );
264 : return (*this_).gap_count;
265 : }
266 :
267 :
268 : /*
269 : Copyright 2018-2025 Andreas Warnke
270 :
271 : Licensed under the Apache License, Version 2.0 (the "License");
272 : you may not use this file except in compliance with the License.
273 : You may obtain a copy of the License at
274 :
275 : http://www.apache.org/licenses/LICENSE-2.0
276 :
277 : Unless required by applicable law or agreed to in writing, software
278 : distributed under the License is distributed on an "AS IS" BASIS,
279 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
280 : See the License for the specific language governing permissions and
281 : limitations under the License.
282 : */
|