Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file b_button.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182(** a clickable button *)(* TODO click on an image *)(* TODO in case of Switch, dim the label when not selected *)(* ==> label_on, label_off ? *)openB_utilsmoduleTheme=B_thememoduleVar=B_varmoduleDraw=B_drawmoduleStyle=B_stylemoduleBox=B_boxmoduleLabel=B_labelmoduleTrigger=B_triggertypekind=|Trigger(* one action when pressed. TODO, better to avoid name clash with
Trigger module*)|Switch(* two states *)typet={label_on:Label.t;label_off:Label.t;state:boolVar.t;pressed:boolVar.t;mutablemouse_over:bool;box_on:Box.t;(* TODO Var.t ? *)box_off:Box.t;(* TODO Var.t ? *)box_over:Box.toption}letcolor_on=Draw.find_colorTheme.button_color_onletcolor_off=Draw.find_colorTheme.button_color_off(* if label_on and/or label_off is provided, then label is ignored *)letcreate?size?border_radius?border_color?fg?(bg_on=Style.color_bgDraw.(opaquecolor_on))?(bg_off=Style.color_bgDraw.(opaquecolor_off))?bg_over?label?label_on?label_off?(state=false)text=letlabel_on,label_off=matchlabel,label_on,label_offwith|None,None,None->letl=Label.create?size?fgtextinl,l|Somel,None,None->l,l|None,_,_->default_lazylabel_on(lazy(Label.create?size?fgtext)),default_lazylabel_off(lazy(Label.create?size?fgtext))|_->printddebug_warning"label argument was ignored because label_on and/or \
label_off was provided";default_lazylabel_on(lazy(Label.create?size?fgtext)),default_lazylabel_off(lazy(Label.create?size?fgtext))inletborder_on,border_off=matchborder_color,border_radiuswith|None,None->None,None|None,Someradius->SomeStyle.(mk_border~radius(mk_line~color:(Style.get_colorbg_on)())),SomeStyle.(mk_border~radius(mk_line~color:(Style.get_colorbg_off)()))|_->lets=Style.(mk_border?radius:border_radius(mk_line?color:border_color()))inSomes,Somesinletstyle_on=Style.create~background:bg_on?border:border_on()inletstyle_off=Style.create~background:bg_off?border:border_off()in{label_on;label_off;state=Var.createstate;pressed=Var.createstate;mouse_over=false;box_on=Box.(create~style:style_on());box_off=Box.(create~style:style_off());box_over=map_optionbg_over(funbg->letstyle=Style.create~background:bg()inBox.create~style())}letunloadl=Label.unloadl.label_on;Label.unloadl.label_off;Box.unloadl.box_on;Box.unloadl.box_off;do_optionl.box_overBox.unload(* TODO *)letfree=unloadletstateb=Var.getb.statelettextb=ifstatebthenLabel.textb.label_onelseLabel.textb.label_offletset_labelbtext=ifstatebthenLabel.setb.label_ontextelseLabel.setb.label_offtextletis_pressedb=Var.getb.pressed(* called on button_down *)letpressb=Var.setb.pressedtrueletresetb=Var.setb.pressedfalse;Var.setb.statefalseletsetbs=Var.setb.presseds;Var.setb.states(* called on button up for Trigger *)letreleaseb=(* TODO: verify true click *)ifis_pressedbthenbeginVar.setb.pressedfalse;Var.setb.state(not(Var.getb.state))(* TODO; this is not exactly what we want with Trigger *)end(* called by button_up in case of kind=Switch *)letswitchbev=ifTrigger.has_full_clickevthenbeginVar.setb.state(not(Var.getb.state));printddebug_event"Switch button to [pressed=%b] [state=%b]"(is_pressedb)(Var.getb.state);end;Var.setb.pressed(Var.getb.state)letmouse_enterb=b.mouse_over<-trueletmouse_leaveb=b.mouse_over<-false(************* display ***********)letbutton_margin=6;;(* logical size - TODO theme this var ? *)letbm=Theme.scale_intbutton_margin(* The size of the widget is dictated by the size of the labels *)letsizeb=let(w,h)=Label.sizeb.label_oninlet(w',h')=Label.sizeb.label_offinletw=imaxww'andh=imaxhh'in(w+2*button_margin,h+2*button_margin)(* For safety (?), if the size is too small, the check icon is not clipped (see
[display] below). *)letresize(w,h)b=letsize=w-2*button_margin,h-2*button_margininList.iter(Label.resizesize)[b.label_on;b.label_off];List.iter(Box.resize(w,h))[b.box_on;b.box_off];do_optionb.box_over(Box.resize(w,h))letdisplaycanvaslayerbg=let(dx,dy)=ifis_pressedbthen(0,1)else(0,0)inletbox=ifis_pressedbthenb.box_onelseifb.mouse_overthendefaultb.box_overb.box_offelseb.box_offin(*let margin = if is_pressed b then 0 else button_margin in*)(* Draw.box canvas.Draw.renderer ~bg (x+margin) (y+margin) (w-2*margin) (h-2*margin); *)letbox_blit=Box.displaycanvaslayerboxDraw.({x=g.x(* + margin *);y=g.y(* + margin *);w=g.w;h=g.h;voffset=g.voffset})inletlabel_blit=Label.displaycanvaslayer(ifstatebthenb.label_onelseb.label_off)Draw.({x=g.x+bm+dx;y=g.y+bm+dy;w=g.w-2*bm;h=g.h-2*bm;voffset=g.voffset})inList.concat[box_blit;label_blit]