Merge branch 'remotes/jsbackus/mpd_lua52'
[notion.git] / mod_statusbar / statusbar.c
blob55e44e53f5dd9aaebf7acd52f43b8fdabe23e3f7
1 /*
2 * ion/mod_statusbar/statusbar.c
4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
7 */
9 #include <string.h>
10 #include <limits.h>
12 #include <libtu/objp.h>
13 #include <libtu/minmax.h>
14 #include <libtu/ptrlist.h>
15 #include <libtu/misc.h>
16 #include <ioncore/common.h>
17 #include <ioncore/global.h>
18 #include <ioncore/window.h>
19 #include <ioncore/binding.h>
20 #include <ioncore/regbind.h>
21 #include <ioncore/event.h>
22 #include <ioncore/resize.h>
23 #include <ioncore/gr.h>
24 #include <ioncore/gr-util.h>
25 #include <ioncore/names.h>
26 #include <ioncore/strings.h>
27 #include <ioncore/basicpholder.h>
28 #include <ioncore/sizehint.h>
30 #include "statusbar.h"
31 #include "main.h"
32 #include "draw.h"
35 static void statusbar_set_elems(WStatusBar *sb, ExtlTab t);
36 static void statusbar_free_elems(WStatusBar *sb);
37 static void statusbar_update_natural_size(WStatusBar *p);
38 static void statusbar_arrange_systray(WStatusBar *p);
39 static int statusbar_systray_x(WStatusBar *p);
40 static void statusbar_rearrange(WStatusBar *sb, bool rs);
41 static void do_calc_systray_w(WStatusBar *p, WSBElem *el);
42 static void statusbar_calc_systray_w(WStatusBar *p);
44 static WStatusBar *statusbars=NULL;
47 /*{{{ Init/deinit */
50 bool statusbar_init(WStatusBar *p, WWindow *parent, const WFitParams *fp)
52 if(!window_init(&(p->wwin), parent, fp, "WStatusBar"))
53 return FALSE;
55 p->brush=NULL;
56 p->elems=NULL;
57 p->nelems=0;
58 p->natural_w=1;
59 p->natural_h=1;
60 p->filleridx=-1;
61 p->sb_next=NULL;
62 p->sb_prev=NULL;
63 p->traywins=NULL;
64 p->systray_enabled=TRUE;
66 statusbar_updategr(p);
68 if(p->brush==NULL){
69 window_deinit(&(p->wwin));
70 return FALSE;
73 window_select_input(&(p->wwin), IONCORE_EVENTMASK_NORMAL);
75 region_register((WRegion*)p);
77 region_add_bindmap((WRegion*)p, mod_statusbar_statusbar_bindmap);
79 LINK_ITEM(statusbars, p, sb_next, sb_prev);
81 return TRUE;
86 WStatusBar *create_statusbar(WWindow *parent, const WFitParams *fp)
88 CREATEOBJ_IMPL(WStatusBar, statusbar, (p, parent, fp));
92 void statusbar_deinit(WStatusBar *p)
94 UNLINK_ITEM(statusbars, p, sb_next, sb_prev);
96 statusbar_free_elems(p);
98 if(p->brush!=NULL){
99 grbrush_release(p->brush);
100 p->brush=NULL;
103 window_deinit(&(p->wwin));
107 /*}}}*/
110 /*{{{ Content stuff */
113 static void init_sbelem(WSBElem *el)
115 el->type=WSBELEM_NONE;
116 el->text_w=0;
117 el->text=NULL;
118 el->max_w=0;
119 el->tmpl=NULL;
120 el->meter=STRINGID_NONE;
121 el->attr=STRINGID_NONE;
122 el->stretch=0;
123 el->align=WSBELEM_ALIGN_CENTER;
124 el->zeropad=0;
125 el->x=0;
126 el->traywins=NULL;
130 static bool gets_stringstore(ExtlTab t, const char *str, StringId *id)
132 char *s;
134 if(extl_table_gets_s(t, str, &s)){
135 *id=stringstore_alloc(s);
136 free(s);
137 return (*id!=STRINGID_NONE);
140 return FALSE;
144 static WSBElem *get_sbelems(ExtlTab t, int *nret, int *filleridxret)
146 int i, n=extl_table_get_n(t);
147 WSBElem *el;
148 int systrayidx=-1;
150 *nret=0;
151 *filleridxret=-1;
153 if(n<=0)
154 return NULL;
156 el=ALLOC_N(WSBElem, n);
158 if(el==NULL)
159 return NULL;
161 for(i=0; i<n; i++){
162 ExtlTab tt;
164 init_sbelem(&el[i]);
166 if(extl_table_geti_t(t, i+1, &tt)){
167 if(extl_table_gets_i(tt, "type", &(el[i].type))){
168 if(el[i].type==WSBELEM_TEXT || el[i].type==WSBELEM_STRETCH){
169 extl_table_gets_s(tt, "text", &(el[i].text));
170 }else if(el[i].type==WSBELEM_METER){
171 gets_stringstore(tt, "meter", &(el[i].meter));
172 extl_table_gets_s(tt, "tmpl", &(el[i].tmpl));
173 extl_table_gets_i(tt, "align", &(el[i].align));
174 extl_table_gets_i(tt, "zeropad", &(el[i].zeropad));
175 el[i].zeropad=maxof(el[i].zeropad, 0);
176 }else if(el[i].type==WSBELEM_SYSTRAY){
177 const char *tmp;
179 gets_stringstore(tt, "meter", &(el[i].meter));
180 extl_table_gets_i(tt, "align", &(el[i].align));
182 tmp=stringstore_get(el[i].meter);
184 if(tmp==NULL || strcmp(tmp, "systray")==0)
185 systrayidx=i;
186 }else if(el[i].type==WSBELEM_FILLER){
187 *filleridxret=i;
190 extl_unref_table(tt);
194 if(systrayidx==-1){
195 WSBElem *el2=REALLOC_N(el, WSBElem, n, n+1);
196 if(el2!=NULL){
197 el=el2;
198 init_sbelem(&el[n]);
199 el[n].type=WSBELEM_SYSTRAY;
200 n++;
204 *nret=n;
206 return el;
210 static void free_sbelems(WSBElem *el, int n)
212 int i;
214 for(i=0; i<n; i++){
215 if(el[i].text!=NULL)
216 free(el[i].text);
217 if(el[i].tmpl!=NULL)
218 free(el[i].tmpl);
219 if(el[i].meter!=STRINGID_NONE)
220 stringstore_free(el[i].meter);
221 if(el[i].attr!=STRINGID_NONE)
222 stringstore_free(el[i].attr);
223 if(el[i].traywins!=NULL)
224 ptrlist_clear(&el[i].traywins);
227 free(el);
231 static void statusbar_set_elems(WStatusBar *sb, ExtlTab t)
233 statusbar_free_elems(sb);
235 sb->elems=get_sbelems(t, &(sb->nelems), &(sb->filleridx));
239 static void statusbar_free_elems(WStatusBar *sb)
241 if(sb->elems!=NULL){
242 free_sbelems(sb->elems, sb->nelems);
243 sb->elems=NULL;
244 sb->nelems=0;
245 sb->filleridx=-1;
250 /*}}}*/
254 /*{{{ Size stuff */
257 static void statusbar_resize(WStatusBar *p)
259 WRQGeomParams rq=RQGEOMPARAMS_INIT;
261 rq.flags=REGION_RQGEOM_WEAK_X|REGION_RQGEOM_WEAK_Y;
263 rq.geom.w=p->natural_w;
264 rq.geom.h=p->natural_h;
265 rq.geom.x=REGION_GEOM(p).x;
266 rq.geom.y=REGION_GEOM(p).y;
268 if(rectangle_compare(&rq.geom, &REGION_GEOM(p))!=RECTANGLE_SAME)
269 region_rqgeom((WRegion*)p, &rq, NULL);
273 static void calc_elem_w(WStatusBar *p, WSBElem *el, GrBrush *brush)
275 const char *str;
277 if(el->type==WSBELEM_SYSTRAY){
278 do_calc_systray_w(p, el);
279 return;
282 if(brush==NULL){
283 el->text_w=0;
284 return;
287 if(el->type==WSBELEM_METER){
288 str=(el->text!=NULL ? el->text : STATUSBAR_NX_STR);
289 el->text_w=grbrush_get_text_width(brush, str, strlen(str));
290 str=el->tmpl;
291 el->max_w=maxof((str!=NULL
292 ? grbrush_get_text_width(brush, str, strlen(str))
293 : 0),
294 el->text_w);
295 }else{
296 str=el->text;
297 el->text_w=(str!=NULL
298 ? grbrush_get_text_width(brush, str, strlen(str))
299 : 0);
300 el->max_w=el->text_w;
305 static void statusbar_calc_widths(WStatusBar *sb)
307 int i;
309 for(i=0; i<sb->nelems; i++)
310 calc_elem_w(sb, &(sb->elems[i]), sb->brush);
314 static void statusbar_do_update_natural_size(WStatusBar *p)
316 GrBorderWidths bdw;
317 GrFontExtents fnte;
318 WRegion *reg;
319 PtrListIterTmp tmp;
320 int totw=0, stmh=0;
321 int i;
323 if(p->brush==NULL){
324 bdw.left=0; bdw.right=0;
325 bdw.top=0; bdw.bottom=0;
326 fnte.max_height=4;
327 }else{
328 grbrush_get_border_widths(p->brush, &bdw);
329 grbrush_get_font_extents(p->brush, &fnte);
332 for(i=0; i<p->nelems; i++)
333 totw+=p->elems[i].max_w;
335 FOR_ALL_ON_PTRLIST(WRegion*, reg, p->traywins, tmp){
336 stmh=maxof(stmh, REGION_GEOM(reg).h);
339 p->natural_w=bdw.left+totw+bdw.right;
340 p->natural_h=maxof(stmh, fnte.max_height)+bdw.top+bdw.bottom;
344 void statusbar_size_hints(WStatusBar *p, WSizeHints *h)
346 h->min_set=TRUE;
347 h->min_width=p->natural_w;
348 h->min_height=p->natural_h;
350 h->max_set=TRUE;
351 h->max_width=INT_MAX;/*p->natural_w;*/
352 h->max_height=p->natural_h;
356 /*}}}*/
359 /*{{{ Systray */
362 static WSBElem *statusbar_associate_systray(WStatusBar *sb, WRegion *reg)
364 WClientWin *cwin=OBJ_CAST(reg, WClientWin);
365 WSBElem *el=NULL, *fbel=NULL;
366 char *name=NULL;
367 int i;
369 if(cwin!=NULL)
370 extl_table_gets_s(cwin->proptab, "statusbar", &name);
372 for(i=0; i<sb->nelems; i++){
373 const char *meter;
375 if(sb->elems[i].type!=WSBELEM_SYSTRAY)
376 continue;
378 meter=stringstore_get(sb->elems[i].meter);
380 if(meter==NULL){
381 fbel=&sb->elems[i];
382 continue;
384 if(name!=NULL && strcmp(meter, name)==0){
385 el=&sb->elems[i];
386 break;
388 if(strcmp(meter, "systray")==0)
389 fbel=&sb->elems[i];
392 if(name!=NULL)
393 free(name);
395 if(el==NULL)
396 el=fbel;
398 if(el==NULL)
399 return NULL;
401 ptrlist_insert_last(&el->traywins, (Obj*)reg);
403 return el;
407 static WSBElem *statusbar_unassociate_systray(WStatusBar *sb, WRegion *reg)
409 int i;
411 for(i=0; i<sb->nelems; i++){
412 if(ptrlist_remove(&(sb->elems[i].traywins), (Obj*)reg))
413 return &sb->elems[i];
416 return NULL;
421 static void do_calc_systray_w(WStatusBar *p, WSBElem *el)
423 WRegion *reg;
424 PtrListIterTmp tmp;
425 int padding=0;
426 int w=-padding;
428 FOR_ALL_ON_PTRLIST(WRegion*, reg, el->traywins, tmp){
429 w=w+REGION_GEOM(reg).w+padding;
432 el->text_w=maxof(0, w);
433 el->max_w=el->text_w; /* for now */
437 static void statusbar_calc_systray_w(WStatusBar *p)
439 int i;
441 for(i=0; i<p->nelems; i++){
442 if(p->elems[i].type==WSBELEM_SYSTRAY)
443 do_calc_systray_w(p, &p->elems[i]);
448 static void statusbar_arrange_systray(WStatusBar *p)
450 WRegion *reg;
451 PtrListIterTmp tmp;
452 GrBorderWidths bdw;
453 int padding=0, ymiddle;
454 int i, x;
456 if(p->brush!=NULL){
457 grbrush_get_border_widths(p->brush, &bdw);
458 }else{
459 bdw.top=0;
460 bdw.bottom=0;
463 ymiddle=bdw.top+(REGION_GEOM(p).h-bdw.top-bdw.bottom)/2;
465 for(i=0; i<p->nelems; i++){
466 WSBElem *el=&p->elems[i];
467 if(el->type!=WSBELEM_SYSTRAY)
468 continue;
469 x=el->x;
470 FOR_ALL_ON_PTRLIST(WRegion*, reg, el->traywins, tmp){
471 WRectangle g=REGION_GEOM(reg);
472 g.x=x;
473 g.y=ymiddle-g.h/2;
474 region_fit(reg, &g, REGION_FIT_EXACT);
475 x=x+g.w+padding;
481 static void systray_adjust_size(WRegion *reg, WRectangle *g)
483 g->h=CF_STATUSBAR_SYSTRAY_HEIGHT;
485 region_size_hints_correct(reg, &g->w, &g->h, TRUE);
490 static WRegion *statusbar_do_attach_final(WStatusBar *sb,
491 WRegion *reg,
492 void *UNUSED(unused))
494 WFitParams fp;
495 WSBElem *el;
497 if(!ptrlist_insert_last(&sb->traywins, (Obj*)reg))
498 return NULL;
500 el=statusbar_associate_systray(sb, reg);
501 if(el==NULL){
502 ptrlist_remove(&sb->traywins, (Obj*)reg);
503 return NULL;
506 fp.g=REGION_GEOM(reg);
507 fp.mode=REGION_FIT_EXACT;
508 systray_adjust_size(reg, &fp.g);
510 region_fitrep(reg, NULL, &fp);
512 do_calc_systray_w(sb, el);
514 region_set_manager(reg, (WRegion*)sb);
516 statusbar_rearrange(sb, TRUE);
518 if(REGION_IS_MAPPED(sb))
519 region_map(reg);
521 return reg;
525 static WRegion *statusbar_do_attach(WStatusBar *sb, WRegionAttachData *data)
527 WFitParams fp;
529 fp.g.x=0;
530 fp.g.y=0;
531 fp.g.h=CF_STATUSBAR_SYSTRAY_HEIGHT;
532 fp.g.w=CF_STATUSBAR_SYSTRAY_HEIGHT;
533 fp.mode=REGION_FIT_WHATEVER|REGION_FIT_BOUNDS;
535 return region_attach_helper((WRegion*)sb, (WWindow*)sb, &fp,
536 (WRegionDoAttachFn*)statusbar_do_attach_final,
537 NULL, data);
541 static WRegion *statusbar_attach_ph(WStatusBar *sb, int UNUSED(flags),
542 WRegionAttachData *data)
544 return statusbar_do_attach(sb, data);
548 static WPHolder *statusbar_prepare_manage(WStatusBar *sb,
549 const WClientWin *UNUSED(cwin),
550 const WManageParams *UNUSED(param),
551 int priority)
553 if(!MANAGE_PRIORITY_OK(priority, MANAGE_PRIORITY_LOW))
554 return NULL;
556 return (WPHolder*)create_basicpholder((WRegion*)sb,
557 ((WBasicPHolderHandler*)
558 statusbar_attach_ph));
562 static void statusbar_managed_remove(WStatusBar *sb, WRegion *reg)
564 WSBElem *el;
566 ptrlist_remove(&sb->traywins, (Obj*)reg);
568 el=statusbar_unassociate_systray(sb, reg);
570 region_unset_manager(reg, (WRegion*)sb);
572 if(el!=NULL && ioncore_g.opmode!=IONCORE_OPMODE_DEINIT){
573 do_calc_systray_w(sb, el);
574 statusbar_rearrange(sb, TRUE);
579 static void statusbar_managed_rqgeom(WStatusBar *sb, WRegion *reg,
580 const WRQGeomParams *rq,
581 WRectangle *geomret)
583 WRectangle g;
585 g.x=REGION_GEOM(reg).x;
586 g.y=REGION_GEOM(reg).y;
587 g.w=rq->geom.w;
588 g.h=rq->geom.h;
590 systray_adjust_size(reg, &g);
592 if(rq->flags&REGION_RQGEOM_TRYONLY){
593 if(geomret!=NULL)
594 *geomret=g;
595 return;
598 region_fit(reg, &g, REGION_FIT_EXACT);
600 statusbar_calc_systray_w(sb);
601 statusbar_rearrange(sb, TRUE);
603 if(geomret!=NULL)
604 *geomret=REGION_GEOM(reg);
609 void statusbar_map(WStatusBar *sb)
611 WRegion *reg;
612 PtrListIterTmp tmp;
614 window_map((WWindow*)sb);
616 FOR_ALL_ON_PTRLIST(WRegion*, reg, sb->traywins, tmp)
617 region_map(reg);
621 void statusbar_unmap(WStatusBar *sb)
623 WRegion *reg;
624 PtrListIterTmp tmp;
626 window_unmap((WWindow*)sb);
628 FOR_ALL_ON_PTRLIST(WRegion*, reg, sb->traywins, tmp)
629 region_unmap(reg);
633 bool statusbar_fitrep(WStatusBar *sb, WWindow *par, const WFitParams *fp)
635 bool wchg=(REGION_GEOM(sb).w!=fp->g.w);
636 bool hchg=(REGION_GEOM(sb).h!=fp->g.h);
638 if(!window_fitrep(&(sb->wwin), par, fp))
639 return FALSE;
641 if(wchg || hchg){
642 statusbar_calculate_xs(sb);
643 statusbar_arrange_systray(sb);
644 statusbar_draw(sb, TRUE);
647 return TRUE;
651 WPHolder *statusbar_prepare_manage_transient(WStatusBar *sb,
652 const WClientWin *cwin,
653 const WManageParams *param,
654 int UNUSED(unused))
656 WRegion *mgr=REGION_MANAGER(sb);
658 if(mgr==NULL)
659 mgr=(WRegion*)region_screen_of((WRegion*)sb);
661 if(mgr!=NULL)
662 return region_prepare_manage(mgr, cwin, param,
663 MANAGE_PRIORITY_NONE);
664 else
665 return NULL;
670 /*}}}*/
673 /*{{{ Exports */
676 static ExtlFn parse_template_fn;
677 static bool parse_template_fn_set=FALSE;
680 EXTL_EXPORT
681 void mod_statusbar__set_template_parser(ExtlFn fn)
683 if(parse_template_fn_set)
684 extl_unref_fn(parse_template_fn);
685 parse_template_fn=extl_ref_fn(fn);
686 parse_template_fn_set=TRUE;
690 /*EXTL_DOC
691 * Set statusbar template.
693 EXTL_EXPORT_MEMBER
694 void statusbar_set_template(WStatusBar *sb, const char *tmpl)
696 ExtlTab t=extl_table_none();
697 bool ok=FALSE;
699 if(parse_template_fn_set){
700 extl_protect(NULL);
701 ok=extl_call(parse_template_fn, "s", "t", tmpl, &t);
702 extl_unprotect(NULL);
705 if(ok)
706 statusbar_set_template_table(sb, t);
710 /*EXTL_DOC
711 * Set statusbar template as table.
713 EXTL_EXPORT_MEMBER
714 void statusbar_set_template_table(WStatusBar *sb, ExtlTab t)
716 WRegion *reg;
717 PtrListIterTmp tmp;
719 statusbar_set_elems(sb, t);
721 FOR_ALL_ON_PTRLIST(WRegion*, reg, sb->traywins, tmp){
722 statusbar_associate_systray(sb, reg);
725 statusbar_calc_widths(sb);
726 statusbar_rearrange(sb, FALSE);
730 /*EXTL_DOC
731 * Get statusbar template as table.
733 EXTL_EXPORT_MEMBER
734 ExtlTab statusbar_get_template_table(WStatusBar *sb)
736 int count = sb->nelems;
737 int i;
739 ExtlTab t = extl_create_table();
741 for(i=0; i<count; i++){
742 ExtlTab tt = extl_create_table();
744 extl_table_sets_i(tt, "type", sb->elems[i].type);
745 extl_table_sets_s(tt, "text", sb->elems[i].text);
746 extl_table_sets_s(tt, "meter", stringstore_get(sb->elems[i].meter));
747 extl_table_sets_s(tt, "tmpl", sb->elems[i].tmpl);
748 extl_table_sets_i(tt, "align", sb->elems[i].align);
749 extl_table_sets_i(tt, "zeropad", sb->elems[i].zeropad);
751 extl_table_seti_t(t, (i+1), tt);
752 extl_unref_table(tt);
755 return t;
759 static void reset_stretch(WStatusBar *sb)
761 int i;
763 for(i=0; i<sb->nelems; i++)
764 sb->elems[i].stretch=0;
768 static void positive_stretch(WStatusBar *sb)
770 int i;
772 for(i=0; i<sb->nelems; i++)
773 sb->elems[i].stretch=maxof(0, sb->elems[i].stretch);
777 static void spread_stretch(WStatusBar *sb)
779 int i, j, k;
780 int diff;
781 WSBElem *el, *lel, *rel;
783 for(i=0; i<sb->nelems; i++){
784 el=&(sb->elems[i]);
786 if(el->type!=WSBELEM_METER && el->type!=WSBELEM_SYSTRAY)
787 continue;
789 diff=el->max_w-el->text_w;
791 lel=NULL;
792 rel=NULL;
794 if(el->align!=WSBELEM_ALIGN_RIGHT){
795 for(j=i+1; j<sb->nelems; j++){
796 if(sb->elems[j].type==WSBELEM_STRETCH){
797 rel=&(sb->elems[j]);
798 break;
803 if(el->align!=WSBELEM_ALIGN_LEFT){
804 for(k=i-1; k>=0; k--){
805 if(sb->elems[k].type==WSBELEM_STRETCH){
806 lel=&(sb->elems[k]);
807 break;
812 if(rel!=NULL && lel!=NULL){
813 int l=diff/2;
814 int r=diff-l;
815 lel->stretch+=l;
816 rel->stretch+=r;
817 }else if(lel!=NULL){
818 lel->stretch+=diff;
819 }else if(rel!=NULL){
820 rel->stretch+=diff;
826 static void statusbar_rearrange(WStatusBar *sb, bool rs)
828 if(rs){
829 int onw=sb->natural_w;
830 int onh=sb->natural_h;
832 statusbar_do_update_natural_size(sb);
834 if( (sb->natural_h>onh && REGION_GEOM(sb).h>=onh)
835 || (sb->natural_h<onh && REGION_GEOM(sb).h<=onh)
836 || (sb->natural_w>onw && REGION_GEOM(sb).w>=onw)
837 || (sb->natural_w<onw && REGION_GEOM(sb).w<=onw)){
839 statusbar_resize(sb);
843 reset_stretch(sb);
844 spread_stretch(sb);
845 positive_stretch(sb);
846 statusbar_calculate_xs(sb);
848 if(rs)
849 statusbar_arrange_systray(sb);
854 /*EXTL_DOC
855 * Set statusbar template.
857 EXTL_EXPORT_MEMBER
858 void statusbar_update(WStatusBar *sb, ExtlTab t)
860 int i;
861 WSBElem *el;
862 bool grow=FALSE;
864 if(sb->brush==NULL)
865 return;
867 for(i=0; i<sb->nelems; i++){
868 const char *meter;
870 el=&(sb->elems[i]);
872 if(el->type!=WSBELEM_METER)
873 continue;
875 if(el->text!=NULL){
876 free(el->text);
877 el->text=NULL;
880 if(el->attr!=GRATTR_NONE){
881 stringstore_free(el->attr);
882 el->attr=GRATTR_NONE;
885 meter=stringstore_get(el->meter);
887 if(meter!=NULL){
888 const char *str;
889 char *attrnm;
891 extl_table_gets_s(t, meter, &(el->text));
893 if(el->text==NULL){
894 str=STATUSBAR_NX_STR;
895 }else{
896 /* Zero-pad */
897 int l=strlen(el->text);
898 int ml=str_len(el->text);
899 int diff=el->zeropad-ml;
900 if(diff>0){
901 char *tmp=ALLOC_N(char, l+diff+1);
902 if(tmp!=NULL){
903 memset(tmp, '0', diff);
904 memcpy(tmp+diff, el->text, l+1);
905 free(el->text);
906 el->text=tmp;
909 str=el->text;
912 if(el->tmpl!=NULL && el->text!=NULL){
913 char *tmp=grbrush_make_label(sb->brush, el->text, el->max_w);
914 if(tmp!=NULL){
915 free(el->text);
916 el->text=tmp;
917 str=tmp;
921 el->text_w=grbrush_get_text_width(sb->brush, str, strlen(str));
923 if(el->text_w>el->max_w && el->tmpl==NULL){
924 el->max_w=el->text_w;
925 grow=TRUE;
928 attrnm=scat(meter, "_hint");
929 if(attrnm!=NULL){
930 char *s;
931 if(extl_table_gets_s(t, attrnm, &s)){
932 el->attr=stringstore_alloc(s);
933 free(s);
935 free(attrnm);
940 statusbar_rearrange(sb, grow);
942 window_draw((WWindow*)sb, FALSE);
946 /*}}}*/
949 /*{{{ Updategr */
952 void statusbar_updategr(WStatusBar *p)
954 GrBrush *nbrush;
956 nbrush=gr_get_brush(p->wwin.win, region_rootwin_of((WRegion*)p),
957 "stdisp-statusbar");
958 if(nbrush==NULL)
959 return;
961 if(p->brush!=NULL)
962 grbrush_release(p->brush);
964 p->brush=nbrush;
966 statusbar_calc_widths(p);
967 statusbar_rearrange(p, TRUE);
969 window_draw(&(p->wwin), TRUE);
973 /*}}}*/
976 /*{{{ Misc */
979 int statusbar_orientation(WStatusBar *UNUSED(sb))
981 return REGION_ORIENTATION_HORIZONTAL;
985 /*EXTL_DOC
986 * Returns a list of all statusbars.
988 EXTL_EXPORT
989 ExtlTab mod_statusbar_statusbars()
991 ExtlTab t=extl_create_table();
992 WStatusBar *sb;
993 int i=1;
995 for(sb=statusbars; sb!=NULL; sb=sb->sb_next){
996 extl_table_seti_o(t, i, (Obj*)sb);
997 i++;
1000 return t;
1004 WStatusBar *mod_statusbar_find_suitable(WClientWin *cwin,
1005 const WManageParams *param)
1007 WStatusBar *sb;
1009 for(sb=statusbars; sb!=NULL; sb=sb->sb_next){
1010 /*if(!sb->is_auto)
1011 continue;*/
1012 if(!sb->systray_enabled)
1013 continue;
1014 if(!region_same_rootwin((WRegion*)sb, (WRegion*)cwin))
1015 continue;
1016 break;
1019 return sb;
1023 bool statusbar_set_systray(WStatusBar *sb, int sp)
1025 bool set=sb->systray_enabled;
1026 bool nset=libtu_do_setparam(sp, set);
1028 sb->systray_enabled=nset;
1030 return nset;
1034 /*EXTL_DOC
1035 * Enable or disable use of \var{sb} as systray.
1036 * The parameter \var{how} can be one of
1037 * \codestr{set}, \codestr{unset}, or \codestr{toggle}.
1038 * Resulting state is returned.
1040 EXTL_EXPORT_AS(WStatusBar, set_systray)
1041 bool statusbar_set_systray_extl(WStatusBar *sb, const char *how)
1043 return statusbar_set_systray(sb, libtu_string_to_setparam(how));
1047 /*EXTL_DOC
1048 * Is \var{sb} used as a systray?
1050 EXTL_EXPORT_AS(WStatusBar, is_systray)
1051 bool statusbar_is_systray_extl(WStatusBar *sb)
1053 return sb->systray_enabled;
1057 /*}}}*/
1060 /*{{{ Load */
1063 WRegion *statusbar_load(WWindow *par, const WFitParams *fp, ExtlTab tab)
1065 WStatusBar *sb=create_statusbar(par, fp);
1067 if(sb!=NULL){
1068 char *tmpl=NULL;
1069 ExtlTab t=extl_table_none();
1070 if(extl_table_gets_s(tab, "template", &tmpl)){
1071 statusbar_set_template(sb, tmpl);
1072 free(tmpl);
1073 }else if(extl_table_gets_t(tab, "template_table", &t)){
1074 statusbar_set_template_table(sb, t);
1075 extl_unref_table(t);
1076 }else{
1077 const char *tmpl=TR("[ %date || load: %load ] %filler%systray");
1078 statusbar_set_template(sb, tmpl);
1081 extl_table_gets_b(tab, "systray", &sb->systray_enabled);
1084 return (WRegion*)sb;
1088 /*}}}*/
1091 /*{{{ Dynamic function table and class implementation */
1094 static DynFunTab statusbar_dynfuntab[]={
1095 {window_draw, statusbar_draw},
1096 {region_updategr, statusbar_updategr},
1097 {region_size_hints, statusbar_size_hints},
1098 {(DynFun*)region_orientation, (DynFun*)statusbar_orientation},
1100 {region_managed_rqgeom, statusbar_managed_rqgeom},
1101 {(DynFun*)region_prepare_manage, (DynFun*)statusbar_prepare_manage},
1102 {region_managed_remove, statusbar_managed_remove},
1104 {(DynFun*)region_prepare_manage_transient,
1105 (DynFun*)statusbar_prepare_manage_transient},
1107 {region_map, statusbar_map},
1108 {region_unmap, statusbar_unmap},
1110 {(DynFun*)region_fitrep,
1111 (DynFun*)statusbar_fitrep},
1113 END_DYNFUNTAB
1117 EXTL_EXPORT
1118 IMPLCLASS(WStatusBar, WWindow, statusbar_deinit, statusbar_dynfuntab);
1121 /*}}}*/