libxputty 0.1
Loading...
Searching...
No Matches
xmultilistview_private.c
Go to the documentation of this file.
1/*
2 * 0BSD
3 *
4 * BSD Zero Clause License
5 *
6 * Copyright (c) 2019 Hermann Meyer
7 *
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted.
10
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 *
19 */
20
21
23#include "xtooltip.h"
24#include <sys/stat.h>
25#include <libgen.h>
26
27
28char* _utf8cpy(char* dst, const char* src, size_t sizeDest ) {
29 if( sizeDest ){
30 size_t sizeSrc = strlen(src);
31 while( sizeSrc >= sizeDest ){
32 const char* lastByte = src + sizeSrc;
33 while( lastByte-- > src )
34 if((*lastByte & 0xC0) != 0x80)
35 break;
36 sizeSrc = lastByte - src;
37 }
38 memcpy(dst, src, sizeSrc);
39 dst[sizeSrc] = '\0';
40 }
41 return dst;
42}
43
44void _draw_multi_listview(void *w_, void* user_data) {
45 Widget_t *w = (Widget_t*)w_;
46 if (!w) return;
48 cairo_paint (w->cr);
49}
50
51void _draw_multi_list(void *w_, void* user_data) {
52 Widget_t *w = (Widget_t*)w_;
53 Metrics_t metrics;
54 os_get_window_metrics(w, &metrics);
55 int width = metrics.width;
56 int height = metrics.height;
57 if (!metrics.visible) return;
59 if (!filelist->folder_scaled) return;
60
62 cairo_rectangle(w->crb, 0, 0, width, height);
63 cairo_fill (w->crb);
64 cairo_set_font_size (w->crb, w->app->normal_font * (0.5 +((filelist->scale_down/0.2)/2.0)));
65 cairo_text_extents_t extents;
66 cairo_text_extents_t fextents;
67 cairo_text_extents(w->crb,"Ay", &extents);
68 double h = extents.height/2.0;
69
70 int i = (int)max(0,adj_get_value(w->adj)*filelist->column);
71 int a = 0;
72 int j = filelist->list_size<filelist->show_items+i+filelist->column ?
73 filelist->list_size : filelist->show_items+i+filelist->column;
74 for(;i<j;i++) {
75 int k = 0;
76 for(;k<filelist->column;k++) {
77 if (filelist->check_dir) {
78 if (os_is_directory(filelist->list_names[i])) {
79 cairo_set_source_surface (w->crb, filelist->folder_scaled,
80 (filelist->icon_pos+(k*filelist->item_width)),
81 ((double)a+0.1)*filelist->item_height);
82 cairo_paint (w->crb);
83 } else {
84 cairo_set_source_surface (w->crb, filelist->file_scaled,
85 (filelist->icon_pos+(k*filelist->item_width)),
86 ((double)a+0.1)*filelist->item_height);
87 cairo_paint (w->crb);
88 }
89 }
90 int pos_y = (filelist->item_height*((double)a+1.0))+3.0 - h;
91 if (pos_y-h < height) {
93 if(i == filelist->prelight_item && i == filelist->active_item)
95 else if(i == filelist->prelight_item)
97 else if (i == filelist->active_item)
99 else
101
102 char label[124];
103 memset(label, '\0', sizeof(char)*124);
104 const char *ulabel = utf8_from_locale(basename(filelist->list_names[i]));
105 cairo_text_extents(w->crb, ulabel, &extents);
106 if (extents.width > filelist->item_width-10) {
107 int slen = strlen(ulabel);
108 int len = ((filelist->item_width-5)/(extents.width/slen));
109 _utf8cpy(label,ulabel, min(slen-4,len-3));
110 strcat(label,"...");
111 } else {
112 strcpy(label, ulabel);
113 }
114 free((void*)ulabel);
115 cairo_text_extents(w->crb, label, &fextents);
116 int pos_x = (k*filelist->item_width) + (filelist->item_width/2) - (fextents.width*0.5);
117 cairo_move_to (w->crb, pos_x, pos_y);
118 cairo_show_text(w->crb, label);
119 cairo_new_path (w->crb);
120 if (i == filelist->prelight_item && extents.width > (float)filelist->item_width-10) {
121 free(filelist->tooltip_text);
122 filelist->tooltip_text = NULL;
123 filelist->tooltip_text = utf8_from_locale(filelist->list_names[i]);
124 tooltip_set_text(w, filelist->tooltip_text);
125 w->flags |= HAS_TOOLTIP;
126 show_tooltip(w);
127 } else if (i == filelist->prelight_item && extents.width < (float)filelist->item_width-10){
128 w->flags &= ~HAS_TOOLTIP;
129 hide_tooltip(w);
130 }
131 }
132 if (k<filelist->column-1 && i<j-1) i++;
133 else break;
134 }
135 a++;
136 }
137}
138
139void _update_view(void *w_) {
140 Widget_t *w = (Widget_t*)w_;
141#ifdef __linux__
142 Metrics_t metrics;
143 os_get_window_metrics(w, &metrics);
144 int height = metrics.height-2;
145 if (!metrics.visible) return;
147 cairo_push_group (w->crb);
148 cairo_set_font_size (w->crb, w->app->normal_font * (0.5 +((filelist->scale_down/0.2)/2.0)));
149 cairo_text_extents_t extents;
150 cairo_text_extents_t fextents;
151 cairo_text_extents(w->crb,"Ay", &extents);
152 double h = extents.height/2.0;
153
154 int i = (int)max(0,adj_get_value(w->adj)*filelist->column);
155 int a = 0;
156 int j = filelist->list_size<filelist->show_items+i+filelist->column ?
157 filelist->list_size : filelist->show_items+i+filelist->column;
158 for(;i<j;i++) {
159 int k = 0;
160 for(;k<filelist->column;k++) {
161 if (i != filelist->prelight_item && i != filelist->prev_prelight_item) {
162 if (k<filelist->column-1 && i<j-1) i++;
163 continue;
164 }
166 cairo_rectangle(w->crb, k*filelist->item_width, a*filelist->item_height,
167 filelist->item_width, filelist->item_height);
168 cairo_fill(w->crb);
169 if (filelist->check_dir) {
170 struct stat sb;
171 if (stat(filelist->list_names[i], &sb) == 0 && S_ISDIR(sb.st_mode)) {
172 if (i == filelist->prelight_item) {
173 cairo_set_source_surface (w->crb, filelist->folder_select_scaled,
174 (filelist->icon_pos+(k*filelist->item_width)),
175 ((double)a+0.1)*filelist->item_height);
176 } else {
177 cairo_set_source_surface (w->crb, filelist->folder_scaled,
178 (filelist->icon_pos+(k*filelist->item_width)),
179 ((double)a+0.1)*filelist->item_height);
180 }
181 cairo_paint (w->crb);
182 } else {
183 cairo_set_source_surface (w->crb, filelist->file_scaled,
184 filelist->icon_pos+(k*filelist->item_width),
185 ((double)a+0.1)*filelist->item_height);
186 if (i == filelist->prelight_item)
187 cairo_set_operator (w->crb, CAIRO_OPERATOR_HARD_LIGHT);
188 cairo_paint (w->crb);
189 cairo_set_operator (w->crb, CAIRO_OPERATOR_OVER);
190 }
191 }
192 int pos_y = (filelist->item_height*((double)a+1.0))+3.0 - h;
193 if (pos_y-h < height) {
195 if(i == filelist->prelight_item && i == filelist->active_item)
197 else if(i == filelist->prelight_item)
199 else if (i == filelist->active_item)
201 else
203
204 char label[124];
205 memset(label, '\0', sizeof(char)*124);
206 cairo_text_extents(w->crb, basename(filelist->list_names[i]), &extents);
207 if (extents.width > filelist->item_width-10) {
208 int slen = strlen(basename(filelist->list_names[i]));
209 int len = ((filelist->item_width-5)/(extents.width/slen));
210 _utf8cpy(label,basename(filelist->list_names[i]), min(slen-4,len-3));
211 strcat(label,"...");
212 } else {
213 strcpy(label,basename(filelist->list_names[i]));
214 }
215
216 cairo_text_extents(w->crb, label, &fextents);
217 int pos_x = (k*filelist->item_width) + (filelist->item_width/2) - (fextents.width/2.0);
218 cairo_move_to (w->crb, pos_x, pos_y);
219 cairo_show_text(w->crb, label);
220 cairo_new_path (w->crb);
221 if (i == filelist->prelight_item && extents.width > (float)filelist->item_width-10) {
222 tooltip_set_text(w,filelist->list_names[i]);
223 w->flags |= HAS_TOOLTIP;
224 show_tooltip(w);
225 } else if (i == filelist->prelight_item && extents.width < (float)filelist->item_width-10){
226 w->flags &= ~HAS_TOOLTIP;
227 hide_tooltip(w);
228 }
229 }
230 if (k<filelist->column-1 && i<j-1) i++;
231 else break;
232 }
233 a++;
234 }
235 cairo_pop_group_to_source (w->crb);
236 cairo_paint (w->crb);
237 cairo_push_group (w->cr);
238 cairo_set_source_surface (w->cr, w->buffer,0,0);
239 cairo_paint (w->cr);
240
241 cairo_pop_group_to_source (w->cr);
242 cairo_paint (w->cr);
243#else
245#endif
246}
247
248void _multi_list_motion(void *w_, void* xmotion_, void* user_data) {
249 Widget_t *w = (Widget_t*)w_;
251 XMotionEvent *xmotion = (XMotionEvent*)xmotion_;
252 int prelight_item = ((xmotion->y/filelist->item_height)*filelist->column) +
253 (xmotion->x/filelist->item_width) + (int)max(0,adj_get_value(w->adj)*filelist->column);
254 if (xmotion->x > (filelist->column*filelist->item_width)-1) {
255 prelight_item = -1;
256 }
257 if(prelight_item != filelist->prelight_item) {
258 filelist->prev_prelight_item = filelist->prelight_item;
259 filelist->prelight_item = prelight_item;
260 hide_tooltip(w);
261 _update_view(w);
262 }
263}
264
265void _multi_list_key_pressed(void *w_, void* xkey_, void* user_data) {
266 Widget_t *w = (Widget_t*)w_;
267 Widget_t* listview = (Widget_t*) w->parent;
268 XKeyEvent *xkey = (XKeyEvent*)xkey_;
270 Metrics_t metrics;
271 os_get_window_metrics(w, &metrics);
272 int height = metrics.height;
273 int _items = height/(height/filelist->item_height);
274 filelist->prelight_item = xkey->y/_items + (int)max(0,adj_get_value(w->adj));
275 int nk = key_mapping(w->app->dpy, xkey);
276 if (nk) {
277 switch (nk) {
278 case 3:
279 case 4:
280 case 5:
281 case 6: filelist->prelight_item = xkey->y/_items + (int)max(0,adj_get_value(w->adj));
282 break;
283 default:
284 break;
285 }
286 }
287 listview->func.key_press_callback(listview, xkey_, user_data);
288}
289
290void _multi_list_entry_released(void *w_, void* button_, void* user_data) {
291 Widget_t *w = (Widget_t*)w_;
292 if (w->flags & HAS_POINTER) {
294 XButtonEvent *xbutton = (XButtonEvent*)button_;
295 Metrics_t metrics;
296 os_get_window_metrics(w, &metrics);
297 int height = metrics.height;
298 int _items = height/(height/filelist->item_height);
299 int prelight_item = xbutton->y/_items + (int)max(0,adj_get_value(w->adj));
300 if (prelight_item > filelist->list_size-1) return;
301 if(xbutton->button == Button4) {
302 if(prelight_item != filelist->prelight_item) {
303 filelist->prelight_item = prelight_item;
304 }
305 } else if (xbutton->button == Button5) {
306 if(prelight_item != filelist->prelight_item) {
307 filelist->prelight_item = prelight_item;
308 }
309 } else if(xbutton->button == Button1) {
310 Widget_t* listview = (Widget_t*) w->parent;
311 filelist->active_item = filelist->prelight_item;
312 adj_set_value(listview->adj,filelist->active_item);
313 listview->func.button_release_callback(listview,xbutton,user_data);
314 } else if(xbutton->button == Button3) {
315 Widget_t* listview = (Widget_t*) w->parent;
316 listview->func.button_release_callback(listview,xbutton,user_data);
317 }
318 }
319}
320
321void _multi_list_entry_double_clicked(void *w_, void* button_, void* user_data) {
322 Widget_t *w = (Widget_t*)w_;
323 Widget_t* listview = (Widget_t*) w->parent;
325 XButtonEvent *xbutton = (XButtonEvent*)button_;
326 Metrics_t metrics;
327 os_get_window_metrics(w, &metrics);
328 int width = metrics.width;
329 int height = metrics.height;
330 int h = floor(max(1,(height/filelist->item_height))) * filelist->item_height;
331 int x_items = max(1,width/filelist->column);
332 int _items = h/max(1,(height/filelist->item_height));
333 int prelight_item = ((xbutton->y/_items)*filelist->column) + (xbutton->x/x_items) + (int)max(0,adj_get_value(w->adj)*filelist->column);
334 if (prelight_item > filelist->list_size-1) return;
335 listview->func.double_click_callback(listview,button_,NULL);
336}
337
338void _leave_multi_list(void *w_, void* user_data) {
339 Widget_t *w = (Widget_t*)w_;
341 filelist->prelight_item = -1;
342 expose_widget(w);
343}
344
345void _reconfigure_multi_listview_viewport(void *w_, void* user_data) {
346 Widget_t *w = (Widget_t*)w_;
347 Widget_t* listview = (Widget_t*) w->parent;
349 Metrics_t metrics;
350 os_get_window_metrics(listview, &metrics);
351 int width = metrics.width;
352 int height = metrics.height;
353 float st = adj_get_value(filelist->slider->adj);
354 filelist->column = max(1,width/filelist->item_width);
355 filelist->show_items = (height/filelist->item_height) * filelist->column;
356 filelist->icon_pos = (filelist->item_width/2) - 120/filelist->scale_up;
357 w->adj->max_value = ((filelist->list_size-filelist->show_items)/filelist->column)+1.0;
358 filelist->slider->adj->max_value = ((filelist->list_size-filelist->show_items)/filelist->column)+1.0;
359 adj_set_scale(filelist->slider->adj, ((float)filelist->list_size/(float)filelist->show_items)/filelist->item_height);
360 adj_set_value(filelist->slider->adj,st);
361}
362
363void _set_multi_listview_viewpoint(void *w_, void* user_data) {
364 Widget_t *w = (Widget_t*)w_;
366 adj_set_state(filelist->slider->adj,adj_get_state(w->adj));
367 expose_widget(w);
368}
369
370void _draw_multi_listviewslider(void *w_, void* user_data) {
371 Widget_t *w = (Widget_t*)w_;
372 Widget_t* view_port = (Widget_t*)w->parent_struct;
373 ViewMultiList_t *filelist = (ViewMultiList_t*)view_port->parent_struct;
374 int v = (int)w->adj->max_value;
375 if (!v) return;
376 Metrics_t metrics;
377 os_get_window_metrics(w, &metrics);
378 int width = metrics.width;
379 int height = metrics.height;
380 if (!metrics.visible) return;
381 float slidersize = 1.0;
382 if (filelist->list_size > filelist->show_items)
383 slidersize = (float)((float)filelist->show_items/(float)filelist->list_size);
384 float sliderstate = adj_get_state(w->adj);
386 cairo_rectangle(w->crb, 0,0,width,height);
387 cairo_fill_preserve(w->crb);
389 cairo_fill(w->crb);
391 cairo_rectangle(w->crb, 0,((float)height-
392 ((float)height*slidersize))*sliderstate,width,((float)height*slidersize));
393 cairo_fill(w->crb);
394}
395
396void _set_multi_listviewport(void *w_, void* user_data) {
397 Widget_t *w = (Widget_t*)w_;
398 Widget_t *viewport = (Widget_t*)w->parent_struct;
399 adj_set_state(viewport->adj, adj_get_state(w->adj));
400 expose_widget(w);
401}
float max_value
Definition xadjustment.h:92
evfunc button_release_callback
Definition xwidget.h:101
evfunc key_press_callback
Definition xwidget.h:104
evfunc double_click_callback
Definition xwidget.h:102
Metrics_t - struct to receive window size, position & visibility Pass this struct to os_get_window_...
ViewMultiList_t - struct to hold information for the listview.
cairo_surface_t * folder_scaled
cairo_surface_t * folder_select_scaled
cairo_surface_t * file_scaled
Widget_t * slider
Widget_t - struct to hold the basic Widget_t info.
Definition xwidget.h:457
XColor_t * color_scheme
Definition xwidget.h:467
Adjustment_t * adj
Definition xwidget.h:497
void * parent
Definition xwidget.h:471
cairo_surface_t * buffer
Definition xwidget.h:487
cairo_t * crb
Definition xwidget.h:489
long long flags
Definition xwidget.h:461
cairo_t * cr
Definition xwidget.h:485
void * parent_struct
Definition xwidget.h:473
Func_t func
Definition xwidget.h:481
Xputty * app
Definition xwidget.h:465
Colors normal
Definition xcolor.h:106
Colors active
Definition xcolor.h:109
int button
int normal_font
Definition xputty.h:248
Display * dpy
Definition xputty.h:232
void adj_set_state(Adjustment_t *adj, float state)
adj_set_state - set the current state of the Adjustment_t
void adj_set_value(Adjustment_t *adj, float value)
adj_set_value - set the current value to the Adjustment_t
float adj_get_value(Adjustment_t *adj)
adj_get_value - get the current value of the Adjustment_t
float adj_get_state(Adjustment_t *adj)
adj_get_state - get the current state of the Adjustment_t
void adj_set_scale(Adjustment_t *adj, float value)
adj_set_scale - internal use to scale the pointer movement (0.1 -1.0)
Color_state get_color_state(Widget_t *wid)
get_color_state - get the Color_state to use in relation to the Widget_t state
Definition xcolor.c:222
void use_text_color_scheme(Widget_t *w, Color_state st)
use_text_color_scheme - use text Colors to paint on Widget_t
Definition xcolor.c:266
@ BACKGROUND_
Definition xcolor.h:65
void use_bg_color_scheme(Widget_t *w, Color_state st)
use_bg_color_scheme - use background Colors to paint on Widget_t
Definition xcolor.c:252
void set_pattern(Widget_t *w, Colors *from, Colors *to, Color_mod mod)
set_pattern - set pattern for the selected Colors
Definition xcolor.c:308
void use_shadow_color_scheme(Widget_t *w, Color_state st)
use_shadow_color_scheme - use shadow Colors to paint on Widget_t
Definition xcolor.c:273
void use_base_color_scheme(Widget_t *w, Color_state st)
use_base_color_scheme - use base Colors to paint on Widget_t
Definition xcolor.c:259
@ NORMAL_
Definition xcolor.h:44
@ INSENSITIVE_
Definition xcolor.h:48
@ SELECTED_
Definition xcolor.h:46
@ PRELIGHT_
Definition xcolor.h:45
@ ACTIVE_
Definition xcolor.h:47
void _multi_list_motion(void *w_, void *xmotion_, void *user_data)
_multi_list_motion - follow mouse pointer to set prelight item
void _multi_list_entry_released(void *w_, void *button_, void *user_data)
_multi_list_entry_released - move listview or set active entry
void _update_view(void *w_)
void _multi_list_entry_double_clicked(void *w_, void *button_, void *user_data)
_multi_list_entry_double_clicke - forward double click from list entry to list view
void _multi_list_key_pressed(void *w_, void *xkey_, void *user_data)
_multi_list_key_pressed - move listview or set active entry
void _draw_multi_listviewslider(void *w_, void *user_data)
_draw_multi_listviewslider - draw a slider on the viewport to indicate the view point
void _leave_multi_list(void *w_, void *user_data)
_leave_multi_list - draw list on pointer leave
void _draw_multi_listview(void *w_, void *user_data)
_draw_multi_listview - draw listview on expose call
void _reconfigure_multi_listview_viewport(void *w_, void *user_data)
_reconfigure_multi_listview_viewport - reconfigure the viewport adjustment on size changes
char * _utf8cpy(char *dst, const char *src, size_t sizeDest)
void _set_multi_listview_viewpoint(void *w_, void *user_data)
_set_multi_listview_viewpoint - move the view_port to position
void _draw_multi_list(void *w_, void *user_data)
_draw_multi_list - draw list on expose call
void _set_multi_listviewport(void *w_, void *user_data)
_set_multi_listviewport - move the view_port to position by listviewslider state
void tooltip_set_text(Widget_t *w, const char *label)
tooltip_set_text - set a (new) text to a tooltip for Widget_t
Definition xtooltip.c:25
void os_get_window_metrics(Widget_t *w, Metrics_t *metrics)
os_get_window_metrics - Get the Merics_t struct related to a Widget_t
char * utf8_from_locale(char *localestr)
utf8_from_locale - convert active codepage to utf8 must be freed by the caller
bool os_is_directory(const char *filename)
os_is directory - check if a given path is a directory or a file
void os_expose_widget(Widget_t *w)
os_expose_widget - Draw the the back buffer to the Widget_t surface
int key_mapping(Display *dpy, XKeyEvent *xkey)
_key_mapping - modifier key's mapped to a integer value
Definition xwidget.c:37
void expose_widget(Widget_t *w)
expose_widgets - send a expose event (EXPOSE) to a Widget_t
Definition xwidget.c:445
void show_tooltip(Widget_t *wid)
show_tooltip - check if a Widget_t have a tooltip, and show it, if a tooltip is available.
Definition xwidget.c:419
@ HAS_POINTER
Definition xwidget.h:402
@ HAS_TOOLTIP
Definition xwidget.h:404
void hide_tooltip(Widget_t *wid)
hide_tooltip - check if a Widget_t have a tooltip, and hide it, if a tooltip is mapped.
Definition xwidget.c:430