123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458(* Contains GridItem used to represent a single grid item during layout *)openGeometryopenStyleopenStyle.GridopenTree(* Type alias for origin zero line *)typeorigin_zero_line=int(* Represents a single grid item *)typet={node:Node_id.t;(* The id of the node that this item represents *)source_order:int;(* The order of the item in the children array We sort the list of grid
items during track sizing. This field allows us to sort back the
original order for final positioning *)row:origin_zero_lineline;(* The item's definite row-start and row-end, as resolved by the placement
algorithm (in origin-zero coordinates) *)column:origin_zero_lineline;(* The items definite column-start and column-end, as resolved by the
placement algorithm (in origin-zero coordinates) *)is_compressible_replaced:bool;(* Is it a compressible replaced element?
https://drafts.csswg.org/css-sizing-3/#min-content-zero *)overflow:overflowpoint;(* The item's overflow style *)box_sizing:box_sizing;(* The item's box_sizing style *)size:dimensionsize;(* The item's size style *)min_size:dimensionsize;(* The item's min_size style *)max_size:dimensionsize;(* The item's max_size style *)aspect_ratio:floatoption;(* The item's aspect_ratio style *)padding:length_percentagerect;(* The item's padding style *)border:length_percentagerect;(* The item's border style *)margin:length_percentage_autorect;(* The item's margin style *)align_self:align_self;(* The item's align_self property, or the parent's align_items property is
not set *)justify_self:justify_self;(* The item's justify_self property, or the parent's justify_items
property is not set *)mutablebaseline:floatoption;(* The items first baseline (horizontal) *)mutablebaseline_shim:float;(* Shim for baseline alignment that acts like an extra top margin *)mutablerow_indexes:intline;(* The item's definite row-start and row-end (same as `row` field, except
in a different coordinate system) (as indexes into the Vec<GridTrack>
stored in a grid's AbstractAxisTracks) *)mutablecolumn_indexes:intline;(* The items definite column-start and column-end (same as `column` field,
except in a different coordinate system) (as indexes into the
Vec<GridTrack> stored in a grid's AbstractAxisTracks) *)mutablecrosses_flexible_row:bool;(* Whether the item crosses a flexible row *)mutablecrosses_flexible_column:bool;(* Whether the item crosses a flexible column *)mutablecrosses_intrinsic_row:bool;(* Whether the item crosses a intrinsic row *)mutablecrosses_intrinsic_column:bool;(* Whether the item crosses a intrinsic column *)(* Caches for intrinsic size computation. These caches are only valid for a single run of the track-sizing algorithm. *)mutableavailable_space_cache:floatoptionsizeoption;(* Cache for the known_dimensions input to intrinsic sizing computation *)mutablemin_content_contribution_cache:floatoptionsize;(* Cache for the min-content size *)mutableminimum_contribution_cache:floatoptionsize;(* Cache for the minimum contribution *)mutablemax_content_contribution_cache:floatoptionsize;(* Cache for the max-content size *)mutabley_position:float;(* Final y position. Used to compute baseline alignment for the
container *)mutableheight:float;(* Final height. Used to compute baseline alignment for the container *)}(* Create a new item given a concrete placement in both axes *)letnew_with_placement_style_and_order~node~col_span~row_span~style~parent_align_items~parent_justify_items~source_order={node;source_order;row=row_span;column=col_span;is_compressible_replaced=Style.is_compressible_replacedstyle;overflow=Style.overflowstyle;box_sizing=Style.box_sizingstyle;size=Style.sizestyle;min_size=Style.min_sizestyle;max_size=Style.max_sizestyle;aspect_ratio=Style.aspect_ratiostyle;padding=Style.paddingstyle;border=Style.borderstyle;margin=Style.marginstyle;align_self=Option.value(Style.align_selfstyle)~default:parent_align_items;justify_self=Option.value(Style.justify_selfstyle)~default:parent_justify_items;baseline=None;baseline_shim=0.0;row_indexes=Line.make00;(* Properly initialised later *)column_indexes=Line.make00;(* Properly initialised later *)crosses_flexible_row=false;(* Properly initialised later *)crosses_flexible_column=false;(* Properly initialised later *)crosses_intrinsic_row=false;(* Properly initialised later *)crosses_intrinsic_column=false;(* Properly initialised later *)available_space_cache=None;min_content_contribution_cache=Size.none;max_content_contribution_cache=Size.none;minimum_contribution_cache=Size.none;y_position=0.0;height=0.0;}(* This item's placement in the specified axis in OriginZero coordinates *)letplacementtaxis=matchaxiswith|Abstract_axis.Block->t.row|Abstract_axis.Inline->t.column(* This item's placement in the specified axis as GridTrackVec indices *)letplacement_indexestaxis=matchaxiswith|Abstract_axis.Block->t.row_indexes|Abstract_axis.Inline->t.column_indexes(* Returns a range which can be used as an index into the GridTrackVec in the
specified axis which will produce a sub-slice of covering all the tracks and
lines that this item spans excluding the lines that bound it *)lettrack_range_excluding_linestaxis=letindexes=placement_indexestaxisin(indexes.start+1,indexes.end_)(* Returns the number of tracks that this item spans in the specified axis *)letspantaxis=matchaxiswith|Abstract_axis.Block->max(t.row.end_-t.row.start)0|Abstract_axis.Inline->max(t.column.end_-t.column.start)0(* Returns the pre-computed value indicating whether the grid item crosses a
flexible track in the specified axis *)letcrosses_flexible_tracktaxis=matchaxiswith|Abstract_axis.Inline->t.crosses_flexible_column|Abstract_axis.Block->t.crosses_flexible_row(* Returns the pre-computed value indicating whether the grid item crosses an
intrinsic track in the specified axis *)letcrosses_intrinsic_tracktaxis=matchaxiswith|Abstract_axis.Inline->t.crosses_intrinsic_column|Abstract_axis.Block->t.crosses_intrinsic_row(* For an item spanning multiple tracks, the upper limit used to calculate its
limited min-/max-content contribution is the sum of the fixed max track
sizing functions of any tracks it spans, and is applied if it only spans such
tracks *)letspanned_track_limittaxisaxis_tracksaxis_parent_sizeresolve_calc_value=letstart_idx,end_idx=track_range_excluding_linestaxisinletspanned_tracks=Array.subaxis_tracksstart_idx(end_idx-start_idx)inlettracks_all_fixed=Array.for_all(funtrack->(* Check if the max track sizing function has a definite limit *)Option.is_some(Track_sizing_function.Max.definite_limit_with_calctrack.Grid_track.track_sizing_functionaxis_parent_sizeresolve_calc_value))spanned_tracksiniftracks_all_fixedthenletlimit=Array.fold_left(funacctrack->letlimit=Option.get(Track_sizing_function.Max.definite_limit_with_calctrack.Grid_track.track_sizing_functionaxis_parent_sizeresolve_calc_value)inacc+.limit)0.0spanned_tracksinSomelimitelseNone(* Compute the known_dimensions to be passed to the child sizing functions The
key thing that is being done here is applying stretch alignment, which is
necessary to allow percentage sizes further down the tree to resolve properly
in some cases *)letknown_dimensions(typetree)(moduleTree:Tree.LAYOUT_PARTIAL_TREEwithtypet=tree)(t:t)(tree:tree)(inner_node_size:floatoptionsize)(grid_area_size:floatoptionsize):floatoptionsize=letcalc=Tree.resolve_calc_valuetreein(* Compute margins *)letmargins=letinner_node_width=inner_node_size.widthinletmargin_rect=Rect.{left=Length_percentage_auto.resolve_or_zerot.margin.left(Some0.0)calc;right=Length_percentage_auto.resolve_or_zerot.margin.right(Some0.0)calc;top=Length_percentage_auto.resolve_or_zerot.margin.topinner_node_widthcalc+.t.baseline_shim;bottom=Length_percentage_auto.resolve_or_zerot.margin.bottominner_node_widthcalc;}inRect.sum_axesmargin_rectin(* Resolve padding and border *)letpadding=Rect.map(funlp->Length_percentage.resolve_or_zerolpgrid_area_size.widthcalc)t.paddinginletborder=Rect.map(funlp->Length_percentage.resolve_or_zerolpgrid_area_size.widthcalc)t.borderinletpadding_border_size=Rect.sum_axes(Rect.addpaddingborder)inletbox_sizing_adjustment=ift.box_sizing=Box_sizing.Content_boxthenpadding_border_sizeelseSize.zeroin(* Resolve inherent size *)letinherent_size=Size.map2(fundimgrid_size->Dimension.maybe_resolvedimgrid_sizecalc)t.sizegrid_area_size|>Size.apply_aspect_ratiot.aspect_ratio|>Size.maybe_addbox_sizing_adjustmentin(* Resolve min/max sizes *)letmin_size=Size.map2(fundimgrid_size->Dimension.maybe_resolvedimgrid_sizecalc)t.min_sizegrid_area_size|>Size.apply_aspect_ratiot.aspect_ratio|>Size.maybe_addbox_sizing_adjustmentinletmax_size=Size.map2(fundimgrid_size->Dimension.maybe_resolvedimgrid_sizecalc)t.max_sizegrid_area_size|>Size.apply_aspect_ratiot.aspect_ratio|>Size.maybe_addbox_sizing_adjustmentinletgrid_area_minus_item_margins_size=Size.maybe_submarginsgrid_area_sizein(* Apply stretch alignment for width *)letwidth=matchinherent_size.widthwith|Somew->Somew|None->if(not(Length_percentage_auto.is_autot.margin.left))&&(not(Length_percentage_auto.is_autot.margin.right))&&t.justify_self=Stretchthengrid_area_minus_item_margins_size.widthelseNonein(* Reapply aspect ratio after stretch *)letsize_after_width=Size.{width;height=inherent_size.height}inletsize_after_width=Size.apply_aspect_ratiot.aspect_ratiosize_after_widthin(* Apply stretch alignment for height *)letheight=matchsize_after_width.heightwith|Someh->Someh|None->if(not(Length_percentage_auto.is_autot.margin.top))&&(not(Length_percentage_auto.is_autot.margin.bottom))&&t.align_self=Stretchthengrid_area_minus_item_margins_size.heightelseNonein(* Reapply aspect ratio after stretch *)letfinal_size=Size.{width=size_after_width.width;height}inletfinal_size=Size.apply_aspect_ratiot.aspect_ratiofinal_sizein(* Clamp by min/max *)Size.clamp_optionmin_sizemax_sizefinal_size(* Similar to the spanned_track_limit, but excludes FitContent arguments from
the limit. Used to clamp the automatic minimum contributions of an item *)letspanned_fixed_track_limittaxisaxis_tracksaxis_parent_sizeresolve_calc_value=letstart_idx,end_idx=track_range_excluding_linestaxisinletspanned_tracks=Array.subaxis_tracksstart_idx(end_idx-start_idx)inlettracks_all_fixed=Array.for_all(funtrack->(* Check if the max track sizing function has a definite value *)Option.is_some(Track_sizing_function.Max.definite_value_with_calctrack.Grid_track.track_sizing_functionaxis_parent_sizeresolve_calc_value))spanned_tracksiniftracks_all_fixedthenletlimit=Array.fold_left(funacctrack->letlimit=Option.get(Track_sizing_function.Max.definite_value_with_calctrack.Grid_track.track_sizing_functionaxis_parent_sizeresolve_calc_value)inacc+.limit)0.0spanned_tracksinSomelimitelseNone(* Compute the item's min content contribution from the provided parameters *)letmin_content_contribution(typetree)(moduleTree:Tree.LAYOUT_PARTIAL_TREEwithtypet=tree)taxistreeavailable_spaceinner_node_size=letknown_dimensions=known_dimensions(moduleTree)ttreeinner_node_sizeavailable_spaceinTree.compute_child_layouttreet.node(Layout_input.make~known_dimensions~parent_size:inner_node_size~available_space:(Size.map(funopt->matchoptwith|Somesize->Available_space.Definitesize|None->Available_space.Min_content)available_space)~sizing_mode:Sizing_mode.Inherent_size~run_mode:Run_mode.Compute_size~axis:(matchaxiswith|Abstract_axis.Inline->Requested_axis.Horizontal|Abstract_axis.Block->Requested_axis.Vertical)~vertical_margins_are_collapsible:Line.both_false)|>Layout_output.size|>funs->matchaxiswith|Abstract_axis.Inline->s.width|Abstract_axis.Block->s.height(* Retrieve the item's min content contribution from the cache or compute it
using the provided parameters *)letmin_content_contribution_cachedtaxis(typetree)(moduleTree:Tree.LAYOUT_PARTIAL_TREEwithtypet=tree)treeavailable_spaceinner_node_size=matchSize.getaxist.min_content_contribution_cachewith|Somecached_value->cached_value|None->letcontribution=min_content_contribution(moduleTree)taxistreeavailable_spaceinner_node_sizeint.min_content_contribution_cache<-Size.setaxis(Somecontribution)t.min_content_contribution_cache;contribution(* Compute the item's max content contribution from the provided parameters *)letmax_content_contribution(typetree)(moduleTree:Tree.LAYOUT_PARTIAL_TREEwithtypet=tree)taxistreeavailable_spaceinner_node_size=letknown_dimensions=known_dimensions(moduleTree)ttreeinner_node_sizeavailable_spaceinTree.compute_child_layouttreet.node(Layout_input.make~known_dimensions~parent_size:inner_node_size~available_space:(Size.map(funopt->matchoptwith|Somesize->Available_space.Definitesize|None->Available_space.Max_content)available_space)~sizing_mode:Sizing_mode.Inherent_size~run_mode:Run_mode.Compute_size~axis:(matchaxiswith|Abstract_axis.Inline->Requested_axis.Horizontal|Abstract_axis.Block->Requested_axis.Vertical)~vertical_margins_are_collapsible:Line.both_false)|>Layout_output.size|>funs->matchaxiswith|Abstract_axis.Inline->s.width|Abstract_axis.Block->s.height(* Retrieve the item's max content contribution from the cache or compute it
using the provided parameters *)letmax_content_contribution_cachedtaxis(typetree)(moduleTree:Tree.LAYOUT_PARTIAL_TREEwithtypet=tree)treeavailable_spaceinner_node_size=matchSize.getaxist.max_content_contribution_cachewith|Somecached_value->cached_value|None->letcontribution=max_content_contribution(moduleTree)taxistreeavailable_spaceinner_node_sizeint.max_content_contribution_cache<-Size.setaxis(Somecontribution)t.max_content_contribution_cache;contribution(* Compute the available space for an item in a given axis based on the tracks
it spans *)letavailable_spacetaxisother_axis_tracksother_axis_available_spaceget_track_size_estimate=letother_axis=Abstract_axis.otheraxisinletstart_idx,end_idx=track_range_excluding_linestother_axisinletspanned_tracks=Array.subother_axis_tracksstart_idx(end_idx-start_idx)inletitem_other_axis_size=Array.fold_left(funacctrack->matchaccwith|None->None|Somesum->(matchget_track_size_estimatetrackother_axis_available_spacewith|None->None|Somesize->Some(sum+.size+.track.Grid_track.content_alignment_adjustment)))(Some0.0)spanned_tracksinSize.setother_axisitem_other_axis_sizeSize.none