Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file util.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270open!Core_kernelopen!ImportopenJs_of_ocamlmoduleFocus_dir=structtypet=|Prev|Next[@@derivingsexp,compare]endmoduleMargin=structtypet={top:float;left:float;bottom:float;right:float}[@@derivingfields,compare,sexp_of]letuniformmargin={top=margin;left=margin;bottom=margin;right=margin}letnone=uniform0.letcreate?(top=0.)?(left=0.)?(bottom=0.)?(right=0.)()={top;left;bottom;right};;letadjust?(top=0.)?(left=0.)?(bottom=0.)?(right=0.)t={top=t.top+.top;left=t.left+.left;bottom=t.bottom+.bottom;right=t.right+.right};;endmoduleScroll_region=structtypet=|Window|ElementofJs_of_ocaml.Dom_html.elementJs_of_ocaml.Js.tmoduleId=structtypet=|Window|Elementofstring[@@derivingcompare,sexp]endletof_id:Id.t->toption=function|Window->SomeWindow|Elementid->Option.map(Dom_html.getElementById_optid)~f:(funel->Elementel);;endmoduleFloat_type=structtypet=|None|Edge|Px_from_edgeofint[@@derivingcompare,sexp]letcompute_offsett~get_float_elem_size=matchtwith|None->0.|Edge->Option.value(get_float_elem_size())~default:0.|Px_from_edgepx->Option.value_map(get_float_elem_size())~f:(funsize->size+.Float.of_intpx)~default:0.;;letis_floating=function|None->false|Edge|Px_from_edge_->true;;letpx_from_edge:t->intoption=function|None->None|Edge->Some0|Px_from_edgepx->Somepx;;endmoduleScroll_result=structtypet=[`Scrolled|`Didn't_scroll]letcombinet1t2=matcht1,t2with|`Didn't_scroll,`Didn't_scroll->`Didn't_scroll|`Scrolled,_|_,`Scrolled->`Scrolled;;letscrolled=function|`Scrolled->true|`Didn't_scroll->false;;endmoduleScroll=structmoduleDir=structtypet=|Horizontal|Verticalendletscroll?(in_=Scroll_region.Window)(dir:Dir.t)shift=ifFloat.equalshift0.then`Didn't_scrollelse(letshift=Float.iround_nearest_exnshiftin(matchin_,dirwith|Window,Horizontal->Dom_html.window##scrollByshift0|Window,Vertical->Dom_html.window##scrollBy0shift|Elementel,Horizontal->el##.scrollLeft:=el##.scrollLeft+shift|Elementel,Vertical->el##.scrollTop:=el##.scrollTop+shift);`Scrolled);;letadjust_margins~start_margin~end_margin~scroll_region_start~scroll_region_end~elem_start~elem_end=letunused_viewport_space=scroll_region_end-.scroll_region_start-.(elem_end-.elem_start)inlettotal_margin=start_margin+.end_margininletscale_downm=m*.unused_viewport_space/.total_margininifFloat.is_negativeunused_viewport_spacethen0.,0.elseifFloat.(<)unused_viewport_spacetotal_marginthenscale_downstart_margin,scale_downend_marginelsestart_margin,end_margin;;letoverflow_past_start~scroll_region_start~start_margin~elem_start=letstart_boundary=scroll_region_start+.start_margininOption.some_if(Float.(<)elem_startstart_boundary)(elem_start-.start_boundary);;letoverflow_past_end~scroll_region_end~end_margin~elem_end=letend_boundary=scroll_region_end-.end_margininOption.some_if(Float.(>)elem_endend_boundary)(elem_end-.end_boundary);;letscroll_into_region?in_dir~start_margin~end_margin~scroll_region_start~scroll_region_end~elem_start~elem_end=letstart_margin,end_margin=adjust_margins~start_margin~end_margin~scroll_region_start~scroll_region_end~elem_start~elem_endinletstart_overflow=overflow_past_start~scroll_region_start~start_margin~elem_startinletend_overflow=overflow_past_end~scroll_region_end~end_margin~elem_endinletshift=matchstart_overflow,end_overflowwith|None,None->0.|Someshift,None|Someshift,Some_->shift|None,Someshift->(* Do not shift element start past the start margin *)letexcess_shift=overflow_past_start~scroll_region_start~start_margin~elem_start:(elem_start-.shift)|>Option.value~default:0.inshift+.excess_shiftinscroll?in_dirshift;;letis_in_region~start_margin~end_margin~scroll_region_start~scroll_region_end~elem_start~elem_end=letstart_margin,end_margin=adjust_margins~start_margin~end_margin~scroll_region_start~scroll_region_end~elem_start~elem_endinOption.is_none(overflow_past_start~scroll_region_start~start_margin~elem_start)&&Option.is_none(overflow_past_end~scroll_region_end~end_margin~elem_end);;letget_elem_start~scroll_region_start~position=scroll_region_start+.positionletget_position~scroll_region_start~elem_start=elem_start-.scroll_region_startletscroll_to_position?in_dir~position~scroll_region_start~elem_start=lettarget_elem_start=get_elem_start~scroll_region_start~positioninletshift=elem_start-.target_elem_startinscroll?in_dirshift;;letscroll_to_position_and_into_region?in_dir~position~start_margin~end_margin~scroll_region_start~scroll_region_end~elem_start~elem_end=lettarget_elem_start=get_elem_start~scroll_region_start~positioninletshift=elem_start-.target_elem_startinletscroll_to_position=scroll?in_dirshiftinlettarget_elem_end=target_elem_start+.elem_end-.elem_startinletscroll_into_region=scroll_into_region?in_dir~start_margin~end_margin~scroll_region_start~scroll_region_end~elem_start:target_elem_start~elem_end:target_elem_endinScroll_result.combinescroll_to_positionscroll_into_region;;endletmove_focusmapfocus(dir:Focus_dir.t)=matchfocuswith|None->(* If there's no focus, we grab the extreme element, depending on the direction of
movement. *)(matchdirwith|Prev->Map.max_eltmap|Next->Map.min_eltmap)|Somekey->(* If we are focused, then just move to the next key in the map. *)letdir=matchdirwith|Prev->`Less_than|Next->`Greater_thaninMap.closest_keymapdirkey;;