Line data Source code
1 : /* File: gui_sketch_card_layouter.c; Copyright and License: see below */
2 :
3 : #include "gui_sketch_card_layouter.h"
4 : #include "sketch/gui_sketch_area.h"
5 : #include "u8/u8_trace.h"
6 : #include "u8/u8_log.h"
7 :
8 0 : void gui_sketch_card_layouter_init( gui_sketch_card_layouter_t *this_, shape_int_rectangle_t *bounds )
9 : {
10 0 : U8_TRACE_BEGIN();
11 0 : assert( NULL != bounds );
12 :
13 0 : (*this_).bounds = *bounds;
14 :
15 0 : U8_TRACE_END();
16 0 : }
17 :
18 0 : void gui_sketch_card_layouter_destroy( gui_sketch_card_layouter_t *this_ )
19 : {
20 0 : U8_TRACE_BEGIN();
21 :
22 0 : U8_TRACE_END();
23 0 : }
24 :
25 : static const uint_fast32_t RATIO_WIDTH = 36;
26 : static const uint_fast32_t RATIO_HEIGHT = 24;
27 : static const uint_fast32_t BORDER = 8;
28 :
29 0 : void gui_sketch_card_layouter_layout ( gui_sketch_card_layouter_t *this_,
30 : gui_tool_t selected_tool,
31 : gui_sketch_card_t io_cards[],
32 : uint32_t cards_num,
33 : cairo_t *cr )
34 : {
35 0 : U8_TRACE_BEGIN();
36 0 : assert( NULL != cr );
37 0 : assert( NULL != io_cards );
38 0 : assert( cards_num <= GUI_SKETCH_AREA_CONST_MAX_CARDS );
39 :
40 : /* fetch area bounds */
41 0 : const uint_fast32_t width = shape_int_rectangle_get_width( &((*this_).bounds) );
42 0 : const uint_fast32_t height = shape_int_rectangle_get_height( &((*this_).bounds) );
43 0 : const int_fast32_t left = shape_int_rectangle_get_left( &((*this_).bounds) );
44 0 : const int_fast32_t top = shape_int_rectangle_get_top( &((*this_).bounds) );
45 0 : U8_TRACE_INFO_INT_INT( "width, height", width, height );
46 :
47 : /* calculate card sizes */
48 : uint_fast32_t focus_card_height;
49 : uint_fast32_t focus_card_width;
50 : {
51 0 : const uint_fast32_t focus_card_w_space = (width * 7) / 10;
52 0 : const uint_fast32_t focus_card_h_space = (height * 4) / 10;
53 0 : if ( (focus_card_w_space * RATIO_HEIGHT) > (focus_card_h_space * RATIO_WIDTH) )
54 : {
55 0 : focus_card_height = focus_card_h_space;
56 0 : focus_card_width = (focus_card_height * RATIO_WIDTH) / RATIO_HEIGHT;
57 : }
58 : else
59 : {
60 0 : focus_card_width = focus_card_w_space;
61 0 : focus_card_height = (focus_card_width * RATIO_HEIGHT) / RATIO_WIDTH;
62 : }
63 : }
64 0 : const uint_fast32_t parent_card_height = (focus_card_height * 6) / 10;
65 0 : const uint_fast32_t parent_card_width = (focus_card_width * 6) / 10;
66 :
67 : /* layout cards */
68 0 : switch( selected_tool )
69 : {
70 0 : case GUI_TOOL_SEARCH:
71 : {
72 : shape_int_rectangle_t card_bounds;
73 :
74 : /* search results */
75 : {
76 0 : shape_int_rectangle_init( &card_bounds, left, top, width, height );
77 0 : gui_sketch_card_layouter_private_layout_to_grid( this_,
78 : &card_bounds,
79 : focus_card_height,
80 : io_cards,
81 : cards_num,
82 : cr
83 : );
84 : }
85 : }
86 0 : break;
87 :
88 0 : case GUI_TOOL_NAVIGATE:
89 : {
90 : shape_int_rectangle_t card_bounds;
91 :
92 : /* self */
93 0 : assert(cards_num > GUI_SKETCH_AREA_CONST_FOCUSED_CARD);
94 : {
95 0 : const int_fast32_t self_left = (left + width) - focus_card_width - BORDER;
96 0 : const int_fast32_t self_top = top + BORDER + (parent_card_height/2);
97 0 : shape_int_rectangle_init( &card_bounds, self_left, self_top, focus_card_width, focus_card_height );
98 0 : shape_int_rectangle_trace( &card_bounds );
99 0 : gui_sketch_card_set_bounds( &(io_cards[GUI_SKETCH_AREA_CONST_FOCUSED_CARD]), card_bounds );
100 0 : const bool valid_card = gui_sketch_card_is_valid( &(io_cards[GUI_SKETCH_AREA_CONST_FOCUSED_CARD]) );
101 0 : gui_sketch_card_do_layout( &(io_cards[GUI_SKETCH_AREA_CONST_FOCUSED_CARD]), cr );
102 0 : gui_sketch_card_set_visible( &(io_cards[GUI_SKETCH_AREA_CONST_FOCUSED_CARD]), valid_card );
103 : }
104 :
105 : /* parent */
106 0 : assert(cards_num > GUI_SKETCH_AREA_CONST_PARENT_CARD);
107 : {
108 0 : const int_fast32_t parent_left = left + BORDER;
109 0 : const int_fast32_t parent_top = top + BORDER;
110 0 : shape_int_rectangle_init( &card_bounds, parent_left, parent_top, parent_card_width, parent_card_height );
111 0 : shape_int_rectangle_trace( &card_bounds );
112 0 : gui_sketch_card_set_bounds( &(io_cards[GUI_SKETCH_AREA_CONST_PARENT_CARD]), card_bounds );
113 0 : const bool valid_parent = gui_sketch_card_is_valid( &(io_cards[GUI_SKETCH_AREA_CONST_PARENT_CARD]) );
114 0 : gui_sketch_card_do_layout( &(io_cards[GUI_SKETCH_AREA_CONST_PARENT_CARD]), cr );
115 0 : gui_sketch_card_set_visible( &(io_cards[GUI_SKETCH_AREA_CONST_PARENT_CARD]), valid_parent );
116 : }
117 :
118 : /* children */
119 0 : assert(cards_num >= GUI_SKETCH_AREA_CONST_FIRST_CHILD_CARD);
120 : {
121 0 : const int_fast32_t children_top = top + focus_card_height + (parent_card_height/2) + 2*BORDER;
122 0 : const uint_fast32_t children_height = (height > (children_top-top)) ? (height - (children_top-top)) : 0;
123 0 : shape_int_rectangle_init( &card_bounds, left, children_top, width, children_height );
124 0 : gui_sketch_card_layouter_private_layout_to_grid( this_,
125 : &card_bounds,
126 : parent_card_height,
127 : &(io_cards[GUI_SKETCH_AREA_CONST_FIRST_CHILD_CARD]),
128 0 : cards_num-GUI_SKETCH_AREA_CONST_FIRST_CHILD_CARD,
129 : cr
130 : );
131 : }
132 : }
133 0 : break;
134 :
135 0 : case GUI_TOOL_EDIT: /* or */
136 : case GUI_TOOL_CREATE:
137 : {
138 : shape_int_rectangle_t card_bounds;
139 :
140 0 : assert(cards_num == GUI_SKETCH_AREA_CONST_FOCUSED_CARD+1);
141 : {
142 0 : card_bounds = (*this_).bounds;
143 0 : shape_int_rectangle_shrink_by_border( &card_bounds, BORDER );
144 0 : shape_int_rectangle_shrink_to_ratio( &card_bounds, RATIO_WIDTH, RATIO_HEIGHT, SHAPE_H_ALIGN_CENTER, SHAPE_V_ALIGN_CENTER );
145 0 : shape_int_rectangle_trace( &card_bounds );
146 0 : gui_sketch_card_set_bounds( &(io_cards[GUI_SKETCH_AREA_CONST_FOCUSED_CARD]), card_bounds );
147 0 : const bool valid_card = gui_sketch_card_is_valid( &(io_cards[GUI_SKETCH_AREA_CONST_FOCUSED_CARD]) );
148 0 : gui_sketch_card_do_layout( &(io_cards[GUI_SKETCH_AREA_CONST_FOCUSED_CARD]), cr );
149 0 : gui_sketch_card_set_visible( &(io_cards[GUI_SKETCH_AREA_CONST_FOCUSED_CARD]), valid_card );
150 : }
151 : }
152 0 : break;
153 :
154 0 : default:
155 : {
156 0 : assert(false);
157 : }
158 : break;
159 : }
160 :
161 0 : U8_TRACE_END();
162 0 : }
163 :
164 0 : void gui_sketch_card_layouter_private_layout_to_grid ( gui_sketch_card_layouter_t *this_,
165 : shape_int_rectangle_t *bounds,
166 : uint_fast32_t max_card_height,
167 : gui_sketch_card_t io_cards[],
168 : uint_fast32_t cards_num,
169 : cairo_t *cr )
170 : {
171 0 : U8_TRACE_BEGIN();
172 0 : assert( NULL != cr );
173 0 : assert( NULL != bounds );
174 0 : assert( NULL != io_cards );
175 0 : assert( cards_num <= GUI_SKETCH_AREA_CONST_MAX_CARDS );
176 :
177 : /* fetch outer bounds */
178 0 : const uint_fast32_t width = shape_int_rectangle_get_width( bounds );
179 0 : const uint_fast32_t height = shape_int_rectangle_get_height( bounds );
180 0 : const int_fast32_t left = shape_int_rectangle_get_left( bounds );
181 0 : const int_fast32_t top = shape_int_rectangle_get_top( bounds );
182 :
183 : /* determine number of columns and rows for layout */
184 0 : uint_fast32_t cols = 0; /* initial value, overwritten if a card exists */
185 0 : uint_fast32_t rows = 0; /* initial value, overwritten if a card exists */
186 0 : uint_fast32_t card_width = 0; /* initial value, overwritten if a card exists */
187 0 : uint_fast32_t card_height = 0; /* initial value, overwritten if a card exists */
188 : {
189 0 : for ( uint_fast32_t probe_rows = 1; probe_rows <= cards_num; probe_rows ++ )
190 : {
191 0 : assert( probe_rows > 0 );
192 0 : uint_fast32_t probe_cols = (cards_num + probe_rows - 1) / probe_rows;
193 : shape_int_rectangle_t probe_bounds;
194 0 : shape_int_rectangle_init( &probe_bounds, 0, 0, ((width*2)/((probe_cols*2)+1)), height/probe_rows );
195 0 : shape_int_rectangle_shrink_by_border( &probe_bounds, BORDER );
196 0 : shape_int_rectangle_shrink_to_ratio( &probe_bounds, RATIO_WIDTH, RATIO_HEIGHT, SHAPE_H_ALIGN_LEFT, SHAPE_V_ALIGN_TOP );
197 0 : if ( card_height <= shape_int_rectangle_get_height( &probe_bounds ) )
198 : {
199 0 : cols = probe_cols;
200 0 : rows = probe_rows;
201 0 : card_width = shape_int_rectangle_get_width( &probe_bounds );
202 0 : card_height = shape_int_rectangle_get_height( &probe_bounds );
203 : }
204 : }
205 : }
206 :
207 : /* children shall not be bigger than the parent */
208 0 : if ( card_height > max_card_height )
209 : {
210 0 : assert( card_height > 0 );
211 0 : card_width = ( card_width * max_card_height ) / card_height;
212 0 : card_height = max_card_height;
213 : }
214 :
215 : /* layout cards to grid */
216 0 : for ( uint_fast32_t y = 0; y < rows; y ++ )
217 : {
218 0 : for ( uint_fast32_t x = 0; x < cols; x ++ )
219 : {
220 0 : uint_fast32_t card_idx = (y * cols) + x;
221 0 : if ( card_idx < cards_num )
222 : {
223 0 : assert( rows > 0 );
224 0 : const uint_fast32_t left_grid_gap = (cols==1) ? 0 : ((card_width*y)/(2*rows)); /* this gap is beautification only */
225 0 : const int_fast32_t rel_left = left_grid_gap + BORDER + (x * ( card_width + BORDER + BORDER ));
226 0 : const int_fast32_t rel_top = BORDER + (y * ( card_height + BORDER + BORDER ));
227 : shape_int_rectangle_t card_bounds;
228 0 : shape_int_rectangle_init( &card_bounds, left+rel_left, top+rel_top, card_width, card_height );
229 0 : shape_int_rectangle_trace( &card_bounds );
230 0 : gui_sketch_card_set_bounds( &(io_cards[card_idx]), card_bounds );
231 0 : const bool valid_card = gui_sketch_card_is_valid( &(io_cards[card_idx]) );
232 0 : gui_sketch_card_do_layout( &(io_cards[card_idx]), cr );
233 0 : gui_sketch_card_set_visible( &(io_cards[card_idx]), valid_card );
234 : }
235 : }
236 : }
237 :
238 0 : U8_TRACE_END();
239 0 : }
240 :
241 :
242 : /*
243 : Copyright 2019-2024 Andreas Warnke
244 :
245 : Licensed under the Apache License, Version 2.0 (the "License");
246 : you may not use this file except in compliance with the License.
247 : You may obtain a copy of the License at
248 :
249 : http://www.apache.org/licenses/LICENSE-2.0
250 :
251 : Unless required by applicable law or agreed to in writing, software
252 : distributed under the License is distributed on an "AS IS" BASIS,
253 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
254 : See the License for the specific language governing permissions and
255 : limitations under the License.
256 : */
257 :
|