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
22 #include "xlistview_private.h"
23 #include "xtooltip.h"
24 #include <sys/stat.h>
25
26
_draw_listview(void * w_,void * user_data)27 void _draw_listview(void *w_, void* user_data) {
28 Widget_t *w = (Widget_t*)w_;
29 if (!w) return;
30 set_pattern(w,&w->app->color_scheme->normal,&w->app->color_scheme->active,BACKGROUND_);
31 cairo_paint (w->cr);
32 }
33
_draw_list(void * w_,void * user_data)34 void _draw_list(void *w_, void* user_data) {
35 Widget_t *w = (Widget_t*)w_;
36 XWindowAttributes attrs;
37 XGetWindowAttributes(w->app->dpy, (Window)w->widget, &attrs);
38 if (attrs.map_state != IsViewable) return;
39 int width = attrs.width;
40 int height = attrs.height;
41 ViewList_t *filelist = (ViewList_t*)w->parent_struct;
42
43 use_base_color_scheme(w, NORMAL_);
44 cairo_rectangle(w->crb, 0, 0, width, height);
45 cairo_fill (w->crb);
46 cairo_set_font_size (w->crb, min(w->app->big_font ,w->app->normal_font/w->scale.ascale));
47 cairo_text_extents_t extents;
48 cairo_text_extents(w->crb,"Ay", &extents);
49 double h = extents.height;
50
51 int i = (int)max(0,adj_get_value(w->adj));
52 int a = 0;
53 int j = filelist->list_size<filelist->show_items+i+1 ?
54 filelist->list_size : filelist->show_items+i+1;
55 for(;i<j;i++) {
56 if(i == filelist->prelight_item && i == filelist->active_item)
57 use_base_color_scheme(w, ACTIVE_);
58 else if(i == filelist->prelight_item)
59 use_base_color_scheme(w, PRELIGHT_);
60 else if (i == filelist->active_item)
61 use_base_color_scheme(w, SELECTED_);
62 else
63 use_base_color_scheme(w,NORMAL_ );
64 cairo_rectangle(w->crb, 0, a*25, width, 25);
65 cairo_fill_preserve(w->crb);
66 cairo_set_line_width(w->crb, 1.0);
67 use_frame_color_scheme(w, PRELIGHT_);
68 cairo_stroke(w->crb);
69
70 /** show label **/
71 if(i == filelist->prelight_item && i == filelist->active_item)
72 use_text_color_scheme(w, ACTIVE_);
73 else if(i == filelist->prelight_item)
74 use_text_color_scheme(w, PRELIGHT_);
75 else if (i == filelist->active_item)
76 use_text_color_scheme(w, SELECTED_);
77 else
78 use_text_color_scheme(w,NORMAL_ );
79
80 if (filelist->check_dir) {
81 struct stat sb;
82 if (stat(filelist->list_names[i], &sb) == 0 && S_ISDIR(sb.st_mode)) {
83 cairo_scale(w->crb,0.08, 0.08);
84 cairo_set_source_surface (w->crb, filelist->folder,1.0*12.5,((double)a+0.1)*25.0*12.5);
85 cairo_paint (w->crb);
86 cairo_scale(w->crb,12.5, 12.5);
87 use_text_color_scheme(w, INSENSITIVE_);
88 } else {
89 cairo_scale(w->crb,0.08, 0.08);
90 cairo_set_source_surface (w->crb, filelist->file,1.0*12.5,((double)a+0.1)*25.0*12.5);
91 cairo_paint (w->crb);
92 cairo_scale(w->crb,12.5, 12.5);
93 use_text_color_scheme(w,NORMAL_ );
94 }
95 }
96 cairo_text_extents(w->crb,filelist->list_names[i] , &extents);
97
98 cairo_move_to (w->crb, 20, (25.0*((double)a+1.0))+3.0 - (h*max(0.71,w->scale.ascale)));
99 cairo_show_text(w->crb, filelist->list_names[i]);
100 cairo_new_path (w->crb);
101 if (i == filelist->prelight_item && extents.width > (float)width-20) {
102 tooltip_set_text(w,filelist->list_names[i]);
103 w->flags |= HAS_TOOLTIP;
104 show_tooltip(w);
105 } else if (i == filelist->prelight_item && extents.width < (float)width-20){
106 w->flags &= ~HAS_TOOLTIP;
107 hide_tooltip(w);
108 }
109 a++;
110 }
111 }
112
_update_list_view(void * w_)113 void _update_list_view(void *w_) {
114 Widget_t *w = (Widget_t*)w_;
115 XWindowAttributes attrs;
116 XGetWindowAttributes(w->app->dpy, (Window)w->widget, &attrs);
117 if (attrs.map_state != IsViewable) return;
118 int width = attrs.width;
119 ViewList_t *filelist = (ViewList_t*)w->parent_struct;
120
121 cairo_push_group (w->crb);
122 use_base_color_scheme(w, NORMAL_);
123 cairo_set_font_size (w->crb, min(w->app->big_font ,w->app->normal_font/w->scale.ascale));
124 cairo_text_extents_t extents;
125 cairo_text_extents(w->crb,"Ay", &extents);
126 double h = extents.height;
127
128 int i = (int)max(0,adj_get_value(w->adj));
129 int a = 0;
130 int j = filelist->list_size<filelist->show_items+i+1 ?
131 filelist->list_size : filelist->show_items+i+1;
132 for(;i<j;i++) {
133 if (i != filelist->prelight_item && i != filelist->prev_prelight_item) {
134 if (i<j-1) {
135 a++;
136 }
137 continue;
138 }
139 if(i == filelist->prelight_item && i == filelist->active_item)
140 use_base_color_scheme(w, ACTIVE_);
141 else if(i == filelist->prelight_item)
142 use_base_color_scheme(w, PRELIGHT_);
143 else if (i == filelist->active_item)
144 use_base_color_scheme(w, SELECTED_);
145 else
146 use_base_color_scheme(w,NORMAL_ );
147 cairo_rectangle(w->crb, 0, a*25, width, 25);
148 cairo_fill_preserve(w->crb);
149 cairo_set_line_width(w->crb, 1.0);
150 use_frame_color_scheme(w, PRELIGHT_);
151 cairo_stroke(w->crb);
152
153 /** show label **/
154 if(i == filelist->prelight_item && i == filelist->active_item)
155 use_text_color_scheme(w, ACTIVE_);
156 else if(i == filelist->prelight_item)
157 use_text_color_scheme(w, PRELIGHT_);
158 else if (i == filelist->active_item)
159 use_text_color_scheme(w, SELECTED_);
160 else
161 use_text_color_scheme(w,NORMAL_ );
162
163 if (filelist->check_dir) {
164 struct stat sb;
165 if (stat(filelist->list_names[i], &sb) == 0 && S_ISDIR(sb.st_mode)) {
166 cairo_scale(w->crb,0.08, 0.08);
167 cairo_set_source_surface (w->crb, filelist->folder,1.0*12.5,((double)a+0.1)*25.0*12.5);
168 cairo_paint (w->crb);
169 cairo_scale(w->crb,12.5, 12.5);
170 use_text_color_scheme(w, INSENSITIVE_);
171 } else {
172 cairo_scale(w->crb,0.08, 0.08);
173 cairo_set_source_surface (w->crb, filelist->file,1.0*12.5,((double)a+0.1)*25.0*12.5);
174 cairo_paint (w->crb);
175 cairo_scale(w->crb,12.5, 12.5);
176 use_text_color_scheme(w,NORMAL_ );
177 }
178 }
179 cairo_text_extents(w->crb,filelist->list_names[i] , &extents);
180
181 cairo_move_to (w->crb, 20, (25.0*((double)a+1.0))+3.0 - (h*max(0.71,w->scale.ascale)));
182 cairo_show_text(w->crb, filelist->list_names[i]);
183 cairo_new_path (w->crb);
184 if (i == filelist->prelight_item && extents.width > (float)width-20) {
185 tooltip_set_text(w,filelist->list_names[i]);
186 w->flags |= HAS_TOOLTIP;
187 show_tooltip(w);
188 } else if (i == filelist->prelight_item && extents.width < (float)width-20){
189 w->flags &= ~HAS_TOOLTIP;
190 hide_tooltip(w);
191 }
192 a++;
193 }
194 cairo_pop_group_to_source (w->crb);
195 cairo_paint (w->crb);
196 cairo_push_group (w->cr);
197 cairo_set_source_surface (w->cr, w->buffer,0,0);
198 cairo_paint (w->cr);
199
200 cairo_pop_group_to_source (w->cr);
201 cairo_paint (w->cr);
202 }
203
_list_motion(void * w_,void * xmotion_,void * user_data)204 void _list_motion(void *w_, void* xmotion_, void* user_data) {
205 Widget_t *w = (Widget_t*)w_;
206 ViewList_t *filelist = (ViewList_t*)w->parent_struct;
207 XMotionEvent *xmotion = (XMotionEvent*)xmotion_;
208 XWindowAttributes attrs;
209 XGetWindowAttributes(w->app->dpy, (Window)w->widget, &attrs);
210 int height = attrs.height;
211 int _items = height/(height/25);
212 int prelight_item = (xmotion->y/_items) + (int)max(0,adj_get_value(w->adj));
213 if(prelight_item != filelist->prelight_item) {
214 filelist->prev_prelight_item = filelist->prelight_item;
215 filelist->prelight_item = prelight_item;
216 hide_tooltip(w);
217 _update_list_view(w);
218 }
219 }
220
_list_key_pressed(void * w_,void * xkey_,void * user_data)221 void _list_key_pressed(void *w_, void* xkey_, void* user_data) {
222 Widget_t *w = (Widget_t*)w_;
223 Widget_t* listview = (Widget_t*) w->parent;
224 XKeyEvent *xkey = (XKeyEvent*)xkey_;
225 ViewList_t *filelist = (ViewList_t*)w->parent_struct;
226 XWindowAttributes attrs;
227 XGetWindowAttributes(w->app->dpy, (Window)w->widget, &attrs);
228 int height = attrs.height;
229 int _items = height/(height/25);
230 filelist->prelight_item = xkey->y/_items + (int)max(0,adj_get_value(w->adj));
231 int nk = key_mapping(w->app->dpy, xkey);
232 if (nk) {
233 switch (nk) {
234 case 3:
235 case 4:
236 case 5:
237 case 6: filelist->prelight_item = xkey->y/_items + (int)max(0,adj_get_value(w->adj));
238 break;
239 default:
240 break;
241 }
242 }
243 listview->func.key_press_callback(listview, xkey_, user_data);
244 }
245
_list_entry_released(void * w_,void * button_,void * user_data)246 void _list_entry_released(void *w_, void* button_, void* user_data) {
247 Widget_t *w = (Widget_t*)w_;
248 if (w->flags & HAS_POINTER) {
249 ViewList_t *filelist = (ViewList_t*)w->parent_struct;
250 XButtonEvent *xbutton = (XButtonEvent*)button_;
251 XWindowAttributes attrs;
252 XGetWindowAttributes(w->app->dpy, (Window)w->widget, &attrs);
253 int height = attrs.height;
254 int _items = height/(height/25);
255 int prelight_item = xbutton->y/_items + (int)max(0,adj_get_value(w->adj));
256 if (prelight_item > filelist->list_size-1) return;
257 if(xbutton->button == Button4) {
258 if(prelight_item != filelist->prelight_item) {
259 filelist->prelight_item = prelight_item;
260 }
261 } else if (xbutton->button == Button5) {
262 if(prelight_item != filelist->prelight_item) {
263 filelist->prelight_item = prelight_item;
264 }
265 } else if(xbutton->button == Button1) {
266 Widget_t* listview = (Widget_t*) w->parent;
267 filelist->active_item = filelist->prelight_item;
268 adj_set_value(listview->adj,filelist->active_item);
269 listview->func.button_release_callback(listview,xbutton,user_data);
270 }
271 }
272 }
273
_list_entry_double_clicked(void * w_,void * button_,void * user_data)274 void _list_entry_double_clicked(void *w_, void* button_, void* user_data) {
275 Widget_t *w = (Widget_t*)w_;
276 Widget_t* listview = (Widget_t*) w->parent;
277 ViewList_t *filelist = (ViewList_t*)w->parent_struct;
278 XButtonEvent *xbutton = (XButtonEvent*)button_;
279 XWindowAttributes attrs;
280 XGetWindowAttributes(w->app->dpy, (Window)w->widget, &attrs);
281 int height = attrs.height;
282 int _items = height/(height/25);
283 int prelight_item = xbutton->y/_items + (int)max(0,adj_get_value(w->adj));
284 if (prelight_item > filelist->list_size-1) return;
285 listview->func.double_click_callback(listview,button_,NULL);
286 }
287
_leave_list(void * w_,void * user_data)288 void _leave_list(void *w_, void* user_data) {
289 Widget_t *w = (Widget_t*)w_;
290 ViewList_t *filelist = (ViewList_t*)w->parent_struct;
291 filelist->prelight_item = -1;
292 expose_widget(w);
293 }
294
_reconfigure_listview_viewport(void * w_,void * user_data)295 void _reconfigure_listview_viewport(void *w_, void* user_data) {
296 Widget_t *w = (Widget_t*)w_;
297 float st = adj_get_state(w->adj);
298 Widget_t* listview = (Widget_t*) w->parent;
299 ViewList_t *filelist = (ViewList_t*)w->parent_struct;
300 XWindowAttributes attrs;
301 XGetWindowAttributes(listview->app->dpy, (Window)listview->widget, &attrs);
302 int height = attrs.height;
303 filelist->show_items = height/25;
304 w->adj->max_value = filelist->list_size-filelist->show_items;
305 adj_set_state(w->adj,st);
306 }
307
_configure_listview(void * w_,void * user_data)308 void _configure_listview(void *w_, void* user_data) {
309 Widget_t *w = (Widget_t*)w_;
310 Widget_t* listview = (Widget_t*) w->parent;
311 ViewList_t *filelist = (ViewList_t*)w->parent_struct;
312 XWindowAttributes attrs;
313 XGetWindowAttributes(listview->app->dpy, (Window)listview->widget, &attrs);
314 int width = attrs.width;
315 int height = attrs.height;
316 filelist->show_items = height/25;
317 filelist->slider->adj->step = max(0.0,1.0/(filelist->list_size-filelist->show_items));
318 adj_set_scale(filelist->slider->adj, ((float)filelist->list_size/(float)filelist->show_items)/25.0);
319 XResizeWindow (w->app->dpy, w->widget, width, height);
320 }
321
_set_listview_viewpoint(void * w_,void * user_data)322 void _set_listview_viewpoint(void *w_, void* user_data) {
323 Widget_t *w = (Widget_t*)w_;
324 ViewList_t *filelist = (ViewList_t*)w->parent_struct;
325 adj_set_state(filelist->slider->adj,adj_get_state(w->adj));
326 expose_widget(w);
327 }
328
_draw_listviewslider(void * w_,void * user_data)329 void _draw_listviewslider(void *w_, void* user_data) {
330 Widget_t *w = (Widget_t*)w_;
331 Widget_t* view_port = (Widget_t*)w->parent_struct;
332 ViewList_t *filelist = (ViewList_t*)view_port->parent_struct;
333 int v = (int)w->adj->max_value;
334 if (!v) return;
335 XWindowAttributes attrs;
336 XGetWindowAttributes(w->app->dpy, (Window)w->widget, &attrs);
337 if (attrs.map_state != IsViewable) return;
338 int width = attrs.width;
339 int height = attrs.height;
340 int show_items = height/25;
341 float slidersize = 1.0;
342 if (filelist->list_size > show_items)
343 slidersize = (float)((float)show_items/(float)filelist->list_size);
344 float sliderstate = adj_get_state(w->adj);
345 use_bg_color_scheme(w, get_color_state(w));
346 cairo_rectangle(w->crb, 0,0,width,height);
347 cairo_fill_preserve(w->crb);
348 use_shadow_color_scheme(w, NORMAL_);
349 cairo_fill(w->crb);
350 use_bg_color_scheme(w, NORMAL_);
351 cairo_rectangle(w->crb, 0,((float)height-
352 ((float)height*slidersize))*sliderstate,width,((float)height*slidersize));
353 cairo_fill(w->crb);
354 }
355
_set_listviewport(void * w_,void * user_data)356 void _set_listviewport(void *w_, void* user_data) {
357 Widget_t *w = (Widget_t*)w_;
358 Widget_t *viewport = (Widget_t*)w->parent_struct;
359 adj_set_state(viewport->adj, adj_get_state(w->adj));
360 expose_widget(w);
361 }
362