From f4582e3277143c6ffb8f9efd276d063c163d0a91 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Wed, 17 Jan 2024 14:17:51 +0000 Subject: [PATCH 1/5] fix for percentage dimensions --- CHANGELOG.md | 1 + src/textual/widget.py | 26 +- .../__snapshots__/test_snapshots.ambr | 1973 +++++++++-------- .../snapshot_apps/input_percentage_width.py | 35 + tests/snapshot_tests/test_snapshots.py | 6 + 5 files changed, 1117 insertions(+), 924 deletions(-) create mode 100644 tests/snapshot_tests/snapshot_apps/input_percentage_width.py diff --git a/CHANGELOG.md b/CHANGELOG.md index d3f838be7d..b0c7afafca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - `SelectionList` option IDs are usable as soon as the widget is instantiated https://github.com/Textualize/textual/issues/3903 - Fix issue with `Strip.crop` when crop window start aligned with strip end https://github.com/Textualize/textual/pull/3998 - Fixed Strip.crop_extend https://github.com/Textualize/textual/pull/4011 +- Fix for percentage dimensions ## [0.47.1] - 2023-01-05 diff --git a/src/textual/widget.py b/src/textual/widget.py index cbff95e1c3..44906eb3b1 100644 --- a/src/textual/widget.py +++ b/src/textual/widget.py @@ -1075,8 +1075,6 @@ def _get_box_model( # Container minus padding and border content_container = container - gutter.totals - # The container including the content - sizing_container = content_container if is_border_box else container if styles.width is None: # No width specified, fill available space @@ -1099,25 +1097,21 @@ def _get_box_model( # An explicit width styles_width = styles.width content_width = styles_width.resolve( - sizing_container - styles.margin.totals, viewport, width_fraction + container - styles.margin.totals, viewport, width_fraction ) - if is_border_box and styles_width.excludes_border: + if is_border_box: content_width -= gutter.width if styles.min_width is not None: # Restrict to minimum width, if set - min_width = styles.min_width.resolve( - content_container, viewport, width_fraction - ) + min_width = styles.min_width.resolve(container, viewport, width_fraction) if is_border_box: min_width -= gutter.width content_width = max(content_width, min_width, Fraction(0)) if styles.max_width is not None: # Restrict to maximum width, if set - max_width = styles.max_width.resolve( - content_container, viewport, width_fraction - ) + max_width = styles.max_width.resolve(container, viewport, width_fraction) if is_border_box: max_width -= gutter.width content_width = min(content_width, max_width) @@ -1143,25 +1137,21 @@ def _get_box_model( styles_height = styles.height # Explicit height set content_height = styles_height.resolve( - sizing_container - styles.margin.totals, viewport, height_fraction + container - styles.margin.totals, viewport, height_fraction ) - if is_border_box and styles_height.excludes_border: + if is_border_box: content_height -= gutter.height if styles.min_height is not None: # Restrict to minimum height, if set - min_height = styles.min_height.resolve( - content_container, viewport, height_fraction - ) + min_height = styles.min_height.resolve(container, viewport, height_fraction) if is_border_box: min_height -= gutter.height content_height = max(content_height, min_height, Fraction(0)) if styles.max_height is not None: # Restrict maximum height, if set - max_height = styles.max_height.resolve( - content_container, viewport, height_fraction - ) + max_height = styles.max_height.resolve(container, viewport, height_fraction) if is_border_box: max_height -= gutter.height content_height = min(content_height, max_height) diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr index 7dc16d9687..d173455380 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr +++ b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr @@ -19466,6 +19466,167 @@ ''' # --- +# name: test_input_percentage_width + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + InputVsTextArea + + + + + + + + + + 01234567890123456789012345678901234567890123456789012345678901234567890123456789 + ────────────────────────────────────── + + + + ────────────────────────────────────── + ────────────────────────────────────── + 1   + + + + ────────────────────────────────────── + ────────────────────────────────────── + + + + + ────────────────────────────────────── + ────────────────────────────────────── + + Button + + + ────────────────────────────────────── + + + + + ''' +# --- # name: test_input_suggestions ''' @@ -20286,136 +20447,136 @@ font-weight: 700; } - .terminal-2540665408-matrix { + .terminal-3085198851-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-2540665408-title { + .terminal-3085198851-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-2540665408-r1 { fill: #c5c8c6 } - .terminal-2540665408-r2 { fill: #e3e3e3 } - .terminal-2540665408-r3 { fill: #e1e1e1 } - .terminal-2540665408-r4 { fill: #ff0000 } - .terminal-2540665408-r5 { fill: #dde8f3;font-weight: bold } - .terminal-2540665408-r6 { fill: #ddedf9 } + .terminal-3085198851-r1 { fill: #c5c8c6 } + .terminal-3085198851-r2 { fill: #e3e3e3 } + .terminal-3085198851-r3 { fill: #e1e1e1 } + .terminal-3085198851-r4 { fill: #ff0000 } + .terminal-3085198851-r5 { fill: #dde8f3;font-weight: bold } + .terminal-3085198851-r6 { fill: #ddedf9 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - DialogIssueApp + DialogIssueApp - - - - DialogIssueApp - - - - - - ─────────────────────────────────────── - - - - - - This should not cause a scrollbar to ap - - - - - - ─────────────────────────────────────── - - - - -  D  Toggle the dialog  + + + + DialogIssueApp + + + + + + ────────────────────────────────────── + + + + + This should not cause a scrollbar to a + + + + + + ────────────────────────────────────── + + + + + +  D  Toggle the dialog  @@ -22685,133 +22846,133 @@ font-weight: 700; } - .terminal-1197668808-matrix { + .terminal-1136068071-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1197668808-title { + .terminal-1136068071-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1197668808-r1 { fill: #e1e1e1 } - .terminal-1197668808-r2 { fill: #c5c8c6 } - .terminal-1197668808-r3 { fill: #00ff00 } - .terminal-1197668808-r4 { fill: #ffdddd } + .terminal-1136068071-r1 { fill: #e1e1e1 } + .terminal-1136068071-r2 { fill: #c5c8c6 } + .terminal-1136068071-r3 { fill: #00ff00 } + .terminal-1136068071-r4 { fill: #ffdddd } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - BrokenClassesApp + BrokenClassesApp - - - - - - - - - ─────────────────────────────────────── - This should have a red background - - - - - - - - - - - ─────────────────────────────────────── - - - - - + + + + + + + + + + ────────────────────────────────────── + This should have a red background + + + + + + + + + + ────────────────────────────────────── + + + + + @@ -23474,135 +23635,135 @@ font-weight: 700; } - .terminal-1795141768-matrix { + .terminal-2734338184-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1795141768-title { + .terminal-2734338184-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1795141768-r1 { fill: #e1e1e1 } - .terminal-1795141768-r2 { fill: #c5c8c6 } - .terminal-1795141768-r3 { fill: #56c278 } - .terminal-1795141768-r4 { fill: #1d1d1d } - .terminal-1795141768-r5 { fill: #e3e4e4 } - .terminal-1795141768-r6 { fill: #e3e4e4;text-decoration: underline; } + .terminal-2734338184-r1 { fill: #e1e1e1 } + .terminal-2734338184-r2 { fill: #c5c8c6 } + .terminal-2734338184-r3 { fill: #56c278 } + .terminal-2734338184-r4 { fill: #1d1d1d } + .terminal-2734338184-r5 { fill: #e3e4e4 } + .terminal-2734338184-r6 { fill: #e3e4e4;text-decoration: underline; } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - NotifyWithInlineLinkApp + NotifyWithInlineLinkApp - - - - - - - - - - - - - - - - - - - - - - - - - Click here for the bell sound. - + + + + + + + + + + + + + + + + + + + + + + + + + Click here for the bell sound. + @@ -23633,135 +23794,135 @@ font-weight: 700; } - .terminal-3756307740-matrix { + .terminal-500610332-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-3756307740-title { + .terminal-500610332-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-3756307740-r1 { fill: #e1e1e1 } - .terminal-3756307740-r2 { fill: #c5c8c6 } - .terminal-3756307740-r3 { fill: #56c278 } - .terminal-3756307740-r4 { fill: #1d1d1d } - .terminal-3756307740-r5 { fill: #e3e4e4 } - .terminal-3756307740-r6 { fill: #ddedf9;font-weight: bold } + .terminal-500610332-r1 { fill: #e1e1e1 } + .terminal-500610332-r2 { fill: #c5c8c6 } + .terminal-500610332-r3 { fill: #56c278 } + .terminal-500610332-r4 { fill: #1d1d1d } + .terminal-500610332-r5 { fill: #e3e4e4 } + .terminal-500610332-r6 { fill: #ddedf9;font-weight: bold } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - NotifyWithInlineLinkApp + NotifyWithInlineLinkApp - - - - - - - - - - - - - - - - - - - - - - - - - Click here for the bell sound. - + + + + + + + + + + + + + + + + + + + + + + + + + Click here for the bell sound. + @@ -23792,139 +23953,139 @@ font-weight: 700; } - .terminal-99275963-matrix { + .terminal-3535066299-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-99275963-title { + .terminal-3535066299-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-99275963-r1 { fill: #e1e1e1 } - .terminal-99275963-r2 { fill: #c5c8c6 } - .terminal-99275963-r3 { fill: #56c278 } - .terminal-99275963-r4 { fill: #1d1d1d } - .terminal-99275963-r5 { fill: #e3e4e4 } - .terminal-99275963-r6 { fill: #feaa35 } - .terminal-99275963-r7 { fill: #e89719;font-weight: bold } - .terminal-99275963-r8 { fill: #e3e4e4;font-weight: bold } - .terminal-99275963-r9 { fill: #e3e4e4;font-weight: bold;font-style: italic; } - .terminal-99275963-r10 { fill: #bc4563 } + .terminal-3535066299-r1 { fill: #e1e1e1 } + .terminal-3535066299-r2 { fill: #c5c8c6 } + .terminal-3535066299-r3 { fill: #56c278 } + .terminal-3535066299-r4 { fill: #1d1d1d } + .terminal-3535066299-r5 { fill: #e3e4e4 } + .terminal-3535066299-r6 { fill: #feaa35 } + .terminal-3535066299-r7 { fill: #e89719;font-weight: bold } + .terminal-3535066299-r8 { fill: #e3e4e4;font-weight: bold } + .terminal-3535066299-r9 { fill: #e3e4e4;font-weight: bold;font-style: italic; } + .terminal-3535066299-r10 { fill: #bc4563 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - ToastApp + ToastApp - - - - - - - - It's an older code, sir, but it  - checks out. - - - - Possible trap detected - Now witness the firepower of this - fully ARMED and OPERATIONAL - battle station! - - - - It's a trap! - - - - It's against my programming to  - impersonate a deity. - + + + + + + + + It's an older code, sir, but it  + checks out. + + + + Possible trap detected + Now witness the firepower of this  + fully ARMED and OPERATIONAL battle  + station! + + + + It's a trap! + + + + It's against my programming to  + impersonate a deity. + @@ -23955,117 +24116,117 @@ font-weight: 700; } - .terminal-61440561-matrix { + .terminal-4012933681-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-61440561-title { + .terminal-4012933681-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-61440561-r1 { fill: #c5c8c6 } - .terminal-61440561-r2 { fill: #56c278 } - .terminal-61440561-r3 { fill: #1d1d1d } - .terminal-61440561-r4 { fill: #e3e4e4 } + .terminal-4012933681-r1 { fill: #c5c8c6 } + .terminal-4012933681-r2 { fill: #56c278 } + .terminal-4012933681-r3 { fill: #1d1d1d } + .terminal-4012933681-r4 { fill: #e3e4e4 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - LoadingOverlayApp + LoadingOverlayApp - - - - - - - - - - - This is a big notification. - This is a big notification. - This is a big notification. - This is a big notification. - This is a big notification. - This is a big notification. - This is a big notification. - This is a big notification. - This is a big notification. - This is a big notification. - - + + + + + + + + + + + This is a big notification. + This is a big notification. + This is a big notification. + This is a big notification. + This is a big notification. + This is a big notification. + This is a big notification. + This is a big notification. + This is a big notification. + This is a big notification. + + @@ -24096,134 +24257,134 @@ font-weight: 700; } - .terminal-2569815150-matrix { + .terminal-1373062254-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-2569815150-title { + .terminal-1373062254-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-2569815150-r1 { fill: #e1e1e1 } - .terminal-2569815150-r2 { fill: #56c278 } - .terminal-2569815150-r3 { fill: #c5c8c6 } - .terminal-2569815150-r4 { fill: #1d1d1d } - .terminal-2569815150-r5 { fill: #e3e4e4 } + .terminal-1373062254-r1 { fill: #e1e1e1 } + .terminal-1373062254-r2 { fill: #56c278 } + .terminal-1373062254-r3 { fill: #c5c8c6 } + .terminal-1373062254-r4 { fill: #1d1d1d } + .terminal-1373062254-r5 { fill: #e3e4e4 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - NotifyThroughModesApp + NotifyThroughModesApp - - - - This is a mode screen - 4 - - - - 5 - - - - 6 - - - - 7 - - - - 8 - - - - 9 - + + + + This is a mode screen + 4 + + + + 5 + + + + 6 + + + + 7 + + + + 8 + + + + 9 + @@ -24254,134 +24415,134 @@ font-weight: 700; } - .terminal-4257366247-matrix { + .terminal-3060613351-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-4257366247-title { + .terminal-3060613351-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-4257366247-r1 { fill: #e1e1e1 } - .terminal-4257366247-r2 { fill: #56c278 } - .terminal-4257366247-r3 { fill: #c5c8c6 } - .terminal-4257366247-r4 { fill: #1d1d1d } - .terminal-4257366247-r5 { fill: #e3e4e4 } + .terminal-3060613351-r1 { fill: #e1e1e1 } + .terminal-3060613351-r2 { fill: #56c278 } + .terminal-3060613351-r3 { fill: #c5c8c6 } + .terminal-3060613351-r4 { fill: #1d1d1d } + .terminal-3060613351-r5 { fill: #e3e4e4 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - NotifyDownScreensApp + NotifyDownScreensApp - - - - Screen 10 - 4 - - - - 5 - - - - 6 - - - - 7 - - - - 8 - - - - 9 - + + + + Screen 10 + 4 + + + + 5 + + + + 6 + + + + 7 + + + + 8 + + + + 9 + @@ -24731,140 +24892,140 @@ font-weight: 700; } - .terminal-371403050-matrix { + .terminal-2682133191-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-371403050-title { + .terminal-2682133191-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-371403050-r1 { fill: #c5c8c6 } - .terminal-371403050-r2 { fill: #e3e3e3 } - .terminal-371403050-r3 { fill: #e1e1e1 } - .terminal-371403050-r4 { fill: #1e1e1e } - .terminal-371403050-r5 { fill: #0178d4 } - .terminal-371403050-r6 { fill: #ddedf9;font-weight: bold } - .terminal-371403050-r7 { fill: #e2e2e2 } - .terminal-371403050-r8 { fill: #434343 } - .terminal-371403050-r9 { fill: #787878 } - .terminal-371403050-r10 { fill: #14191f } - .terminal-371403050-r11 { fill: #ddedf9 } + .terminal-2682133191-r1 { fill: #c5c8c6 } + .terminal-2682133191-r2 { fill: #e3e3e3 } + .terminal-2682133191-r3 { fill: #e1e1e1 } + .terminal-2682133191-r4 { fill: #1e1e1e } + .terminal-2682133191-r5 { fill: #0178d4 } + .terminal-2682133191-r6 { fill: #ddedf9;font-weight: bold } + .terminal-2682133191-r7 { fill: #e2e2e2 } + .terminal-2682133191-r8 { fill: #434343 } + .terminal-2682133191-r9 { fill: #787878 } + .terminal-2682133191-r10 { fill: #14191f } + .terminal-2682133191-r11 { fill: #ddedf9 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - OptionListApp + OptionListApp - - - - OptionListApp - - - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - Aerilon - Aquaria - ─────────────────────────────────────────────────── - Canceron - Caprica - ─────────────────────────────────────────────────── - Gemenon - ─────────────────────────────────────────────────── - Leonis - Libran - ─────────────────────────────────────────────────── - Picon - ─────────────────────────────────────────────────── - Sagittaron▄▄ - Scorpia - ─────────────────────────────────────────────────── - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - - + + + + OptionListApp + + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + Aerilon + Aquaria + ────────────────────────────────────────────────── + Canceron + Caprica + ────────────────────────────────────────────────── + Gemenon + ────────────────────────────────────────────────── + Leonis + Libran + ────────────────────────────────────────────────── + Picon▁▁ + ────────────────────────────────────────────────── + Sagittaron + Scorpia + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + @@ -25378,137 +25539,137 @@ font-weight: 700; } - .terminal-2341816165-matrix { + .terminal-534841697-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-2341816165-title { + .terminal-534841697-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-2341816165-r1 { fill: #c5c8c6 } - .terminal-2341816165-r2 { fill: #e3e3e3 } - .terminal-2341816165-r3 { fill: #e1e1e1 } - .terminal-2341816165-r4 { fill: #1e1e1e } - .terminal-2341816165-r5 { fill: #0178d4 } - .terminal-2341816165-r6 { fill: #ddedf9;font-weight: bold } - .terminal-2341816165-r7 { fill: #e2e2e2 } - .terminal-2341816165-r8 { fill: #ddedf9 } + .terminal-534841697-r1 { fill: #c5c8c6 } + .terminal-534841697-r2 { fill: #e3e3e3 } + .terminal-534841697-r3 { fill: #e1e1e1 } + .terminal-534841697-r4 { fill: #1e1e1e } + .terminal-534841697-r5 { fill: #0178d4 } + .terminal-534841697-r6 { fill: #ddedf9;font-weight: bold } + .terminal-534841697-r7 { fill: #e2e2e2 } + .terminal-534841697-r8 { fill: #ddedf9 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - OptionListApp + OptionListApp - - - - OptionListApp - - - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - Aerilon - Aquaria - Canceron - Caprica - Gemenon - Leonis - Libran - Picon - Sagittaron - Scorpia - Tauron - Virgon - - - - - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - - + + + + OptionListApp + + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + Aerilon + Aquaria + Canceron + Caprica + Gemenon + Leonis + Libran + Picon + Sagittaron + Scorpia + Tauron + Virgon + + + + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + @@ -25539,141 +25700,141 @@ font-weight: 700; } - .terminal-228828675-matrix { + .terminal-1755547624-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-228828675-title { + .terminal-1755547624-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-228828675-r1 { fill: #c5c8c6 } - .terminal-228828675-r2 { fill: #e3e3e3 } - .terminal-228828675-r3 { fill: #e1e1e1 } - .terminal-228828675-r4 { fill: #1e1e1e } - .terminal-228828675-r5 { fill: #0178d4 } - .terminal-228828675-r6 { fill: #ddedf9;font-weight: bold;font-style: italic; } - .terminal-228828675-r7 { fill: #e2e2e2 } - .terminal-228828675-r8 { fill: #ddedf9;font-weight: bold } - .terminal-228828675-r9 { fill: #14191f } - .terminal-228828675-r10 { fill: #e2e2e2;font-style: italic; } - .terminal-228828675-r11 { fill: #e2e2e2;font-weight: bold } - .terminal-228828675-r12 { fill: #ddedf9 } + .terminal-1755547624-r1 { fill: #c5c8c6 } + .terminal-1755547624-r2 { fill: #e3e3e3 } + .terminal-1755547624-r3 { fill: #e1e1e1 } + .terminal-1755547624-r4 { fill: #1e1e1e } + .terminal-1755547624-r5 { fill: #0178d4 } + .terminal-1755547624-r6 { fill: #ddedf9;font-weight: bold;font-style: italic; } + .terminal-1755547624-r7 { fill: #e2e2e2 } + .terminal-1755547624-r8 { fill: #ddedf9;font-weight: bold } + .terminal-1755547624-r9 { fill: #14191f } + .terminal-1755547624-r10 { fill: #e2e2e2;font-style: italic; } + .terminal-1755547624-r11 { fill: #e2e2e2;font-weight: bold } + .terminal-1755547624-r12 { fill: #ddedf9 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - OptionListApp + OptionListApp - - - - OptionListApp - - - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ -                  Data for Aerilon                   - ┏━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┓ - Patron God   Population    Capital City   - ┡━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━┩▃▃ - Demeter      1.2 Billion   Gaoth          - └───────────────┴────────────────┴────────────────┘ -                  Data for Aquaria                   - ┏━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓ - Patron God   Population   Capital City    - ┡━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩ - Hermes       75,000       None            - └───────────────┴───────────────┴─────────────────┘ -                  Data for Canceron                  - ┏━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┓ - Patron God   Population    Capital City   - ┡━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━┩ - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - - + + + + OptionListApp + + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ +                  Data for Aerilon                  + ┏━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┓ + Patron God   Population   Capital City   + ┡━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━┩▇▇ + Demeter      1.2 Billion  Gaoth          + └───────────────┴───────────────┴────────────────┘ +                  Data for Aquaria                  + ┏━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┓ + Patron God   Population   Capital City   + ┡━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━┩ + Hermes       75,000       None           + └───────────────┴───────────────┴────────────────┘ +                 Data for Canceron                  + ┏━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┓ + Patron God   Population   Capital City   + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + @@ -27616,139 +27777,139 @@ font-weight: 700; } - .terminal-3755206349-matrix { + .terminal-2068636424-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-3755206349-title { + .terminal-2068636424-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-3755206349-r1 { fill: #e1e1e1 } - .terminal-3755206349-r2 { fill: #c5c8c6 } - .terminal-3755206349-r3 { fill: #1e1e1e } - .terminal-3755206349-r4 { fill: #0178d4 } - .terminal-3755206349-r5 { fill: #575757 } - .terminal-3755206349-r6 { fill: #262626;font-weight: bold } - .terminal-3755206349-r7 { fill: #e2e2e2 } - .terminal-3755206349-r8 { fill: #e2e2e2;text-decoration: underline; } - .terminal-3755206349-r9 { fill: #434343 } - .terminal-3755206349-r10 { fill: #4ebf71;font-weight: bold } + .terminal-2068636424-r1 { fill: #e1e1e1 } + .terminal-2068636424-r2 { fill: #c5c8c6 } + .terminal-2068636424-r3 { fill: #1e1e1e } + .terminal-2068636424-r4 { fill: #0178d4 } + .terminal-2068636424-r5 { fill: #575757 } + .terminal-2068636424-r6 { fill: #262626;font-weight: bold } + .terminal-2068636424-r7 { fill: #e2e2e2 } + .terminal-2068636424-r8 { fill: #e2e2e2;text-decoration: underline; } + .terminal-2068636424-r9 { fill: #434343 } + .terminal-2068636424-r10 { fill: #4ebf71;font-weight: bold } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - RadioChoicesApp + RadioChoicesApp - - - - - - - - - - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - Battlestar Galactica -  Dune 1984 -  Dune 2021 -  Serenity -  Star Trek: The Motion Picture -  Star Wars: A New Hope -  The Last Starfighter -  Total Recall 👉 🔴 -  Wing Commander - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - - - - - - + + + + + + + + + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + Battlestar Galactica +  Dune 1984 +  Dune 2021 +  Serenity +  Star Trek: The Motion Picture +  Star Wars: A New Hope +  The Last Starfighter +  Total Recall 👉 🔴 +  Wing Commander + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + + + @@ -27779,140 +27940,140 @@ font-weight: 700; } - .terminal-3259211563-matrix { + .terminal-2449642391-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-3259211563-title { + .terminal-2449642391-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-3259211563-r1 { fill: #e1e1e1 } - .terminal-3259211563-r2 { fill: #c5c8c6 } - .terminal-3259211563-r3 { fill: #1e1e1e } - .terminal-3259211563-r4 { fill: #0178d4 } - .terminal-3259211563-r5 { fill: #575757 } - .terminal-3259211563-r6 { fill: #262626;font-weight: bold } - .terminal-3259211563-r7 { fill: #e2e2e2 } - .terminal-3259211563-r8 { fill: #e2e2e2;text-decoration: underline; } - .terminal-3259211563-r9 { fill: #434343 } - .terminal-3259211563-r10 { fill: #4ebf71;font-weight: bold } - .terminal-3259211563-r11 { fill: #cc555a;font-weight: bold;font-style: italic; } + .terminal-2449642391-r1 { fill: #e1e1e1 } + .terminal-2449642391-r2 { fill: #c5c8c6 } + .terminal-2449642391-r3 { fill: #1e1e1e } + .terminal-2449642391-r4 { fill: #0178d4 } + .terminal-2449642391-r5 { fill: #575757 } + .terminal-2449642391-r6 { fill: #262626;font-weight: bold } + .terminal-2449642391-r7 { fill: #e2e2e2 } + .terminal-2449642391-r8 { fill: #e2e2e2;text-decoration: underline; } + .terminal-2449642391-r9 { fill: #434343 } + .terminal-2449642391-r10 { fill: #4ebf71;font-weight: bold } + .terminal-2449642391-r11 { fill: #cc555a;font-weight: bold;font-style: italic; } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - RadioChoicesApp + RadioChoicesApp - - - - - - - - - - ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ - Battlestar Galactica Amanda -  Dune 1984 Connor MacLeod -  Dune 2021 Duncan MacLeod -  Serenity Heather MacLeod -  Star Trek: The Motion Picture Joe Dawson -  Star Wars: A New Hope Kurgan, The -  The Last Starfighter Methos -  Total Recall 👉 🔴 Rachel Ellenstein -  Wing Commander Ramírez - ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ - - - - - - + + + + + + + + + + ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ + Battlestar Galactica Amanda +  Dune 1984 Connor MacLeod +  Dune 2021 Duncan MacLeod +  Serenity Heather MacLeod +  Star Trek: The Motion Pictur Joe Dawson +  Star Wars: A New Hope Kurgan, The +  The Last Starfighter Methos +  Total Recall 👉 🔴 Rachel Ellenstein +  Wing Commander Ramírez + ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ + + + + + + @@ -30976,139 +31137,139 @@ font-weight: 700; } - .terminal-3401996005-matrix { + .terminal-2928221602-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-3401996005-title { + .terminal-2928221602-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-3401996005-r1 { fill: #c5c8c6 } - .terminal-3401996005-r2 { fill: #e3e3e3 } - .terminal-3401996005-r3 { fill: #e1e1e1 } - .terminal-3401996005-r4 { fill: #0178d4 } - .terminal-3401996005-r5 { fill: #575757 } - .terminal-3401996005-r6 { fill: #4ebf71;font-weight: bold } - .terminal-3401996005-r7 { fill: #ddedf9;font-weight: bold } - .terminal-3401996005-r8 { fill: #262626;font-weight: bold } - .terminal-3401996005-r9 { fill: #e2e2e2 } - .terminal-3401996005-r10 { fill: #ddedf9 } + .terminal-2928221602-r1 { fill: #c5c8c6 } + .terminal-2928221602-r2 { fill: #e3e3e3 } + .terminal-2928221602-r3 { fill: #e1e1e1 } + .terminal-2928221602-r4 { fill: #0178d4 } + .terminal-2928221602-r5 { fill: #575757 } + .terminal-2928221602-r6 { fill: #4ebf71;font-weight: bold } + .terminal-2928221602-r7 { fill: #ddedf9;font-weight: bold } + .terminal-2928221602-r8 { fill: #262626;font-weight: bold } + .terminal-2928221602-r9 { fill: #e2e2e2 } + .terminal-2928221602-r10 { fill: #ddedf9 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - SelectionListApp + SelectionListApp - - - - SelectionListApp - - -  Shall we play some games? ────────────────────────────────── - - XFalken's Maze - XBlack Jack - XGin Rummy - XHearts - XBridge - XCheckers - XChess - XPoker - XFighter Combat - - - - - - - ────────────────────────────────────────────────────────────── - - + + + + SelectionListApp + + +  Shall we play some games? ────────────────────────────────── + + XFalken's Maze + XBlack Jack + XGin Rummy + XHearts + XBridge + XCheckers + XChess + XPoker + XFighter Combat + + + + + + ────────────────────────────────────────────────────────────── + + + @@ -31139,139 +31300,139 @@ font-weight: 700; } - .terminal-3401996005-matrix { + .terminal-2928221602-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-3401996005-title { + .terminal-2928221602-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-3401996005-r1 { fill: #c5c8c6 } - .terminal-3401996005-r2 { fill: #e3e3e3 } - .terminal-3401996005-r3 { fill: #e1e1e1 } - .terminal-3401996005-r4 { fill: #0178d4 } - .terminal-3401996005-r5 { fill: #575757 } - .terminal-3401996005-r6 { fill: #4ebf71;font-weight: bold } - .terminal-3401996005-r7 { fill: #ddedf9;font-weight: bold } - .terminal-3401996005-r8 { fill: #262626;font-weight: bold } - .terminal-3401996005-r9 { fill: #e2e2e2 } - .terminal-3401996005-r10 { fill: #ddedf9 } + .terminal-2928221602-r1 { fill: #c5c8c6 } + .terminal-2928221602-r2 { fill: #e3e3e3 } + .terminal-2928221602-r3 { fill: #e1e1e1 } + .terminal-2928221602-r4 { fill: #0178d4 } + .terminal-2928221602-r5 { fill: #575757 } + .terminal-2928221602-r6 { fill: #4ebf71;font-weight: bold } + .terminal-2928221602-r7 { fill: #ddedf9;font-weight: bold } + .terminal-2928221602-r8 { fill: #262626;font-weight: bold } + .terminal-2928221602-r9 { fill: #e2e2e2 } + .terminal-2928221602-r10 { fill: #ddedf9 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - SelectionListApp + SelectionListApp - - - - SelectionListApp - - -  Shall we play some games? ────────────────────────────────── - - XFalken's Maze - XBlack Jack - XGin Rummy - XHearts - XBridge - XCheckers - XChess - XPoker - XFighter Combat - - - - - - - ────────────────────────────────────────────────────────────── - - + + + + SelectionListApp + + +  Shall we play some games? ────────────────────────────────── + + XFalken's Maze + XBlack Jack + XGin Rummy + XHearts + XBridge + XCheckers + XChess + XPoker + XFighter Combat + + + + + + ────────────────────────────────────────────────────────────── + + + diff --git a/tests/snapshot_tests/snapshot_apps/input_percentage_width.py b/tests/snapshot_tests/snapshot_apps/input_percentage_width.py new file mode 100644 index 0000000000..f20b2ddd29 --- /dev/null +++ b/tests/snapshot_tests/snapshot_apps/input_percentage_width.py @@ -0,0 +1,35 @@ +from textual.app import App, ComposeResult +from textual.widgets import Input, TextArea, Static, Button, Label + + +class InputVsTextArea(App[None]): + CSS = """ + Screen > *, Screen > *:focus { + width: 50%; + height: 1fr; + border: solid red; + } + App #ruler { + width: 1fr; + height: 1; + border: none; + } + """ + + def compose(self) -> ComposeResult: + yield Label("[reverse]0123456789[/]0123456789" * 4, id="ruler") + + input = Input() + input.cursor_blink = False + yield input + + text_area = TextArea() + text_area.cursor_blink = False + yield text_area + + yield Static() + yield Button() + + +if __name__ == "__main__": + InputVsTextArea().run() diff --git a/tests/snapshot_tests/test_snapshots.py b/tests/snapshot_tests/test_snapshots.py index 63e5d93026..485e4fad8b 100644 --- a/tests/snapshot_tests/test_snapshots.py +++ b/tests/snapshot_tests/test_snapshots.py @@ -984,3 +984,9 @@ def test_nested_specificity(snap_compare): def test_tab_rename(snap_compare): """Test setting a new label for a tab amongst a TabbedContent.""" assert snap_compare(SNAPSHOT_APPS_DIR / "tab_rename.py") + + +def test_input_percentage_width(snap_compare): + """Check percentage widths work correctly.""" + # https://github.com/Textualize/textual/issues/3721 + assert snap_compare(SNAPSHOT_APPS_DIR / "input_percentage_width.py") From 7e3904d404f4e18aedd4aef07f99e3fecb32b7ad Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Wed, 17 Jan 2024 14:24:16 +0000 Subject: [PATCH 2/5] remove deprecated code --- CHANGELOG.md | 2 +- src/textual/css/scalar.py | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0c7afafca..c742d981fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,7 +26,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - `SelectionList` option IDs are usable as soon as the widget is instantiated https://github.com/Textualize/textual/issues/3903 - Fix issue with `Strip.crop` when crop window start aligned with strip end https://github.com/Textualize/textual/pull/3998 - Fixed Strip.crop_extend https://github.com/Textualize/textual/pull/4011 -- Fix for percentage dimensions +- Fix for percentage dimensions https://github.com/Textualize/textual/pull/4037 ## [0.47.1] - 2023-01-05 diff --git a/src/textual/css/scalar.py b/src/textual/css/scalar.py index 044fce1161..0ef332c571 100644 --- a/src/textual/css/scalar.py +++ b/src/textual/css/scalar.py @@ -37,8 +37,6 @@ class Unit(Enum): AUTO = 8 -UNIT_EXCLUDES_BORDER = {Unit.CELLS, Unit.FRACTION, Unit.VIEW_WIDTH, Unit.VIEW_HEIGHT} - UNIT_SYMBOL = { Unit.CELLS: "", Unit.FRACTION: "fr", @@ -206,10 +204,6 @@ def is_fraction(self) -> bool: """Check if the unit is a fraction.""" return self.unit == Unit.FRACTION - @property - def excludes_border(self) -> bool: - return self.unit in UNIT_EXCLUDES_BORDER - @property def cells(self) -> int | None: """Check if the unit is explicit cells.""" From 8bebd345ad90cd75f9d343480363a7241c435fd9 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Wed, 17 Jan 2024 15:10:31 +0000 Subject: [PATCH 3/5] simplify --- src/textual/widget.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/textual/widget.py b/src/textual/widget.py index 44906eb3b1..a9540911b4 100644 --- a/src/textual/widget.py +++ b/src/textual/widget.py @@ -1076,15 +1076,15 @@ def _get_box_model( # Container minus padding and border content_container = container - gutter.totals + print(self, width_fraction) + if styles.width is None: # No width specified, fill available space content_width = Fraction(content_container.width - margin.width) elif is_auto_width: # When width is auto, we want enough space to always fit the content content_width = Fraction( - self.get_content_width( - content_container - styles.margin.totals, viewport - ) + self.get_content_width(content_container - margin.totals, viewport) ) if styles.scrollbar_gutter == "stable" and styles.overflow_x == "auto": content_width += styles.scrollbar_size_vertical @@ -1097,7 +1097,7 @@ def _get_box_model( # An explicit width styles_width = styles.width content_width = styles_width.resolve( - container - styles.margin.totals, viewport, width_fraction + container - margin.totals, viewport, width_fraction ) if is_border_box: content_width -= gutter.width @@ -1137,7 +1137,7 @@ def _get_box_model( styles_height = styles.height # Explicit height set content_height = styles_height.resolve( - container - styles.margin.totals, viewport, height_fraction + container - margin.totals, viewport, height_fraction ) if is_border_box: content_height -= gutter.height From a1c5bd54dfb0c02802a2ced6eb279538ad25627c Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Wed, 17 Jan 2024 15:50:44 +0000 Subject: [PATCH 4/5] fix margin --- src/textual/_arrange.py | 1 - src/textual/layouts/horizontal.py | 6 ++++-- src/textual/layouts/vertical.py | 2 +- src/textual/widget.py | 2 -- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/textual/_arrange.py b/src/textual/_arrange.py index 87879573af..97d8abbe4a 100644 --- a/src/textual/_arrange.py +++ b/src/textual/_arrange.py @@ -160,5 +160,4 @@ def _arrange_dock_widgets( _WidgetPlacement(dock_region, null_spacing, dock_widget, top_z, True) ) dock_spacing = Spacing(top, right, bottom, left) - return (placements, dock_spacing) diff --git a/src/textual/layouts/horizontal.py b/src/textual/layouts/horizontal.py index 9d5697f0fe..02672ae879 100644 --- a/src/textual/layouts/horizontal.py +++ b/src/textual/layouts/horizontal.py @@ -26,7 +26,9 @@ def arrange( add_placement = placements.append child_styles = [child.styles for child in children] - box_margins: list[Spacing] = [styles.margin for styles in child_styles] + box_margins: list[Spacing] = [ + styles.margin for styles in child_styles if styles.overlay != "screen" + ] if box_margins: resolve_margin = Size( sum( @@ -36,7 +38,7 @@ def arrange( ] ) + (box_margins[0].left + box_margins[-1].right), - max( + min( [ margin_top + margin_bottom for margin_top, _, margin_bottom, _ in box_margins diff --git a/src/textual/layouts/vertical.py b/src/textual/layouts/vertical.py index a81518f1d2..995b135439 100644 --- a/src/textual/layouts/vertical.py +++ b/src/textual/layouts/vertical.py @@ -29,7 +29,7 @@ def arrange( ] if box_margins: resolve_margin = Size( - max( + min( [ margin_right + margin_left for _, margin_right, _, margin_left in box_margins diff --git a/src/textual/widget.py b/src/textual/widget.py index a9540911b4..fba5d7a4b9 100644 --- a/src/textual/widget.py +++ b/src/textual/widget.py @@ -1076,8 +1076,6 @@ def _get_box_model( # Container minus padding and border content_container = container - gutter.totals - print(self, width_fraction) - if styles.width is None: # No width specified, fill available space content_width = Fraction(content_container.width - margin.width) From 1fb3c6470363101863eaf6d2bdf0f9c6fbb27988 Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Wed, 31 Jan 2024 13:42:30 +0000 Subject: [PATCH 5/5] snapshots --- src/textual/widget.py | 16 ++- .../__snapshots__/test_snapshots.ambr | 123 +++++++++--------- tests/test_box_model.py | 4 +- 3 files changed, 75 insertions(+), 68 deletions(-) diff --git a/src/textual/widget.py b/src/textual/widget.py index 7f49cbb861..943df445fd 100644 --- a/src/textual/widget.py +++ b/src/textual/widget.py @@ -1098,14 +1098,18 @@ def _get_box_model( if styles.min_width is not None: # Restrict to minimum width, if set - min_width = styles.min_width.resolve(container, viewport, width_fraction) + min_width = styles.min_width.resolve( + container - margin.totals, viewport, width_fraction + ) if is_border_box: min_width -= gutter.width content_width = max(content_width, min_width, Fraction(0)) if styles.max_width is not None: # Restrict to maximum width, if set - max_width = styles.max_width.resolve(container, viewport, width_fraction) + max_width = styles.max_width.resolve( + container - margin.totals, viewport, width_fraction + ) if is_border_box: max_width -= gutter.width content_width = min(content_width, max_width) @@ -1138,14 +1142,18 @@ def _get_box_model( if styles.min_height is not None: # Restrict to minimum height, if set - min_height = styles.min_height.resolve(container, viewport, height_fraction) + min_height = styles.min_height.resolve( + container - margin.totals, viewport, height_fraction + ) if is_border_box: min_height -= gutter.height content_height = max(content_height, min_height, Fraction(0)) if styles.max_height is not None: # Restrict maximum height, if set - max_height = styles.max_height.resolve(container, viewport, height_fraction) + max_height = styles.max_height.resolve( + container - margin.totals, viewport, height_fraction + ) if is_border_box: max_height -= gutter.height content_height = min(content_height, max_height) diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr index 643ed6c1b7..5824f20be7 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr +++ b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr @@ -19489,138 +19489,137 @@ font-weight: 700; } - .terminal-354308713-matrix { + .terminal-1152611452-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-354308713-title { + .terminal-1152611452-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-354308713-r1 { fill: #1e1e1e } - .terminal-354308713-r2 { fill: #e1e1e1 } - .terminal-354308713-r3 { fill: #c5c8c6 } - .terminal-354308713-r4 { fill: #ff0000 } - .terminal-354308713-r5 { fill: #c2c2bf } - .terminal-354308713-r6 { fill: #272822 } - .terminal-354308713-r7 { fill: #f8f8f2 } - .terminal-354308713-r8 { fill: #e2e3e3;font-weight: bold } + .terminal-1152611452-r1 { fill: #1e1e1e } + .terminal-1152611452-r2 { fill: #e1e1e1 } + .terminal-1152611452-r3 { fill: #c5c8c6 } + .terminal-1152611452-r4 { fill: #ff0000 } + .terminal-1152611452-r5 { fill: #f8f8f2 } + .terminal-1152611452-r6 { fill: #272822 } + .terminal-1152611452-r7 { fill: #e2e3e3;font-weight: bold } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - InputVsTextArea + InputVsTextArea - - - - 01234567890123456789012345678901234567890123456789012345678901234567890123456789 - ────────────────────────────────────── - - - - ────────────────────────────────────── - ────────────────────────────────────── - 1   - - - - ────────────────────────────────────── - ────────────────────────────────────── - - - - - ────────────────────────────────────── - ────────────────────────────────────── - - Button - - - ────────────────────────────────────── + + + + 01234567890123456789012345678901234567890123456789012345678901234567890123456789 + ────────────────────────────────────── + + + + ────────────────────────────────────── + ────────────────────────────────────── + + + + + ────────────────────────────────────── + ────────────────────────────────────── + + + + + ────────────────────────────────────── + ────────────────────────────────────── + + Button + + + ────────────────────────────────────── diff --git a/tests/test_box_model.py b/tests/test_box_model.py index 8f59c8a82f..d775dc9be9 100644 --- a/tests/test_box_model.py +++ b/tests/test_box_model.py @@ -90,7 +90,7 @@ def get_content_height(self, container: Size, parent: Size, width: int) -> int: styles.max_width = "50%" box_model = widget._get_box_model(Size(60, 20), Size(80, 24), one, one) - assert box_model == BoxModel(Fraction(30), Fraction(16), Spacing(1, 2, 3, 4)) + assert box_model == BoxModel(Fraction(27), Fraction(16), Spacing(1, 2, 3, 4)) def test_height(): @@ -141,7 +141,7 @@ def get_content_height(self, container: Size, parent: Size, width: int) -> int: styles.max_height = "50%" box_model = widget._get_box_model(Size(60, 20), Size(80, 24), one, one) - assert box_model == BoxModel(Fraction(54), Fraction(10), Spacing(1, 2, 3, 4)) + assert box_model == BoxModel(Fraction(54), Fraction(8), Spacing(1, 2, 3, 4)) def test_max():