rofi  1.5.4
listview.c
Go to the documentation of this file.
1 /*
2  * rofi
3  *
4  * MIT/X11 License
5  * Copyright © 2013-2017 Qball Cow <qball@gmpclient.org>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining
8  * a copy of this software and associated documentation files (the
9  * "Software"), to deal in the Software without restriction, including
10  * without limitation the rights to use, copy, modify, merge, publish,
11  * distribute, sublicense, and/or sell copies of the Software, and to
12  * permit persons to whom the Software is furnished to do so, subject to
13  * the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  *
26  */
27 
28 #include <config.h>
29 #include <glib.h>
30 #include <widgets/widget.h>
31 #include <widgets/textbox.h>
32 #include <widgets/listview.h>
33 #include <widgets/scrollbar.h>
34 
35 #include "settings.h"
36 #include "theme.h"
37 
39 #define DEFAULT_SPACING 2
40 
44 typedef enum
45 {
50 } ViewType;
51 
55 typedef enum
56 {
58  RIGHT_TO_LEFT = 1
60 
61 struct _listview
62 {
64 
66 
67  // RChanged
68  // Text needs to be repainted.
69  unsigned int rchanged;
70  // Administration
71 
72  unsigned int cur_page;
73  unsigned int last_offset;
74  unsigned int selected;
75 
76  unsigned int element_height;
77  unsigned int max_rows;
78  unsigned int max_elements;
79 
80  //
81  unsigned int cur_columns;
82  unsigned int req_elements;
83  unsigned int cur_elements;
84 
86  unsigned int menu_lines;
87  unsigned int max_displayed_lines;
88  unsigned int menu_columns;
89  unsigned int fixed_num_lines;
90  unsigned int dynamic;
91  unsigned int eh;
92  unsigned int reverse;
93  gboolean cycle;
94  gboolean multi_select;
95 
97 
100 
102  void *udata;
103 
105 
106  xcb_timestamp_t last_click;
109 
111 
112 
113  PangoEllipsizeMode emode;
115  struct
116  {
118  unsigned int cur_visible;
120 };
121 
122 static int listview_get_desired_height ( widget *wid );
123 
124 static void listview_free ( widget *wid )
125 {
126  listview *lv = (listview *) wid;
127  for ( unsigned int i = 0; i < lv->cur_elements; i++ ) {
128  widget_free ( WIDGET ( lv->boxes [i] ) );
129  }
130  g_free ( lv->boxes );
131 
132  g_free ( lv->listview_name );
133  widget_free ( WIDGET ( lv->scrollbar ) );
134  g_free ( lv );
135 }
136 static unsigned int scroll_per_page_barview ( listview *lv )
137 {
138  unsigned int offset = lv->last_offset;
139 
140  // selected row is always visible.
141  // If selected is visible do not scroll.
142  if ( lv->selected < lv->last_offset ) {
143  offset = lv->selected;
144  lv->rchanged = TRUE;
145  }
146  else if ( lv->selected >= ( lv->last_offset + lv->barview.cur_visible ) ) {
147  offset = lv->selected;
148  lv->rchanged = TRUE;
149  }
150  return offset;
151 }
152 static unsigned int scroll_per_page ( listview * lv )
153 {
154  int offset = 0;
155 
156  // selected row is always visible.
157  // If selected is visible do not scroll.
158  if ( ( ( lv->selected - ( lv->last_offset ) ) < ( lv->max_elements ) ) && ( lv->selected >= ( lv->last_offset ) ) ) {
159  offset = lv->last_offset;
160  }
161  else{
162  // Do paginating
163  unsigned int page = ( lv->max_elements > 0 ) ? ( lv->selected / lv->max_elements ) : 0;
164  offset = page * lv->max_elements;
165  if ( page != lv->cur_page ) {
166  lv->cur_page = page;
167  lv->rchanged = TRUE;
168  }
169  // Set the position
170  //scrollbar_set_handle ( lv->scrollbar, page * lv->max_elements );
171  }
172  return offset;
173 }
174 
175 static unsigned int scroll_continious ( listview *lv )
176 {
177  unsigned int middle = ( lv->max_rows - ( ( lv->max_rows & 1 ) == 0 ) ) / 2;
178  unsigned int offset = 0;
179  if ( lv->selected > middle ) {
180  if ( lv->selected < ( lv->req_elements - ( lv->max_rows - middle ) ) ) {
181  offset = lv->selected - middle;
182  }
183  // Don't go below zero.
184  else if ( lv->req_elements > lv->max_rows ) {
185  offset = lv->req_elements - lv->max_rows;
186  }
187  }
188  if ( offset != lv->cur_page ) {
189  //scrollbar_set_handle ( lv->scrollbar, offset );
190  lv->cur_page = offset;
191  lv->rchanged = TRUE;
192  }
193  return offset;
194 }
195 
196 static void update_element ( listview *lv, unsigned int tb, unsigned int index, gboolean full )
197 {
198  // Select drawing mode
199  TextBoxFontType type = ( index & 1 ) == 0 ? NORMAL : ALT;
200  type = ( index ) == lv->selected ? HIGHLIGHT : type;
201 
202  if ( lv->callback ) {
203  lv->callback ( lv->boxes[tb], index, lv->udata, type, full );
204  }
205 }
206 
207 static void barview_draw ( widget *wid, cairo_t *draw )
208 {
209  unsigned int offset = 0;
210  listview *lv = (listview *) wid;
211  offset = scroll_per_page_barview ( lv );
212  lv->last_offset = offset;
213  int spacing_hori = distance_get_pixel ( lv->spacing, ROFI_ORIENTATION_HORIZONTAL );
214 
215  int left_offset = widget_padding_get_left ( wid );
216  int right_offset = lv->widget.w - widget_padding_get_right ( wid );
217  int top_offset = widget_padding_get_top ( wid );
218  if ( lv->cur_elements > 0 ) {
219  // Set new x/y position.
220  unsigned int max = MIN ( lv->cur_elements, lv->req_elements - offset );
221  if ( lv->rchanged ) {
222  int first = TRUE;
223  int width = lv->widget.w;
224  lv->barview.cur_visible = 0;
225  width -= widget_padding_get_padding_width ( wid );
226  if ( lv->barview.direction == LEFT_TO_RIGHT ) {
227  for ( unsigned int i = 0; i < max && width > 0; i++ ) {
228  update_element ( lv, i, i + offset, TRUE );
229  int twidth = textbox_get_desired_width ( WIDGET ( lv->boxes[i] ) );
230  if ( twidth >= width ) {
231  if ( !first ) {
232  break;
233  }
234  twidth = width;
235  }
236  textbox_moveresize ( lv->boxes[i], left_offset, top_offset, twidth, lv->element_height );
237 
238  widget_draw ( WIDGET ( lv->boxes[i] ), draw );
239  width -= twidth + spacing_hori;
240  left_offset += twidth + spacing_hori;
241  first = FALSE;
242  lv->barview.cur_visible++;
243  }
244  }
245  else {
246  for ( unsigned int i = 0; i < lv->cur_elements && width > 0 && i <= offset; i++ ) {
247  update_element ( lv, i, offset - i, TRUE );
248  int twidth = textbox_get_desired_width ( WIDGET ( lv->boxes[i] ) );
249  if ( twidth >= width ) {
250  if ( !first ) {
251  break;
252  }
253  twidth = width;
254  }
255  right_offset -= twidth;
256  textbox_moveresize ( lv->boxes[i], right_offset, top_offset, twidth, lv->element_height );
257 
258  widget_draw ( WIDGET ( lv->boxes[i] ), draw );
259  width -= twidth + spacing_hori;
260  right_offset -= spacing_hori;
261  first = FALSE;
262  lv->barview.cur_visible++;
263  }
264  offset -= lv->barview.cur_visible - 1;
265  lv->last_offset = offset;
266  for ( unsigned int i = 0; i < ( lv->barview.cur_visible / 2 ); i++ ) {
267  void * temp = lv->boxes[i];
268  int sw = lv->barview.cur_visible - i - 1;
269  lv->boxes[i] = lv->boxes[sw];
270  lv->boxes[sw] = temp;
271  }
272  }
273  lv->rchanged = FALSE;
274  }
275  else {
276  for ( unsigned int i = 0; i < lv->barview.cur_visible; i++ ) {
277  update_element ( lv, i, i + offset, FALSE );
278  widget_draw ( WIDGET ( lv->boxes[i] ), draw );
279  }
280  }
281  }
282 }
283 
284 static void listview_draw ( widget *wid, cairo_t *draw )
285 {
286  unsigned int offset = 0;
287  listview *lv = (listview *) wid;
289  offset = scroll_continious ( lv );
290  }
291  else {
292  offset = scroll_per_page ( lv );
293  }
294  // Set these all together to make sure they update consistently.
297  if ( lv->reverse ) {
298  scrollbar_set_handle ( lv->scrollbar, lv->req_elements - lv->selected - 1 );
299  }
300  else {
302  }
303  lv->last_offset = offset;
304  int spacing_vert = distance_get_pixel ( lv->spacing, ROFI_ORIENTATION_VERTICAL );
305  int spacing_hori = distance_get_pixel ( lv->spacing, ROFI_ORIENTATION_HORIZONTAL );
306 
307  int left_offset = widget_padding_get_left ( wid );
308  int top_offset = widget_padding_get_top ( wid );
309  /*
310  if ( lv->scrollbar->widget.index == 0 ) {
311  left_offset += spacing_hori + lv->scrollbar->widget.w;
312  }
313  */
314  if ( lv->cur_elements > 0 && lv->max_rows > 0 ) {
315  // Set new x/y position.
316  unsigned int max = MIN ( lv->cur_elements, lv->req_elements - offset );
317  if ( lv->rchanged ) {
318  unsigned int width = lv->widget.w - spacing_hori * ( lv->cur_columns - 1 );
319  width -= widget_padding_get_padding_width ( wid );
320  if ( widget_enabled ( WIDGET ( lv->scrollbar ) ) ) {
321  width -= spacing_hori;
322  width -= widget_get_width ( WIDGET ( lv->scrollbar ) );
323  }
324  unsigned int element_width = ( width ) / lv->cur_columns;
325  for ( unsigned int i = 0; i < max; i++ ) {
326  unsigned int ex = left_offset + ( ( i ) / lv->max_rows ) * ( element_width + spacing_hori );
327  if ( lv->reverse ) {
328  unsigned int ey = wid->h - ( widget_padding_get_bottom ( wid ) + ( ( i ) % lv->max_rows ) * ( lv->element_height + spacing_vert ) ) - lv->element_height;
329  textbox_moveresize ( lv->boxes[i], ex, ey, element_width, lv->element_height );
330  }
331  else {
332  unsigned int ey = top_offset + ( ( i ) % lv->max_rows ) * ( lv->element_height + spacing_vert );
333  textbox_moveresize ( lv->boxes[i], ex, ey, element_width, lv->element_height );
334  }
335 
336  update_element ( lv, i, i + offset, TRUE );
337  widget_draw ( WIDGET ( lv->boxes[i] ), draw );
338  }
339  lv->rchanged = FALSE;
340  }
341  else {
342  for ( unsigned int i = 0; i < max; i++ ) {
343  update_element ( lv, i, i + offset, FALSE );
344  widget_draw ( WIDGET ( lv->boxes[i] ), draw );
345  }
346  }
347  }
348  widget_draw ( WIDGET ( lv->scrollbar ), draw );
349 }
351 
352 static void _listview_draw ( widget *wid, cairo_t *draw )
353 {
354  listview *lv = (listview *) wid;
355  if ( lv->type == LISTVIEW ) {
356  listview_draw ( wid, draw );
357  }
358  else {
359  barview_draw ( wid, draw );
360  }
361 }
363 {
364  unsigned int newne = 0;
365  if ( lv->max_rows == 0 ) {
366  return;
367  }
368  if ( lv->req_elements < lv->max_elements ) {
369  newne = lv->req_elements;
370  lv->cur_columns = ( lv->req_elements + ( lv->max_rows - 1 ) ) / lv->max_rows;
371  }
372  else {
373  newne = lv->max_elements;
374  lv->cur_columns = lv->menu_columns;
375  }
376  for ( unsigned int i = newne; i < lv->cur_elements; i++ ) {
377  widget_free ( WIDGET ( lv->boxes[i] ) );
378  }
379  lv->boxes = g_realloc ( lv->boxes, newne * sizeof ( textbox* ) );
380  if ( newne > 0 ) {
381  for ( unsigned int i = lv->cur_elements; i < newne; i++ ) {
383  flags |= ( ( config.show_icons ) ? TB_ICON : 0 );
384  lv->boxes[i] = textbox_create ( WIDGET ( lv ), WIDGET_TYPE_LISTVIEW_ELEMENT, "element", flags, NORMAL, "", 0, 0 );
386  }
387  }
388  lv->rchanged = TRUE;
389  lv->cur_elements = newne;
390 }
391 
392 void listview_set_num_elements ( listview *lv, unsigned int rows )
393 {
394  if ( lv == NULL ) {
395  return;
396  }
397  lv->req_elements = rows;
398  listview_set_selected ( lv, lv->selected );
400  widget_queue_redraw ( WIDGET ( lv ) );
401 }
402 
403 unsigned int listview_get_selected ( listview *lv )
404 {
405  if ( lv != NULL ) {
406  return lv->selected;
407  }
408  return 0;
409 }
410 
411 void listview_set_selected ( listview *lv, unsigned int selected )
412 {
413  if ( lv && lv->req_elements > 0 ) {
414  lv->selected = MIN ( selected, lv->req_elements - 1 );
416  widget_queue_redraw ( WIDGET ( lv ) );
417  }
418 }
419 
420 static void listview_resize ( widget *wid, short w, short h )
421 {
422  listview *lv = (listview *) wid;
423  lv->widget.w = MAX ( 0, w );
424  lv->widget.h = MAX ( 0, h );
425  int height = lv->widget.h - widget_padding_get_padding_height ( WIDGET ( lv ) );
426  int spacing_vert = distance_get_pixel ( lv->spacing, ROFI_ORIENTATION_VERTICAL );
427  lv->max_rows = ( spacing_vert + height ) / ( lv->element_height + spacing_vert );
428  lv->max_elements = lv->max_rows * lv->menu_columns;
429 
430  if ( /*lv->scrollbar->widget.index ==*/ 0 ) {
431  widget_move ( WIDGET ( lv->scrollbar ),
432  widget_padding_get_left ( WIDGET ( lv ) ),
433  widget_padding_get_top ( WIDGET ( lv ) ) );
434  }
435  else {
436  widget_move ( WIDGET ( lv->scrollbar ),
438  widget_padding_get_top ( WIDGET ( lv ) ) );
439  }
440  widget_resize ( WIDGET ( lv->scrollbar ), widget_get_width ( WIDGET ( lv->scrollbar ) ), height );
441 
442  if ( lv->type == BARVIEW ) {
443  lv->max_elements = lv->menu_lines;
444  }
445 
447  widget_queue_redraw ( wid );
448 }
449 
450 static widget *listview_find_mouse_target ( widget *wid, WidgetType type, gint x, gint y )
451 {
452  widget *target = NULL;
453  gint rx, ry;
454  listview *lv = (listview *) wid;
455  if ( widget_enabled ( WIDGET ( lv->scrollbar ) ) && widget_intersect ( WIDGET ( lv->scrollbar ), x, y ) ) {
456  rx = x - widget_get_x_pos ( WIDGET ( lv->scrollbar ) );
457  ry = y - widget_get_y_pos ( WIDGET ( lv->scrollbar ) );
458  target = widget_find_mouse_target ( WIDGET ( lv->scrollbar ), type, rx, ry );
459  }
460 
461  unsigned int max = MIN ( lv->cur_elements, lv->req_elements - lv->last_offset );
462  unsigned int i;
463  for ( i = 0; i < max && target == NULL; i++ ) {
464  widget *w = WIDGET ( lv->boxes[i] );
465  if ( widget_intersect ( w, x, y ) ) {
466  rx = x - widget_get_x_pos ( w );
467  ry = y - widget_get_y_pos ( w );
468  target = widget_find_mouse_target ( w, type, rx, ry );
469  }
470  }
471 
472  return target;
473 }
474 
475 static WidgetTriggerActionResult listview_trigger_action ( widget *wid, MouseBindingListviewAction action, G_GNUC_UNUSED gint x, G_GNUC_UNUSED gint y, G_GNUC_UNUSED void *user_data )
476 {
477  listview *lv = (listview *) wid;
478  switch ( action )
479  {
480  case SCROLL_LEFT:
481  listview_nav_left ( lv );
482  break;
483  case SCROLL_RIGHT:
484  listview_nav_right ( lv );
485  break;
486  case SCROLL_DOWN:
487  listview_nav_down ( lv );
488  break;
489  case SCROLL_UP:
490  listview_nav_up ( lv );
491  break;
492  }
494 }
495 
496 static WidgetTriggerActionResult listview_element_trigger_action ( widget *wid, MouseBindingListviewElementAction action, G_GNUC_UNUSED gint x, G_GNUC_UNUSED gint y, void *user_data )
497 {
498  listview *lv = (listview *) user_data;
499  unsigned int max = MIN ( lv->cur_elements, lv->req_elements - lv->last_offset );
500  unsigned int i;
501  for ( i = 0; i < max && WIDGET ( lv->boxes[i] ) != wid; i++ ) {
502  }
503  if ( i == max ) {
505  }
506 
507  gboolean custom = FALSE;
508  switch ( action )
509  {
511  listview_set_selected ( lv, lv->last_offset + i );
512  break;
514  custom = TRUE;
515  /* FALLTHRU */
517  listview_set_selected ( lv, lv->last_offset + i );
518  lv->mouse_activated ( lv, custom, lv->mouse_activated_data );
519  break;
520  }
522 }
523 
524 listview *listview_create ( widget *parent, const char *name, listview_update_callback cb, void *udata, unsigned int eh, gboolean reverse )
525 {
526  listview *lv = g_malloc0 ( sizeof ( listview ) );
527  widget_init ( WIDGET ( lv ), parent, WIDGET_TYPE_LISTVIEW, name );
528  lv->listview_name = g_strdup ( name );
529  lv->widget.free = listview_free;
531  lv->widget.draw = _listview_draw;
535  lv->eh = eh;
536 
537  lv->emode = PANGO_ELLIPSIZE_END;
538  lv->scrollbar = scrollbar_create ( WIDGET ( lv ), "scrollbar" );
539  // Calculate height of an element.
540  //
541  textbox *tb = textbox_create ( WIDGET ( lv ), WIDGET_TYPE_LISTVIEW_ELEMENT, "element", 0, NORMAL, "", 0, 0 );
543  widget_free ( WIDGET ( tb ) );
544 
545  lv->callback = cb;
546  lv->udata = udata;
547 
548  // Some settings.
549  lv->spacing = rofi_theme_get_distance ( WIDGET ( lv ), "spacing", DEFAULT_SPACING );
550  lv->menu_columns = rofi_theme_get_integer ( WIDGET ( lv ), "columns", config.menu_columns );
551  lv->fixed_num_lines = rofi_theme_get_boolean ( WIDGET ( lv ), "fixed-height", config.fixed_num_lines );
552  lv->dynamic = rofi_theme_get_boolean ( WIDGET ( lv ), "dynamic", TRUE );
553  lv->reverse = rofi_theme_get_boolean ( WIDGET ( lv ), "reverse", reverse );
554  lv->cycle = rofi_theme_get_boolean ( WIDGET ( lv ), "cycle", config.cycle );
555 
557  if ( lv->type == LISTVIEW ) {
558  listview_set_show_scrollbar ( lv, rofi_theme_get_boolean ( WIDGET ( lv ), "scrollbar", FALSE ) );
559  }
560  else {
561  listview_set_show_scrollbar ( lv, FALSE );
562  }
563  return lv;
564 }
565 
570 static void listview_nav_up_int ( listview *lv )
571 {
572  if ( lv == NULL ) {
573  return;
574  }
575  if ( lv->req_elements == 0 || ( lv->selected == 0 && !lv->cycle ) ) {
576  return;
577  }
578  if ( lv->selected == 0 ) {
579  lv->selected = lv->req_elements;
580  }
581  lv->selected--;
583  widget_queue_redraw ( WIDGET ( lv ) );
584 }
585 static void listview_nav_down_int ( listview *lv )
586 {
587  if ( lv == NULL ) {
588  return;
589  }
590  if ( lv->req_elements == 0 || ( lv->selected == ( lv->req_elements - 1 ) && !lv->cycle ) ) {
591  return;
592  }
593  lv->selected = lv->selected < lv->req_elements - 1 ? MIN ( lv->req_elements - 1, lv->selected + 1 ) : 0;
595  widget_queue_redraw ( WIDGET ( lv ) );
596 }
597 
599 {
600  if ( lv == NULL ) {
601  return;
602  }
603  if ( lv->reverse ) {
604  listview_nav_down_int ( lv );
605  }
606  else {
607  listview_nav_up_int ( lv );
608  }
609 }
611 {
612  if ( lv == NULL ) {
613  return;
614  }
615  if ( lv->reverse ) {
616  listview_nav_up_int ( lv );
617  }
618  else {
619  listview_nav_down_int ( lv );
620  }
621 }
622 
624 {
625  if ( lv == NULL ) {
626  return;
627  }
628  if ( lv->type == BARVIEW ) {
629  listview_nav_up_int ( lv );
630  return;
631  }
632  if ( lv->selected >= lv->max_rows ) {
633  lv->selected -= lv->max_rows;
634  widget_queue_redraw ( WIDGET ( lv ) );
635  }
636 }
638 {
639  if ( lv == NULL ) {
640  return;
641  }
642  if ( lv->type == BARVIEW ) {
643  listview_nav_down_int ( lv );
644  return;
645  }
646  if ( ( lv->selected + lv->max_rows ) < lv->req_elements ) {
647  lv->selected += lv->max_rows;
648  widget_queue_redraw ( WIDGET ( lv ) );
649  }
650  else if ( lv->selected < ( lv->req_elements - 1 ) ) {
651  // We do not want to move to last item, UNLESS the last column is only
652  // partially filled, then we still want to move column and select last entry.
653  // First check the column we are currently in.
654  int col = lv->selected / lv->max_rows;
655  // Check total number of columns.
656  int ncol = lv->req_elements / lv->max_rows;
657  // If there is an extra column, move.
658  if ( col != ncol ) {
659  lv->selected = lv->req_elements - 1;
660  widget_queue_redraw ( WIDGET ( lv ) );
661  }
662  }
663 }
664 
666 {
667  if ( lv == NULL ) {
668  return;
669  }
670  if ( lv->type == BARVIEW ) {
671  if ( lv->last_offset == 0 ) {
672  lv->selected = 0;
673  }
674  else {
675  lv->selected = lv->last_offset - 1;
676  }
678  widget_queue_redraw ( WIDGET ( lv ) );
679  return;
680  }
681 
682  if ( lv->selected < lv->max_elements ) {
683  lv->selected = 0;
684  }
685  else{
686  lv->selected -= ( lv->max_elements );
687  }
688  widget_queue_redraw ( WIDGET ( lv ) );
689 }
691 {
692  if ( lv == NULL ) {
693  return;
694  }
695  if ( lv->req_elements == 0 ) {
696  return;
697  }
698  if ( lv->type == BARVIEW ) {
699  unsigned int new = lv->last_offset + lv->barview.cur_visible;
700  lv->selected = MIN ( new, lv->req_elements - 1 );
702 
703  widget_queue_redraw ( WIDGET ( lv ) );
704  return;
705  }
706  lv->selected += ( lv->max_elements );
707  if ( lv->selected >= lv->req_elements ) {
708  lv->selected = lv->req_elements - 1;
709  }
710  widget_queue_redraw ( WIDGET ( lv ) );
711 }
712 
714 {
715  if ( lv == NULL ) {
716  return;
717  }
718  if ( lv->reverse ) {
720  }
721  else {
723  }
724 }
726 {
727  if ( lv == NULL ) {
728  return;
729  }
730  if ( lv->reverse ) {
732  }
733  else {
735  }
736 }
737 
739 {
740  listview *lv = (listview *) wid;
741  if ( lv == NULL || lv->widget.enabled == FALSE ) {
742  return 0;
743  }
745  int h = lv->menu_lines;
746  if ( !( lv->fixed_num_lines ) ) {
747  if ( lv->dynamic ) {
748  h = MIN ( lv->menu_lines, lv->req_elements );
749  }
750  else {
751  h = MIN ( lv->menu_lines, lv->max_displayed_lines );
752  }
753  }
754  if ( lv->type == BARVIEW ) {
755  h = MIN ( h, 1 );
756  }
757  if ( h == 0 ) {
758  if ( lv->dynamic && !lv->fixed_num_lines ) {
759  // Hide widget fully.
760  return 0;
761  }
762  return widget_padding_get_padding_height ( WIDGET ( lv ) );
763  }
764  int height = widget_padding_get_padding_height ( WIDGET ( lv ) );
765  height += h * ( lv->element_height + spacing ) - spacing;
766  return height;
767 }
768 
769 void listview_set_show_scrollbar ( listview *lv, gboolean enabled )
770 {
771  if ( lv ) {
772  if ( enabled ) {
773  widget_enable ( WIDGET ( lv->scrollbar ) );
774  }
775  else {
776  widget_disable ( WIDGET ( lv->scrollbar ) );
777  }
779  }
780 }
781 
783 {
784  if ( lv ) {
785  lv->scroll_type = type;
786  }
787 }
788 
790 {
791  if ( lv ) {
792  lv->mouse_activated = cb;
793  lv->mouse_activated_data = udata;
794  }
795 }
796 void listview_set_multi_select ( listview *lv, gboolean enable )
797 {
798  if ( lv ) {
799  lv->multi_select = enable;
800  }
801 }
802 void listview_set_num_lines ( listview *lv, unsigned int num_lines )
803 {
804  if ( lv ) {
805  lv->menu_lines = num_lines;
806  }
807 }
808 
809 unsigned int listview_get_num_lines ( listview *lv )
810 {
811  if ( lv ) {
812  return lv->menu_lines;
813  }
814  return 0;
815 }
816 void listview_set_max_lines ( listview *lv, unsigned int max_lines )
817 {
818  if ( lv ) {
819  lv->max_displayed_lines = max_lines;
820  }
821 }
822 
824 {
825  if ( lv ) {
826  return lv->fixed_num_lines;
827  }
828  return FALSE;
829 }
831 {
832  if ( lv ) {
833  lv->fixed_num_lines = TRUE;
834  }
835 }
836 
838 {
839  if ( lv ) {
840  PangoEllipsizeMode mode = lv->emode;
841  if ( mode == PANGO_ELLIPSIZE_START ) {
842  mode = PANGO_ELLIPSIZE_MIDDLE;
843  } else if ( mode == PANGO_ELLIPSIZE_MIDDLE ) {
844  mode = PANGO_ELLIPSIZE_END;
845  } else if ( mode == PANGO_ELLIPSIZE_END ) {
846  mode = PANGO_ELLIPSIZE_START;
847  }
848  lv->emode = mode;
849  for ( unsigned int i = 0; i < lv->cur_elements; i++ ) {
850  textbox_set_ellipsize ( lv->boxes[i], mode );
851  }
852  }
853 }
_scrollbar
Definition: scrollbar.h:44
listview_nav_up_int
static void listview_nav_up_int(listview *lv)
Definition: listview.c:570
WIDGET
#define WIDGET(a)
Definition: widget.h:115
listview_toggle_ellipsizing
void listview_toggle_ellipsizing(listview *lv)
Definition: listview.c:837
_listview::boxes
textbox ** boxes
Definition: listview.c:98
WidgetType
WidgetType
Definition: widget.h:57
WIDGET_TYPE_LISTVIEW
@ WIDGET_TYPE_LISTVIEW
Definition: widget.h:61
widget_set_trigger_action_handler
void widget_set_trigger_action_handler(widget *wid, widget_trigger_action_cb cb, void *cb_data)
Definition: widget.c:479
_listview::listview_name
char * listview_name
Definition: listview.c:110
_listview::cur_elements
unsigned int cur_elements
Definition: listview.c:83
_widget::enabled
gboolean enabled
Definition: widget-internal.h:58
DEFAULT_SPACING
#define DEFAULT_SPACING
Definition: listview.c:39
textbox_get_desired_width
int textbox_get_desired_width(widget *wid)
Definition: textbox.c:935
listview_nav_up
void listview_nav_up(listview *lv)
Definition: listview.c:598
LISTVIEW_SCROLL_CONTINIOUS
@ LISTVIEW_SCROLL_CONTINIOUS
Definition: listview.h:52
_listview::dynamic
unsigned int dynamic
Definition: listview.c:90
listview_nav_page_prev
void listview_nav_page_prev(listview *lv)
Definition: listview.c:713
settings.h
listview_update_callback
void(* listview_update_callback)(textbox *tb, unsigned int entry, void *udata, TextBoxFontType type, gboolean full)
Definition: listview.h:64
listview_set_num_elements
void listview_set_num_elements(listview *lv, unsigned int rows)
Definition: listview.c:392
listview_nav_down_int
static void listview_nav_down_int(listview *lv)
Definition: listview.c:585
_listview::emode
PangoEllipsizeMode emode
Definition: listview.c:113
scroll_continious
static unsigned int scroll_continious(listview *lv)
Definition: listview.c:175
_listview::max_rows
unsigned int max_rows
Definition: listview.c:77
listview_create
listview * listview_create(widget *parent, const char *name, listview_update_callback cb, void *udata, unsigned int eh, gboolean reverse)
Definition: listview.c:524
_listview::callback
listview_update_callback callback
Definition: listview.c:101
_listview::rchanged
unsigned int rchanged
Definition: listview.c:69
ROFI_ORIENTATION_VERTICAL
@ ROFI_ORIENTATION_VERTICAL
Definition: rofi-types.h:107
_listview::cur_visible
unsigned int cur_visible
Definition: listview.c:118
listview_trigger_action
static WidgetTriggerActionResult listview_trigger_action(widget *wid, MouseBindingListviewAction action, G_GNUC_UNUSED gint x, G_GNUC_UNUSED gint y, G_GNUC_UNUSED void *user_data)
Definition: listview.c:475
listview_set_scroll_type
void listview_set_scroll_type(listview *lv, ScrollType type)
Definition: listview.c:782
listview_find_mouse_target
static widget * listview_find_mouse_target(widget *wid, WidgetType type, gint x, gint y)
Definition: listview.c:450
NORMAL
@ NORMAL
Definition: textbox.h:97
distance_get_pixel
int distance_get_pixel(RofiDistance d, RofiOrientation ori)
Definition: theme.c:765
listview_get_num_lines
unsigned int listview_get_num_lines(listview *lv)
Definition: listview.c:809
_widget::get_desired_height
int(* get_desired_height)(struct _widget *)
Definition: widget-internal.h:81
rofi_theme_get_distance
RofiDistance rofi_theme_get_distance(const widget *widget, const char *property, int def)
Definition: theme.c:579
update_element
static void update_element(listview *lv, unsigned int tb, unsigned int index, gboolean full)
Definition: listview.c:196
rofi_theme_get_boolean
int rofi_theme_get_boolean(const widget *widget, const char *property, int def)
Definition: theme.c:601
_listview::max_elements
unsigned int max_elements
Definition: listview.c:78
HIGHLIGHT
@ HIGHLIGHT
Definition: textbox.h:110
widget_get_width
int widget_get_width(widget *widget)
Definition: widget.c:388
_listview::direction
MoveDirection direction
Definition: listview.c:117
_listview::eh
unsigned int eh
Definition: listview.c:91
_listview::selected
unsigned int selected
Definition: listview.c:74
RIGHT_TO_LEFT
@ RIGHT_TO_LEFT
Definition: listview.c:58
widget_padding_get_bottom
int widget_padding_get_bottom(const widget *wid)
Definition: widget.c:527
rofi_theme_get_integer
int rofi_theme_get_integer(const widget *widget, const char *property, int def)
Definition: theme.c:563
scrollbar_create
scrollbar * scrollbar_create(widget *parent, const char *name)
Definition: scrollbar.c:102
_listview::type
ViewType type
Definition: listview.c:65
widget_find_mouse_target
widget * widget_find_mouse_target(widget *wid, WidgetType type, gint x, gint y)
Definition: widget.c:453
listview_set_show_scrollbar
void listview_set_show_scrollbar(listview *lv, gboolean enabled)
Definition: listview.c:769
_listview::cur_page
unsigned int cur_page
Definition: listview.c:72
widget_padding_get_right
int widget_padding_get_right(const widget *wid)
Definition: widget.c:507
listview_nav_page_prev_int
static void listview_nav_page_prev_int(listview *lv)
Definition: listview.c:665
listview_recompute_elements
static void listview_recompute_elements(listview *lv)
Definition: listview.c:362
listview.h
listview_set_mouse_activated_cb
void listview_set_mouse_activated_cb(listview *lv, listview_mouse_activated_cb cb, void *udata)
Definition: listview.c:789
_widget::draw
void(* draw)(struct _widget *widget, cairo_t *draw)
Definition: widget-internal.h:72
BARVIEW
@ BARVIEW
Definition: listview.c:49
_listview::scrollbar
scrollbar * scrollbar
Definition: listview.c:99
rofi_theme_get_orientation
RofiOrientation rofi_theme_get_orientation(const widget *widget, const char *property, RofiOrientation def)
Definition: theme.c:617
_listview::last_click
xcb_timestamp_t last_click
Definition: listview.c:106
listview_nav_page_next_int
static void listview_nav_page_next_int(listview *lv)
Definition: listview.c:690
ScrollType
ScrollType
Definition: listview.h:48
theme.h
flags
MenuFlags flags
Definition: view.c:108
listview_nav_right
void listview_nav_right(listview *lv)
Definition: listview.c:637
widget_free
void widget_free(widget *wid)
Definition: widget.c:365
listview_set_num_lines
void listview_set_num_lines(listview *lv, unsigned int num_lines)
Definition: listview.c:802
RofiDistance
Definition: rofi-types.h:93
_widget::free
void(* free)(struct _widget *widget)
Definition: widget-internal.h:92
_widget::trigger_action
widget_trigger_action_cb trigger_action
Definition: widget-internal.h:87
ViewType
ViewType
Definition: listview.c:45
_listview_draw
static void _listview_draw(widget *wid, cairo_t *draw)
Definition: listview.c:352
_listview::reverse
unsigned int reverse
Definition: listview.c:92
TB_ICON
@ TB_ICON
Definition: textbox.h:89
scrollbar_set_handle_length
void scrollbar_set_handle_length(scrollbar *sb, unsigned int pos_length)
Definition: scrollbar.c:146
listview_get_selected
unsigned int listview_get_selected(listview *lv)
Definition: listview.c:403
widget_queue_redraw
void widget_queue_redraw(widget *wid)
Definition: widget.c:432
barview_draw
static void barview_draw(widget *wid, cairo_t *draw)
Definition: listview.c:207
SELECT_HOVERED_ENTRY
@ SELECT_HOVERED_ENTRY
Definition: keyb.h:159
scroll_per_page_barview
static unsigned int scroll_per_page_barview(listview *lv)
Definition: listview.c:136
widget.h
listview_get_desired_height
static int listview_get_desired_height(widget *wid)
Definition: listview.c:738
SCROLL_UP
@ SCROLL_UP
Definition: keyb.h:151
ACCEPT_HOVERED_CUSTOM
@ ACCEPT_HOVERED_CUSTOM
Definition: keyb.h:161
widget_padding_get_top
int widget_padding_get_top(const widget *wid)
Definition: widget.c:517
Settings::fixed_num_lines
unsigned int fixed_num_lines
Definition: settings.h:108
_listview::element_height
unsigned int element_height
Definition: listview.c:76
listview_mouse_activated_cb
void(* listview_mouse_activated_cb)(listview *, gboolean, void *)
Definition: listview.h:69
Settings::cycle
unsigned int cycle
Definition: settings.h:128
widget_disable
void widget_disable(widget *widget)
Definition: widget.c:133
widget_intersect
int widget_intersect(const widget *widget, int x, int y)
Definition: widget.c:70
_listview::req_elements
unsigned int req_elements
Definition: listview.c:82
widget_get_x_pos
int widget_get_x_pos(widget *widget)
Definition: widget.c:398
listview_resize
static void listview_resize(widget *wid, short w, short h)
Definition: listview.c:420
_listview::udata
void * udata
Definition: listview.c:102
TextboxFlags
TextboxFlags
Definition: textbox.h:81
MoveDirection
MoveDirection
Definition: listview.c:56
listview_free
static void listview_free(widget *wid)
Definition: listview.c:124
SCROLL_RIGHT
@ SCROLL_RIGHT
Definition: keyb.h:149
_listview
Definition: listview.c:62
textbox_set_ellipsize
void textbox_set_ellipsize(textbox *tb, PangoEllipsizeMode mode)
Definition: textbox.c:958
LISTVIEW
@ LISTVIEW
Definition: listview.c:47
_listview::mouse_activated
listview_mouse_activated_cb mouse_activated
Definition: listview.c:107
_listview::scroll_type
ScrollType scroll_type
Definition: listview.c:96
listview_set_multi_select
void listview_set_multi_select(listview *lv, gboolean enable)
Definition: listview.c:796
widget_move
void widget_move(widget *widget, short x, short y)
Definition: widget.c:100
WIDGET_TYPE_LISTVIEW_ELEMENT
@ WIDGET_TYPE_LISTVIEW_ELEMENT
Definition: widget.h:63
scrollbar_set_max_value
void scrollbar_set_max_value(scrollbar *sb, unsigned int max)
Definition: scrollbar.c:132
listview_nav_page_next
void listview_nav_page_next(listview *lv)
Definition: listview.c:725
MouseBindingListviewElementAction
MouseBindingListviewElementAction
Definition: keyb.h:158
scrollbar_set_handle
void scrollbar_set_handle(scrollbar *sb, unsigned int pos)
Definition: scrollbar.c:139
SCROLL_DOWN
@ SCROLL_DOWN
Definition: keyb.h:150
_widget::h
short h
Definition: widget-internal.h:46
widget_get_y_pos
int widget_get_y_pos(widget *widget)
Definition: widget.c:405
listview_set_fixed_num_lines
void listview_set_fixed_num_lines(listview *lv)
Definition: listview.c:830
Settings::menu_columns
unsigned int menu_columns
Definition: settings.h:67
widget_init
void widget_init(widget *wid, widget *parent, WidgetType type, const char *name)
Definition: widget.c:37
_widget::w
short w
Definition: widget-internal.h:44
TB_INDICATOR
@ TB_INDICATOR
Definition: textbox.h:88
widget_enable
void widget_enable(widget *widget)
Definition: widget.c:124
textbox_get_estimated_height
int textbox_get_estimated_height(const textbox *tb, int eh)
Definition: textbox.c:930
TextBoxFontType
TextBoxFontType
Definition: textbox.h:95
listview_set_max_lines
void listview_set_max_lines(listview *lv, unsigned int max_lines)
Definition: listview.c:816
widget_draw
void widget_draw(widget *widget, cairo_t *d)
Definition: widget.c:142
scroll_per_page
static unsigned int scroll_per_page(listview *lv)
Definition: listview.c:152
_listview::mouse_activated_data
void * mouse_activated_data
Definition: listview.c:108
SCROLL_LEFT
@ SCROLL_LEFT
Definition: keyb.h:148
listview_draw
static void listview_draw(widget *wid, cairo_t *draw)
Definition: listview.c:284
listview_get_fixed_num_lines
gboolean listview_get_fixed_num_lines(listview *lv)
Definition: listview.c:823
_listview::multi_select
gboolean multi_select
Definition: listview.c:94
_listview::cur_columns
unsigned int cur_columns
Definition: listview.c:81
ALT
@ ALT
Definition: textbox.h:108
listview_nav_left
void listview_nav_left(listview *lv)
Definition: listview.c:623
textbox
Definition: textbox.h:51
textbox.h
_listview::barview
struct _listview::@1 barview
_widget::find_mouse_target
widget_find_mouse_target_cb find_mouse_target
Definition: widget-internal.h:85
LEFT_TO_RIGHT
@ LEFT_TO_RIGHT
Definition: listview.c:57
_listview::spacing
RofiDistance spacing
Definition: listview.c:85
widget_padding_get_left
int widget_padding_get_left(const widget *wid)
Definition: widget.c:497
_widget::resize
void(* resize)(struct _widget *, short, short)
Definition: widget-internal.h:74
Settings::show_icons
gboolean show_icons
Definition: settings.h:78
_listview::max_displayed_lines
unsigned int max_displayed_lines
Definition: listview.c:87
textbox_moveresize
void textbox_moveresize(textbox *tb, int x, int y, int w, int h)
Definition: textbox.c:353
_listview::widget
widget widget
Definition: listview.c:63
_listview::menu_columns
unsigned int menu_columns
Definition: listview.c:88
widget_resize
void widget_resize(widget *widget, short w, short h)
Definition: widget.c:84
WIDGET_TRIGGER_ACTION_RESULT_HANDLED
@ WIDGET_TRIGGER_ACTION_RESULT_HANDLED
Definition: widget.h:82
config
Settings config
_listview::last_offset
unsigned int last_offset
Definition: listview.c:73
WIDGET_TRIGGER_ACTION_RESULT_IGNORED
@ WIDGET_TRIGGER_ACTION_RESULT_IGNORED
Definition: widget.h:80
ROFI_ORIENTATION_HORIZONTAL
@ ROFI_ORIENTATION_HORIZONTAL
Definition: rofi-types.h:108
listview_set_selected
void listview_set_selected(listview *lv, unsigned int selected)
Definition: listview.c:411
ACCEPT_HOVERED_ENTRY
@ ACCEPT_HOVERED_ENTRY
Definition: keyb.h:160
widget_enabled
gboolean widget_enabled(widget *widget)
Definition: widget.c:116
_listview::cycle
gboolean cycle
Definition: listview.c:93
_listview::menu_lines
unsigned int menu_lines
Definition: listview.c:86
listview_nav_down
void listview_nav_down(listview *lv)
Definition: listview.c:610
widget_padding_get_padding_width
int widget_padding_get_padding_width(const widget *wid)
Definition: widget.c:559
widget_padding_get_padding_height
int widget_padding_get_padding_height(const widget *wid)
Definition: widget.c:552
_widget
Definition: widget-internal.h:36
WidgetTriggerActionResult
WidgetTriggerActionResult
Definition: widget.h:78
listview_element_trigger_action
static WidgetTriggerActionResult listview_element_trigger_action(widget *wid, MouseBindingListviewElementAction action, gint x, gint y, void *user_data)
_listview::fixed_num_lines
unsigned int fixed_num_lines
Definition: listview.c:89
MouseBindingListviewAction
MouseBindingListviewAction
Definition: keyb.h:147
scrollbar.h
_listview::scrollbar_scroll
gboolean scrollbar_scroll
Definition: listview.c:104
textbox_create
textbox * textbox_create(widget *parent, WidgetType type, const char *name, TextboxFlags flags, TextBoxFontType tbft, const char *text, double xalign, double yalign)
Definition: textbox.c:166