123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206(*
* lTerm_buttons_impl.ml
* ---------------------
* Copyright : (c) 2011, Jeremie Dimino <jeremie@dimino.org>
* Licence : BSD3
*
* This file is a part of Lambda-Term.
*)moduleMake(LiteralIntf:LiteralIntf.Type)=structopenLTerm_geomopenLTerm_keyopenLTerm_mouseopenLTerm_widget_callbacksletsection=Lwt_log.Section.make"lambda-term(buttons_impl)"classt=LTerm_widget_base_impl.tletspace=Char(Uchar.of_char' ')classbutton?bracketsinitial_label=let(bl,br)=matchbracketswith|Some(bl,br)->LiteralIntf.to_string_exnbl,LiteralIntf.to_string_exnbr|None->Zed_string.unsafe_of_utf8"< ",Zed_string.unsafe_of_utf8" >"inletbrackets_size=LTerm_text.aval_width(Zed_string.widthbl)+LTerm_text.aval_width(Zed_string.widthbr)inobject(self)inheritt"button"method!can_focus=truevalclick_callbacks=LTerm_widget_callbacks.create()methodon_click?switchf=registerswitchclick_callbacksfvalmutablesize_request={rows=1;cols=brackets_size+(LTerm_text.aval_width(Zed_string.width(LiteralIntf.to_string_exninitial_label)))}method!size_request=size_requestvalmutablelabel=LiteralIntf.to_string_exninitial_labelmethodlabel=LiteralIntf.of_stringlabelmethodlabel_zed=labelmethodset_labeltext=lettext=LiteralIntf.to_string_exntextinlabel<-text;size_request<-{rows=1;cols=brackets_size+(LTerm_text.aval_width(Zed_string.widthtext))};self#queue_drawinitializerself#on_event(function|LTerm_event.Key{control=false;meta=false;shift=false;code=Enter}->exec_callbacksclick_callbacks();true|LTerm_event.Mousemwhenm.button=Button1->exec_callbacksclick_callbacks();true|_->false)valmutablefocused_style=LTerm_style.nonevalmutableunfocused_style=LTerm_style.nonemethod!update_resources=letrc=self#resource_classandresources=self#resourcesinfocused_style<-LTerm_resources.get_style(rc^".focused")resources;unfocused_style<-LTerm_resources.get_style(rc^".unfocused")resourcesmethodprivateapply_stylectxfocused=letstyle=iffocused=(self:>t)thenfocused_styleelseunfocused_styleinLTerm_draw.fill_stylectxstylemethod!drawctxfocused=let{rows;cols}=LTerm_draw.sizectxinletwidth=LTerm_text.aval_width(Zed_string.widthlabel)inself#apply_stylectxfocused;LTerm_draw.draw_stringctx(rows/2)((cols-width-brackets_size)/2)(Zed_string.append(Zed_string.appendbllabel)br)endclasscheckbuttoninitial_labelinitial_state=object(self)inheritbuttoninitial_labelvalmutablestate=initial_stateinitializerself#on_event(funev->letupdate()=state<-notstate;(* checkbutton changes the state when clicked, so has to be redrawn *)self#queue_draw;exec_callbacksclick_callbacks();trueinmatchevwith|LTerm_event.Key{control=false;meta=false;shift=false;code}when(code=Enter||code=space)->update()|LTerm_event.Mousemwhenm.button=Button1->update()|_->false);self#set_resource_class"checkbutton"methodstate=statemethod!drawctxfocused=let{rows;_}=LTerm_draw.sizectxinletchecked=Zed_string.unsafe_of_utf8(ifstatethen"[x] "else"[ ] ")inself#apply_stylectxfocused;LTerm_draw.draw_stringctx(rows/2)0(Zed_string.appendcheckedlabel);endclasstype['a]radio=objectmethodon:unitmethodoff:unitmethodid:'aendclass['a]radiogroup=objectvalstate_change_callbacks=LTerm_widget_callbacks.create()methodon_state_change?switchf=registerswitchstate_change_callbacksfvalmutablestate=Nonevalmutablebuttons=[]methodstate=statemethodregister_object(button:'aradio)=(* Switch the first button added to group to 'on' state *)ifbuttons=[]thenbutton#onelse();buttons<-button::buttons;()methodswitch_tosome_id=letswitch_buttonbutton=ifbutton#id=some_idthenbutton#onelsebutton#offinList.iterswitch_buttonbuttons;state<-Somesome_id;exec_callbacksstate_change_callbacksstateendclass['a]radiobutton(group:'aradiogroup)initial_label(id:'a)=object(self)inheritbuttoninitial_labelvalmutablestate=falseinitializerself#on_event(funev->letupdate()=ifstate(* no need to do anything if the button is on already *)then()elsegroup#switch_toid;(* event is consumed in any case *)exec_callbacksclick_callbacks();trueinmatchevwith|LTerm_event.Key{control=false;meta=false;shift=false;code}when(code=Enter||code=space)->update()|LTerm_event.Mousemwhenm.button=Button1->update()|_->false);self#set_resource_class"radiobutton";group#register_object(self:>'aradio)method!drawctxfocused=let{rows;_}=LTerm_draw.sizectxinletchecked=Zed_string.unsafe_of_utf8(ifstatethen"(o) "else"( ) ")inself#apply_stylectxfocused;LTerm_draw.draw_stringctx(rows/2)0(Zed_string.appendcheckedself#label_zed);methodstate=statemethodon=state<-true;self#queue_drawmethodoff=state<-false;self#queue_drawmethodid=idendend