@@ -160,6 +160,17 @@ where
160160 ) -> Self {
161161 children. into_iter ( ) . fold ( self , Self :: push)
162162 }
163+
164+ /// Turns the [`Column`] into a [`Wrapping`] column.
165+ ///
166+ /// The original alignment of the [`Column`] is preserved per column wrapped.
167+ pub fn wrap ( self ) -> Wrapping < ' a , Message , Theme , Renderer > {
168+ Wrapping {
169+ column : self ,
170+ horizontal_spacing : None ,
171+ align_y : alignment:: Vertical :: Top ,
172+ }
173+ }
163174}
164175
165176impl < Message , Renderer > Default for Column < ' _ , Message , Renderer >
@@ -353,3 +364,254 @@ where
353364 Self :: new ( column)
354365 }
355366}
367+
368+ /// A [`Column`] that wraps its contents.
369+ ///
370+ /// Create a [`Column`] first, and then call [`Column::wrap`] to
371+ /// obtain a [`Column`] that wraps its contents.
372+ ///
373+ /// The original alignment of the [`Column`] is preserved per column wrapped.
374+ #[ allow( missing_debug_implementations) ]
375+ pub struct Wrapping <
376+ ' a ,
377+ Message ,
378+ Theme = crate :: Theme ,
379+ Renderer = crate :: Renderer ,
380+ > {
381+ column : Column < ' a , Message , Theme , Renderer > ,
382+ horizontal_spacing : Option < f32 > ,
383+ align_y : alignment:: Vertical ,
384+ }
385+
386+ impl < Message , Theme , Renderer > Wrapping < ' _ , Message , Theme , Renderer > {
387+ /// Sets the horizontal spacing _between_ columns.
388+ pub fn horizontal_spacing ( mut self , amount : impl Into < Pixels > ) -> Self {
389+ self . horizontal_spacing = Some ( amount. into ( ) . 0 ) ;
390+ self
391+ }
392+
393+ /// Sets the vertical alignment of the wrapping [`Column`].
394+ pub fn align_x ( mut self , align_y : impl Into < alignment:: Vertical > ) -> Self {
395+ self . align_y = align_y. into ( ) ;
396+ self
397+ }
398+ }
399+
400+ impl < Message , Theme , Renderer > Widget < Message , Theme , Renderer >
401+ for Wrapping < ' _ , Message , Theme , Renderer >
402+ where
403+ Renderer : crate :: core:: Renderer ,
404+ {
405+ fn children ( & self ) -> Vec < Tree > {
406+ self . column . children ( )
407+ }
408+
409+ fn diff ( & self , tree : & mut Tree ) {
410+ self . column . diff ( tree) ;
411+ }
412+
413+ fn size ( & self ) -> Size < Length > {
414+ self . column . size ( )
415+ }
416+
417+ fn layout (
418+ & mut self ,
419+ tree : & mut Tree ,
420+ renderer : & Renderer ,
421+ limits : & layout:: Limits ,
422+ ) -> layout:: Node {
423+ let limits = limits
424+ . width ( self . column . width )
425+ . height ( self . column . height )
426+ . shrink ( self . column . padding ) ;
427+
428+ let child_limits = limits. loose ( ) ;
429+ let spacing = self . column . spacing ;
430+ let horizontal_spacing = self . horizontal_spacing . unwrap_or ( spacing) ;
431+ let max_height = limits. max ( ) . height ;
432+
433+ let mut children: Vec < layout:: Node > = Vec :: new ( ) ;
434+ let mut intrinsic_size = Size :: ZERO ;
435+ let mut column_start = 0 ;
436+ let mut column_width = 0.0 ;
437+ let mut x = 0.0 ;
438+ let mut y = 0.0 ;
439+
440+ let align_factor = match self . column . align {
441+ Alignment :: Start => 0.0 ,
442+ Alignment :: Center => 2.0 ,
443+ Alignment :: End => 1.0 ,
444+ } ;
445+
446+ let align_x = |column_start : std:: ops:: Range < usize > ,
447+ column_width : f32 ,
448+ children : & mut Vec < layout:: Node > | {
449+ if align_factor != 0.0 {
450+ for node in & mut children[ column_start] {
451+ let width = node. size ( ) . width ;
452+
453+ node. translate_mut ( Vector :: new (
454+ ( column_width - width) / align_factor,
455+ 0.0 ,
456+ ) ) ;
457+ }
458+ }
459+ } ;
460+
461+ for ( i, child) in self . column . children . iter_mut ( ) . enumerate ( ) {
462+ let node = child. as_widget_mut ( ) . layout (
463+ & mut tree. children [ i] ,
464+ renderer,
465+ & child_limits,
466+ ) ;
467+
468+ let child_size = node. size ( ) ;
469+
470+ if y != 0.0 && y + child_size. height > max_height {
471+ intrinsic_size. height = intrinsic_size. height . max ( y - spacing) ;
472+
473+ align_x ( column_start..i, column_width, & mut children) ;
474+
475+ x += column_width + horizontal_spacing;
476+ y = 0.0 ;
477+ column_start = i;
478+ column_width = 0.0 ;
479+ }
480+
481+ column_width = column_width. max ( child_size. width ) ;
482+
483+ children. push ( node. move_to ( (
484+ x + self . column . padding . left ,
485+ y + self . column . padding . top ,
486+ ) ) ) ;
487+
488+ y += child_size. height + spacing;
489+ }
490+
491+ if y != 0.0 {
492+ intrinsic_size. height = intrinsic_size. height . max ( y - spacing) ;
493+ }
494+
495+ intrinsic_size. width = x + column_width;
496+ align_x ( column_start..children. len ( ) , column_width, & mut children) ;
497+
498+ let align_factor = match self . align_y {
499+ alignment:: Vertical :: Top => 0.0 ,
500+ alignment:: Vertical :: Center => 2.0 ,
501+ alignment:: Vertical :: Bottom => 1.0 ,
502+ } ;
503+
504+ if align_factor != 0.0 {
505+ let total_height = intrinsic_size. height ;
506+
507+ let mut column_start = 0 ;
508+
509+ for i in 0 ..children. len ( ) {
510+ let bounds = children[ i] . bounds ( ) ;
511+ let column_height = bounds. y + bounds. height ;
512+
513+ let next_y = children
514+ . get ( i + 1 )
515+ . map ( |node| node. bounds ( ) . y )
516+ . unwrap_or_default ( ) ;
517+
518+ if next_y == 0.0 {
519+ let translation = Vector :: new (
520+ 0.0 ,
521+ ( total_height - column_height) / align_factor,
522+ ) ;
523+
524+ for node in & mut children[ column_start..=i] {
525+ node. translate_mut ( translation) ;
526+ }
527+
528+ column_start = i + 1 ;
529+ }
530+ }
531+ }
532+
533+ let size = limits. resolve (
534+ self . column . width ,
535+ self . column . height ,
536+ intrinsic_size,
537+ ) ;
538+
539+ layout:: Node :: with_children ( size. expand ( self . column . padding ) , children)
540+ }
541+
542+ fn operate (
543+ & mut self ,
544+ tree : & mut Tree ,
545+ layout : Layout < ' _ > ,
546+ renderer : & Renderer ,
547+ operation : & mut dyn Operation ,
548+ ) {
549+ self . column . operate ( tree, layout, renderer, operation) ;
550+ }
551+
552+ fn update (
553+ & mut self ,
554+ tree : & mut Tree ,
555+ event : & Event ,
556+ layout : Layout < ' _ > ,
557+ cursor : mouse:: Cursor ,
558+ renderer : & Renderer ,
559+ clipboard : & mut dyn Clipboard ,
560+ shell : & mut Shell < ' _ , Message > ,
561+ viewport : & Rectangle ,
562+ ) {
563+ self . column . update (
564+ tree, event, layout, cursor, renderer, clipboard, shell, viewport,
565+ ) ;
566+ }
567+
568+ fn mouse_interaction (
569+ & self ,
570+ tree : & Tree ,
571+ layout : Layout < ' _ > ,
572+ cursor : mouse:: Cursor ,
573+ viewport : & Rectangle ,
574+ renderer : & Renderer ,
575+ ) -> mouse:: Interaction {
576+ self . column
577+ . mouse_interaction ( tree, layout, cursor, viewport, renderer)
578+ }
579+
580+ fn draw (
581+ & self ,
582+ tree : & Tree ,
583+ renderer : & mut Renderer ,
584+ theme : & Theme ,
585+ style : & renderer:: Style ,
586+ layout : Layout < ' _ > ,
587+ cursor : mouse:: Cursor ,
588+ viewport : & Rectangle ,
589+ ) {
590+ self . column
591+ . draw ( tree, renderer, theme, style, layout, cursor, viewport) ;
592+ }
593+
594+ fn overlay < ' b > (
595+ & ' b mut self ,
596+ tree : & ' b mut Tree ,
597+ layout : Layout < ' b > ,
598+ renderer : & Renderer ,
599+ viewport : & Rectangle ,
600+ translation : Vector ,
601+ ) -> Option < overlay:: Element < ' b , Message , Theme , Renderer > > {
602+ self . column
603+ . overlay ( tree, layout, renderer, viewport, translation)
604+ }
605+ }
606+
607+ impl < ' a , Message , Theme , Renderer > From < Wrapping < ' a , Message , Theme , Renderer > >
608+ for Element < ' a , Message , Theme , Renderer >
609+ where
610+ Message : ' a ,
611+ Theme : ' a ,
612+ Renderer : crate :: core:: Renderer + ' a ,
613+ {
614+ fn from ( column : Wrapping < ' a , Message , Theme , Renderer > ) -> Self {
615+ Self :: new ( column)
616+ }
617+ }
0 commit comments