123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291(**************************************************************************)(* *)(* This file is part of Frama-C. *)(* *)(* Copyright (C) 2007-2023 *)(* CEA (Commissariat à l'énergie atomique et aux énergies *)(* alternatives) *)(* *)(* you can redistribute it and/or modify it under the terms of the GNU *)(* Lesser General Public License as published by the Free Software *)(* Foundation, version 2.1. *)(* *)(* It is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU Lesser General Public License for more details. *)(* *)(* See the GNU Lesser General Public License version 2.1 *)(* for more details (enclosed in the file licenses/LGPLv2.1). *)(* *)(**************************************************************************)openWidget(* -------------------------------------------------------------------------- *)(* --- Forms --- *)(* -------------------------------------------------------------------------- *)typefield=[`Compact|`Field|`Panel]letfexpand=function`Compact->`NONE|`Field->`X|`Panel->`BOTHclassform()=letbox=GPack.table~columns:2~col_spacings:16~homogeneous:false()inobject(self)valmutableline=0valmutableleft=false(* left column fed on current line *)valmutableright=false(* right column fed on current line *)valmutablexpadding=0(* set with sections *)inheritWutil.gobj_widgetboxmethodprivateoccupy_left=ifleft||rightthenline<-succline;left<-true;right<-falsemethodprivateoccupy_right=ifrightthen(line<-succline;left<-false);right<-truemethodprivateoccupy_both=ifleft||rightthenline<-succline;left<-true;right<-truemethodadd_newline=self#occupy_both;letw=GMisc.label~text:""()inbox#attach~left:0~right:2~top:line~ypadding:12~expand:`Yw#coercemethodadd_sectionlabel=self#occupy_both;letw=GMisc.label~text:label~xalign:0.0~yalign:1.0()inWutil.set_bold_fontw;xpadding<-24;box#attach~left:0~right:1~top:line~xpadding:0~ypadding:12~expand:`Yw#coercemethodadd_label_widgetw=self#occupy_left;box#attach~left:0~top:line~xpadding~expand:`NONEwmethodadd_labellabel=letw=GMisc.label~text:label~xalign:1.0()inself#add_label_widgetw#coercemethodadd_field?label?(field:field=`Field)w=Wutil.onlabelself#add_label;self#occupy_right;box#attach~left:1~top:line~expand:(fexpandfield)wmethodadd_row?(field:field=`Field)?(xpadding=xpadding)?ypaddingw=self#occupy_both;box#attach~left:0~right:2~top:line~xpadding?ypadding~expand:(fexpandfield)wend(* -------------------------------------------------------------------------- *)(* --- Extensible Array --- *)(* -------------------------------------------------------------------------- *)classtypeentry=objectmethodwidget:GObj.widgetmethodupdate:unit->unitmethoddelete:unit->unitendletno_entry=fun_->assertfalseclass['a]warray?(dir=`VERTICAL)?(entry=no_entry)()=letbox=GPack.boxdir~homogeneous:false()inobject(self)inheritWutil.gobj_widgetboxvalmutablerows:('a*entry)list=[]valmutablecreator:('a->entry)=entrymethodsetxs=beginList.iter(fun(y,e)->ifnot(List.memyxs)thenbegine#delete();letw=e#widgetinbox#removew;w#destroy();end)rows;rows<-List.map(funx->lete=tryList.assocxrowswithNot_found->lete=creatorxinbox#pack~expand:falsee#widget;einx,e)xs;ignore(List.fold_left(funpos(_,w)->box#reorder_childw#widget~pos;succpos)0rows)endmethodget=List.mapfstrowsmethodmemx=List.mem_assocxrowsmethodprivateothersx=List.fold_right(fun(y,_)ys->ifx=ythenyselsey::ys)rows[]methodappendx=self#set(self#othersx@[x])methodinsert?afterx=letys=self#othersxinletzs=matchafterwith|None->x::ys|Somez->letrechookzx=function|[]->[x]|y::ys->ify=zthenz::x::yselsey::hookzxysinhookzxysinself#setzsmethodremovex=self#set(self#othersx)methodset_entryf=creator<-fmethodupdate()=List.iter(fun(_,e)->e#update())rowsend(* -------------------------------------------------------------------------- *)(* --- Notebook --- *)(* -------------------------------------------------------------------------- *)class['a]notebook?tabs~default()=letview=GPack.notebook~enable_popup:false~show_tabs:false~show:true()inobject(self)valmutablepages:'alist=[]inherit['a]Wutil.selectordefaultasselectmethodadd?labelpagecontent=lettab_label=matchlabelwith|None->None|Sometext->Some(GMisc.label~text())#coerceinpages<-pages@[page];ignore(view#append_page?tab_labelcontent);self#setdefaultmethod!setpage=letrecscanip=function|q::qs->ifp=qthenview#goto_pageielsescan(succi)pqs|[]->()inscan0pagepagesmethodprivateswitchedi=tryselect#set(List.nthpagesi)withInvalid_argument_->()methodon_focuspagef=select#connect(funp->f(page=p))initializerbeginignore(view#connect#switch_page~callback:self#switched);Wutil.ontabs(funp->view#set_show_tabstrue;view#set_tab_posp);endmethodcoerce=view#coercemethodwidget=(self:>Widget.t)method!set_enabled=Wutil.set_enabledviewmethodset_visible=Wutil.set_visibleviewend(* -------------------------------------------------------------------------- *)(* --- Dialogs --- *)(* -------------------------------------------------------------------------- *)type'aaction=[|`CANCEL|`APPLY|`DEFAULTof'a|`SELECTof'a|`ALTof'a|`ACTIONof(unit->unit)]class['a]dialog~title~window?(resize=false)()=letshell=GWindow.window~title~kind:`TOPLEVEL~modal:true~show:false~decorated:true~position:`CENTER_ON_PARENT~resizable:resize()inlethclip=GBin.alignment~packing:shell#add()inletvbox=GPack.vbox~homogeneous:false~spacing:6~packing:hclip#add()inletvclip=GBin.alignment~packing:(vbox#pack~from:`END~expand:false)()inlethbox=GPack.hbox~homogeneous:false~spacing:32~packing:vclip#add()inletalt_box=GPack.hbox~homogeneous:true~spacing:6~packing:(hbox#pack~expand:true~fill:false)()inletmain_box=GPack.hbox~homogeneous:true~spacing:6~packing:(hbox#pack~expand:true~fill:false)()inobject(self)constraint'a=[>`CANCEL|`APPLY]inherit['a]Wutil.signalvalmutabledefw=(fun()->())methodadd_roww=vbox#pack~from:`START~expand:falsewmethodadd_blockw=vbox#pack~from:`START~expand:truewmethodbutton~(action:'aaction)?label?icon?tooltip()=letw=newbutton?label?icon?tooltip()inletbox=matchactionwith|`DEFAULT_|`APPLY->defw<-w#default;main_box|`SELECT_|`CANCEL->main_box|`ALT_|`ACTION_->alt_boxinbox#pack~expand:falsew#coerce;matchactionwith|`ALTr|`SELECTr|`DEFAULTr->w#connect(fun()->self#selectr)|`CANCEL->w#connect(fun()->self#select`CANCEL)|`APPLY->w#connect(fun()->self#select`APPLY)|`ACTIONf->w#connectfmethodselectr=beginwindow#misc#set_sensitivetrue;shell#misc#hide();self#firer;endmethodrun()=beginwindow#misc#set_sensitivefalse;shell#show();defw();endinitializerbeginhclip#set_top_padding4;hclip#set_bottom_padding4;hclip#set_left_padding24;hclip#set_right_padding24;ignore(shell#event#connect#delete~callback:(fun_->self#select`CANCEL;true));(* returning [true] prevent the dialog from being destroyed *)endend