123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687(** group layouts into tabs *)openB_utilsmoduleLayout=B_layoutmoduleTrigger=B_triggermoduleDraw=B_drawmoduleButton=B_buttonmoduleStyle=B_stylemoduleTheme=B_thememoduleW=B_widgetletbg_on=Style.gradientDraw.[opaqueButton.color_off;opaqueButton.color_off;opaqueButton.color_on](* Style.gradient Draw.[opaque white;opaque pale_grey;opaque pale_grey;opaque pale_grey];; *)letbg_off=Style.SolidDraw.(opaqueButton.color_off)(* Style.gradient Draw.[opaque pale_grey;opaque grey;opaque grey;opaque grey];; *)(* On attache tous les rooms dans le layout (en mode "superposition"), et on met
en show=true celui qu'on veut. Ça permet de les nettoyer correctement tous, à
l'extinction. Cependant, ce n'est pas optimisé au cas où il y a des millions
de tabs (peu probable ...) car la boucle de display va les passer tous en
revue pour trouver celui à montrer. Au départ on ne mettait dans le layout
que le tab actif; l'inconvénient était que tous les autres n'étaient pas
"visibles" par bogue, et donc n'étaient pas nettoyés en quittant. D'autre
part, ça forçait à "modifier" le contenu du layout à chaque changement de tab
actif, ce qui n'est pas très joli. *)letcreate_one?slidetitleroomdest_room=(* The button is neither normal Trigger nor Switch since once selected it
cannot be unselected by clicking on it. *)letl=W.create_empty(W.Button(Button.create~bg_on~bg_offButton.Triggertitle))in(* the first action sets the button to 'pressed' when we click (button_down)
on it. Below we will add another action to reset all other buttons to 'not
pressed' *)letonpressw__=letb=W.get_buttonwinifnot(Button.is_pressedb)&¬(Layout.is_shownroom)thenbeginButton.pressb;Layout.iter_rooms(funl->Layout.set_showlfalse)dest_room;Layout.set_showroomtrue;do_optionslide(funfrom->Layout.slide_in~from~dst:dest_roomroom);W.updatew;(* or refresh only layout ? *)endinletc=W.connect_mainllonpressTrigger.(E.key_down::buttons_down)inW.add_connectionlc;l(** create tabs from a assoc list ("title"; layout) *)(* TODO, return a function that can be called to activate tab #i *)letcreate(*?(circular = true)*)?slide?(adjust=Layout.Fit)?(expand=true)?canvas?(name="tabs")list=iflist=[]thenfailwith"Cannot create empty tabs"elsebeginlet_,first_room=List.hdlistinletall_rooms=List.mapsndlistinList.iter(funl->Layout.set_showlfalse)all_rooms;Layout.set_showfirst_roomtrue;letdest_room=Layout.superpose?canvasall_roomsinletlabels=List.map(fun(title,layout)->create_one?slidetitlelayoutdest_room)listinletreset_other_labelsw__=List.iter(funb->ifnot(W.equalwb)thenButton.reset(W.get_buttonb))labels;(* + refresh ? *)inList.iter(funl->letc=W.connect_mainllreset_other_labelsTrigger.(E.key_down::buttons_down)inW.add_connectionlc)labels;(* We activate the first label (TODO: choose which one) *)letfirst_l=List.hdlabelsinButton.press(W.get_buttonfirst_l);letmenu=Layout.flat_of_w~name:(name^".menu")?canvas~sep:0labelsinifexpandthenLayout.(set_widthmenu(widthdest_room));lettabs=Layout.tower~name~sep:0~adjust?canvas[menu;dest_room]inifexpandthenmenu.resize<-(fun(w,_)->Layout.Resize.set_widthmenu(w-2*Theme.room_margin))elseLayout.disable_resizemenu;tabsend