1 module rpui.widgets.chain_layout.widget; 2 3 import std.math; 4 5 import rpui.events; 6 import rpui.primitives; 7 import rpui.math; 8 import rpui.widget; 9 import rpui.widgets.stack_layout.stack_locator; 10 import rpui.widgets.chain_layout.renderer; 11 12 final class ChainLayout : Widget { 13 private StackLocator stackLocator; 14 15 this(in string style = "ChainLayout") { 16 super(style); 17 18 skipFocus = true; 19 stackLocator.attach(this); 20 stackLocator.orientation = Orientation.horizontal; 21 renderer = new ChainLayoutRenderer(); 22 } 23 24 override void onProgress(in ProgressEvent event) { 25 super.onProgress(event); 26 27 locator.updateLocationAlign(); 28 locator.updateVerticalLocationAlign(); 29 locator.updateRegionAlign(); 30 locator.updateAbsolutePosition(); 31 32 updateSize(); 33 34 foreach (Widget widget; children) { 35 updatePartDraws(widget, PartDraws.center); 36 } 37 38 updatePartDraws(children.front, PartDraws.left); 39 updatePartDraws(children.back, PartDraws.right); 40 41 // little adjustment. 42 // TODO(Andrey): explay meaning of number 1 43 children.back.associatedWidget.margin.left = 1; 44 } 45 46 override void updateSize() { 47 super.updateSize(); 48 49 handleWidgetsVariableSize(); 50 stackLocator.updateWidgetsPosition(); 51 stackLocator.updateSize(); 52 } 53 54 private void handleWidgetsVariableSize() { 55 float fixedSize = 0; 56 int nonFixedCount = 0; 57 58 if (widthType == SizeType.matchParent) { 59 locationAlign = Align.none; 60 size.x = parent.innerSize.x - outerOffsetSize.x; 61 position.x = 0; 62 } 63 64 foreach (Widget row; children) { 65 const widget = row.associatedWidget; 66 67 if (!widget.isVisible) { 68 continue; 69 } 70 71 if (widget.widthType != SizeType.matchParent) { 72 fixedSize += widget.size.x; 73 } else { 74 nonFixedCount += 1; 75 } 76 } 77 78 const partWidth = round((size.x - fixedSize) / nonFixedCount); 79 80 float total = 0; 81 Widget lastNonFixedWidget = null; 82 83 foreach (Widget row; children) { 84 Widget widget = row.associatedWidget; 85 86 if (!widget.isVisible) { 87 continue; 88 } 89 90 if (widget.widthType == SizeType.matchParent) { 91 widget.size.x = partWidth; 92 lastNonFixedWidget = widget; 93 } 94 95 total += widget.width; 96 } 97 98 // NOTE(Andrey): Adjustment because of partWidth rounding. 99 if (lastNonFixedWidget !is null) { 100 lastNonFixedWidget.size.x += size.x - total - 1; 101 } 102 } 103 104 private void updatePartDraws(Widget row, in Widget.PartDraws partDraws) { 105 row.associatedWidget.partDraws = partDraws; 106 } 107 108 override void onRender() { 109 renderer.onRender(); 110 } 111 }