Repository navigation
feat: draw table styles, cell backgrounds and borders, and merged cells - #29
Merged
Merged
Conversation
…spans TableStyle, TableCell.Background, TableCell.Border and ColumnSpan/RowSpan were stored in the model but ignored by layout and rendering: every table was drawn with a fixed 1-unit grey grid, 4-unit padding and one cell per slot. - Layout uses TableStyle.BorderWidth/CellPadding and resolves spans: a spanning cell is laid out at its combined width, covers the grid lines between its slots, and a tall row-spanning cell grows the last row it covers. Covered slots are skipped. Spans are clamped to the grid and to slots not already claimed by an earlier cell. - TableLayoutBlock carries BorderWidth, BorderColor and per-slot CellInfo (span, effective background, border) with GetCellBounds/GetOwningCell helpers shared by the renderer, hit tester and caret renderer. - The renderer fills cell backgrounds (cell colour, else header-row fill) and draws collapsed borders: each edge once, with the wider of the two adjacent sides, skipping edges inside a span. - Hit-testing and the caret resolve covered slots to the spanning cell; Tab/Shift+Tab skip covered cells. TableBlock.GetSpanAnchor exposes the slot-to-cell mapping. MAUI table resize uses the layout's border width. - TableStyle.BorderColor now defaults to the grey tables were always drawn with, so unstyled tables render as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0197tHRWhTiagB1MTsDuPkoa
There was a problem hiding this comment.
🟡 Changes recommended
Merged-cell interaction bugs, border overflow, and quadratic Tab traversal remain unresolved.
7 open issues
Normalize stored positions to visible merged-cell anchors · New Pass the terminal merged slot to table-boundary handling · New Reuse the ownership map to avoid O(N²) merged-cell traversal · New Inset the outer bottom border within the table height · New Inset the outer right border within the table edge · New Ignore hidden column boundaries during resizing · New Ignore hidden row boundaries during resizing · New
What changed in this PR
Makes existing table styling and merged-cell properties affect the editor’s layout, rendering, and interaction.
Changes:
- Renders table styles, cell backgrounds, borders, and merged cells.
- Updates hit-testing, caret placement, Tab navigation, and resize geometry.
- Adds regression tests and documents behavior and defaults.
| File | Description |
|---|---|
| tests/MintedTextEditor.Core.Tests/TableStylingTests.cs | Adds styling and merged-cell tests. |
| src/MintedTextEditor.Maui/MintedEditorView.cs | Uses styled border widths for resizing. |
| src/MintedTextEditor.Core/Rendering/DocumentRenderer.cs | Draws backgrounds, merged content, and shared borders. |
| src/MintedTextEditor.Core/Layout/TextLayoutEngine.cs | Applies styles and calculates merged geometry. |
| src/MintedTextEditor.Core/Layout/TableLayoutBlock.cs | Exposes cell ownership, bounds, and styling. |
| src/MintedTextEditor.Core/Input/EditorInputController.cs | Skips covered cells during Tab navigation. |
| src/MintedTextEditor.Core/Input/DocumentHitTester.cs | Resolves taps to merged-cell anchors. |
| src/MintedTextEditor.Core/Editing/CaretRenderer.cs | Positions the caret relative to merged cells. |
| src/MintedTextEditor.Core/Document/TableStyle.cs | Defines rendering defaults and documents styling. |
| src/MintedTextEditor.Core/Document/TableCell.cs | Clarifies decoration and merge documentation. |
| src/MintedTextEditor.Core/Document/TableBlock.cs | Adds span ownership and clamping. |
| docs/tables.md | Documents styling and merged-cell behavior. |
| CHANGELOG.md | Records features and the border-color default change. |
Review effort: Balanced
# Conflicts: # CHANGELOG.md
…ize handles - Caret positions in a slot covered by a merged cell are mapped to the spanning cell (offsets clamped to its content) whenever the controller moves the caret, and before edits, so Ctrl+End, arrows, Tab, table row/column commands and typing never target the hidden cell. GetBlockEndPosition/MoveDocEnd use the cell covering the last slot, and IsLastCell treats it as the last cell so Right leaves the table. - Tab decides whether to leave the table from the terminal slot it reached, so a merged last cell exits instead of inserting a tab. - Tab builds the span ownership grid once instead of on every step. - Wide outer bottom and right borders are inset so they stay within the table's height and width; the bottom line's visibility check uses its inset position. - Column/row resize ignore grid lines hidden inside a merged cell in the pointer's row/column (TableLayoutBlock.FindColumnResizeBoundary / FindRowResizeBoundary, used by MintedEditorView). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0197tHRWhTiagB1MTsDuPkoa
# Conflicts: # CHANGELOG.md # src/MintedTextEditor.Core/Rendering/DocumentRenderer.cs
hflexgrig
pushed a commit
to hflexgrig/MintedTextEditor
that referenced
this pull request
Oct 30, 2026
…e bitmap cache (TheEightBot#9) - Shape text with HarfBuzz (HarfBuzzSharp) so ZWJ sequences, flags and VS16 sequences form single glyphs; draw and measure from the same shaped result. Shapers are shared process-wide and load only shaping tables (never sbix/ CBDT/glyf), and shaped runs are cached, so full shaping costs about the same as unshaped drawing. SkiaDrawingContext.ShapeAllText = false limits shaping to fallback-font segments. - Read grapheme clusters with StringInfo (UAX TheEightBot#29) so 👩💻 is never split and TruncateWithEllipsis cannot cut an emoji in half. - Resolve VS16 / emoji-plane clusters through the color emoji typeface (matched via und-Zsye), so ❤️ and 😀 no longer fall back to monochrome fonts. - Cache SKImage only for immutable bitmaps; mutable bitmaps get a fresh snapshot per draw. Bitmaps the MAUI view loads are marked immutable. - Add MintedTextEditor.SkiaSharp.Tests and run it in CI with Noto Color Emoji. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K5aL8htyk8HUJ3FnsZYDva
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
The table model had properties that layout and drawing ignored:
TableStyle,TableCell.Background,TableCell.Border, and column/row spans. They now take effect. Tables that set none of them look the same as before.TableLayoutBlock:BorderWidth,BorderColor, per-slotCellInfo,GetCellBounds,GetOwningCell,GetColumnXandGetRowY.TableBlock.GetSpanAnchor.Default change:
TableStyle.BorderColorused to default to black, but tables were always drawn in grey (160,160,160). Its default is now that grey, so existing tables look the same now that the property is used. This is listed under Changed in the CHANGELOG.Testing
TableStylingTests:colspan/rowspan.Not included
NotifyChanged. The docs say so.Checklist
Generated by Claude Code