-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Add non uniform TableBorder #172441
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add non uniform TableBorder #172441
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
73f26b9 to
5948b48
Compare
Piinks
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @korca0220 welcome! Thank you for contributing.
| verticalInside.width != topWidth) { | ||
| return false; | ||
| /// Whether all the outer sides of the border (excluding the inner sides) are identical. | ||
| bool get outerBorderIsUniform { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like a special case. Can you share more about what it is for? Why not have innerBorderIsUniform?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the question! Let me explain the specific use case that drove this implementation.
The Problem I Faced
I needed to create complex table layouts where:
- Different corner radius configurations: Each of the 4 corners needed different radius values for proper visual styling
- Combining multiple tables: I had to combine two separate tables to appear as a single unified table
When combining two tables, making them look like a seamless single table requires fine-tuned customization of the borders. However, the existing isUniform condition was too restrictive - it required ALL borders (including inner borders) to be identical, which made this kind of customization impossible.
Why Only outerBorderIsUniform?
The key insight is that border radius only affects the outer edges of a table. Inner borders (horizontalInside, verticalInside) don't contribute to the corner rendering, so their uniformity is irrelevant for radius application.
By checking only outer border uniformity, we can:
- Apply border radius when outer borders have the same color (but different widths)
- Allow complete freedom for inner border styling
- Enable the table combination use case I mentioned above
Why Not innerBorderIsUniform?
I didn't implement innerBorderIsUniform for two reasons:
- Personal need: My specific use case didn't require it
- General applicability: In typical table designs, I believe there are fewer scenarios where inner border uniformity checking would be necessary
However, you raise a good point - adding innerBorderIsUniform could enable even broader customization possibilities. If there's interest in that functionality, I'd be happy to add it in a follow-up or extend this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for filing an issue. I am not sure this public getter is necessary in order for TableBorder to support non-uniform borders. Can you remove it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, of course. I agree — it doesn’t necessarily need to be public. I only made it public to be consistent with isUniform
| /// Returns the set of distinct visible colors from the outer border sides. | ||
| /// | ||
| /// Only includes colors from border sides that are not [BorderStyle.none]. | ||
| @visibleForTesting |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there another way that we could test this without public API?
https://github.com/flutter/flutter/blob/master/docs/contributing/Style-guide-for-Flutter-repo.md#avoid-using-visiblefortesting
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point! I can make distinctVisibleOuterColors() private (rename to _distinctVisibleOuterColors()) and remove the @visibleForTesting annotation entirely.
The core functionality can be tested through the public API by:
- Testing various
TableBorderconfigurations withborderRadius - Verifying that border radius is applied when outer colors are uniform but widths differ
- Ensuring border radius is not applied when outer colors differ
This way we test the actual behavior users care about rather than implementation details.
24e8649 to
a3d4556
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @korca0220 I just realized that there is not an open issue this is trying to resolve. I can see how this is similar to changes in #121921, although the addition of outerBorderIsUniform public api is still a bit curious.
Can you file an issues that better illustrates your use case that this would resolve? It will really help evaluate if this is the right fix. :)
Hello @Piinks , By checking only outer border uniformity, we can apply border radius when outer borders have the same color but different widths, while allowing complete freedom for inner border styling. In my specific use case, I needed to combine header and body tables to appear as a single unified table, with proper corner radius. The current isUniform constraint is too restrictive as it requires ALL borders (including inner borders) to be identical, resulting in undesirable thick borders between sections. Example
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
buildHeaderTable(shouldShowEmptyRows: !hasPlans),
buildBodyTable(),
],
),// buildHeaderTable...
Table(
border: TableBorder.all(
color: DColors.lightGray.color,
borderRadius: BorderRadius.only(
topLeft: const Radius.circular(3),
topRight: const Radius.circular(3),
bottomLeft: shouldShowEmptyRows ? const Radius.circular(3) : Radius.zero,
bottomRight: shouldShowEmptyRows ? const Radius.circular(3) : Radius.zero,
),
),
|
|
@korca0220 as mentioned previously, and listed in the PR description, there should be an open issue this is resolving. You checked off that it is closing an issue but have not provided what issue that is: This is also not identical to #121921 as described. And is failing many tests. Until these are resolved this change cannot move forward. |
Sorry about that, I will update the information. |
bin/internal/engine.version
Outdated
| @@ -0,0 +1 @@ | |||
| f85f6b62b6db2a8725cafa75360ec960d581a809 | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These changes look unrelated. Can you revert them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thank you. I’ll revert the unnecessary changes.
| } | ||
|
|
||
| /// Inflates an [RRect] by the given [EdgeInsets]. | ||
| static RRect _inflateRRect(RRect rect, EdgeInsets insets) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are _inflateRect and _deflateRect here the same as the methods defined in BoxBorder? Perhaps those should be made reusable and @protected in the base class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’ll check it and make the necessary corrections
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've created a new RRectUtils utility class to address the code duplication between TableBorder and BoxBorder. Since these classes have different base classes (TableBorder is standalone while BoxBorder extends ShapeBorder), we can't easily share the methods through inheritance.
The new utility class provides static methods for inflating and deflating RRects, which are now used by both TableBorder and BoxBorder. This eliminates code duplication while maintaining the existing class hierarchy.
I've also added comprehensive tests for the RRectUtils class to ensure it works correctly in all scenarios.
| expect(nonUniformOuter.outerBorderIsUniform, isFalse); | ||
| }); | ||
|
|
||
| test('TableBorder with non-uniform widths but uniform colors applies border radius', () { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test that follows this uses the same name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
confirmed. I’ll clean it up
| import 'edge_insets.dart'; | ||
|
|
||
| /// Utility methods for manipulating [RRect] objects. | ||
| abstract final class RRectUtils { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know that we need a new class and file for these methods. I was thinking more along the lines of a mixin. :) That could be defined in box_border.dart. Also, the docs should be clearer about the use case and how radius is incorporated into this. The docs should also link to the associated classed that are using it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I’ve moved the shared methods into borders.dart as a public RRectUtils class so both BoxBorder and TableBorder (in separate libraries) can use them without duplicating code.
Since they are in different libraries, a library-private helper wasn’t accessible from both.
I also added complete Dartdoc describing the use case, radius handling, and related classes, per the review feedback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah ok, I see, I see. Sorry about that mix up.
Now that I am not thinking about these as private, I think they should go into the EdgeInsets class, where inflateRect and deflateRect are defined. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree! Since EdgeInsets class already has similar functions like inflateRect and deflateRect, placing these methods within the same class would improve cohesion.
I'll update the PR to move the RRect utility methods to the EdgeInsets class, keeping them consistent with the existing naming pattern.
Piinks
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your patience while I was away on a business trip. 🙏
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
justinmc
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍 Thanks for your persistence on this!
| expect(deflatedThenInflated.right, closeTo(original.right, 0.001)); | ||
| expect(deflatedThenInflated.bottom, closeTo(original.bottom, 0.001)); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for writing non-widget unit tests for these new methods, this is good.
| top.strokeOutset, | ||
| right.strokeOutset, | ||
| bottom.strokeOutset, | ||
| ).inflateRRect(borderRect); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks a lot cleaner with the new insets methods 👍
|
autosubmit label was removed for flutter/flutter/172441, because The base commit of the PR is older than 7 days and can not be merged. Please merge the latest changes from the main into this branch and resubmit the PR. |
|
@korca0220 can you rebase this PR with tip of tree? We should be able to land it once that is done. Thanks! |
…#173886) https://dart.googlesource.com/sdk.git/+log/9277d6303da5..67ca79475db6 2025-08-15 [email protected] Version 3.10.0-104.0.dev If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/dart-sdk-flutter Please CC [email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
…3890) https://skia.googlesource.com/skia.git/+log/91ad1f21ca61..1e148cada9d4 2025-08-15 [email protected] [pdf] Unpremul after interpolating unpremul 2025-08-15 [email protected] Roll vulkan-deps from 2d05384af7d2 to e04b90257b5a (9 revisions) 2025-08-15 [email protected] Last users of (unneeded) RawIter If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/skia-flutter-autoroll Please CC [email protected],[email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Skia: https://bugs.chromium.org/p/skia/issues/entry To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
) https://skia.googlesource.com/skia.git/+log/1e148cada9d4..16dbd908dcab 2025-08-16 [email protected] Roll vulkan-deps from e04b90257b5a to 57d74122fab7 (1 revision) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/skia-flutter-autoroll Please CC [email protected],[email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Skia: https://bugs.chromium.org/p/skia/issues/entry To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
…72406) # Improve SweepGradient and TileMode Documentation ## Description This PR enhances the documentation for `SweepGradient` and `TileMode` to provide clearer guidance on how angles are measured and how tile modes affect sweep gradient rendering. ### Changes 1. **SweepGradient Documentation**: - Clarified angle measurement in radians from the positive x-axis - Documented angle normalization behavior for values outside [0, 2π] - Added detailed explanations of how each `TileMode` affects rendering outside the angular sector 2. **Gradient.sweep Constructor**: - Improved parameter documentation - Added a practical example showing how to create a 90-degree sweep gradient - Clarified the relationship between color stops and angles 3. **TileMode Documentation**: - Added sweep gradient-specific behavior to each `TileMode` variant - Clarified how each mode (clamp, repeated, mirror, decal) affects rendering outside the angular sector - Improved overall documentation structure for gradient edge behavior ## Related Issues Fixes flutter#166206 ## Testing - Verified documentation changes by reviewing the generated API docs - Ensured all examples compile and render as expected ## Breaking Changes None - this is purely a documentation improvement. ## Additional Notes The changes make it much clearer how `startAngle` and `endAngle` interact with different `TileMode` values, which was a source of confusion in the original issue. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md --------- Co-authored-by: Victor Sanni <[email protected]>
) https://skia.googlesource.com/skia.git/+log/16dbd908dcab..d445371afee5 2025-08-16 [email protected] Revert "Factor out common pathiter" If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/skia-flutter-autoroll Please CC [email protected],[email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Skia: https://bugs.chromium.org/p/skia/issues/entry To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
…3910) https://skia.googlesource.com/skia.git/+log/d445371afee5..a30d857718ad 2025-08-16 [email protected] Manual roll ANGLE from 63d8f74cdf9c to 806c80ece32b (6 revisions) 2025-08-16 [email protected] Manual roll Dawn from 8f680a2a9cb9 to b639f97ad620 (8 revisions) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/skia-flutter-autoroll Please CC [email protected],[email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Skia: https://bugs.chromium.org/p/skia/issues/entry To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
…... (flutter#173913) If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/fuchsia-linux-sdk-flutter Please CC [email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
ec3128b to
027042c
Compare
Recreates the implementation from PR flutter#172441 on a clean branch after resolving rebase issues. Enables border radius when outer border sides have uniform colors but different widths/styles. Also adds inflateRRect and deflateRRect methods to EdgeInsets for consistent handling of rounded rectangles.
|
@Piinks @justinmc Sorry... I've encountered issues while attempting to rebase this PR with the tip of tree. During the rebase process, many unrelated commits were accidentally included, significantly increasing the PR size Rather than trying to fix this PR directly, I've created a new clean PR #175773 with the same implementation. |
Recreates the implementation from PR flutter#172441 on a clean branch after resolving rebase issues. Enables border radius when outer border sides have uniform colors but different widths/styles. Also adds inflateRRect and deflateRRect methods to EdgeInsets for consistent handling of rounded rectangles.
Re-implementation of PR #172441 <!-- Thanks for filing a pull request! Reviewers are typically assigned within a week of filing a request. To learn more about code review, see our documentation on Tree Hygiene: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md --> ## Add non-uniform border radius support to TableBorder This PR extends TableBorder to support border radius even when the outer border sides have different widths but the same color, similar to the non-uniform border support added to Border in #121921. ### Changes - Enhanced border rendering logic: TableBorder can now apply border radius when outer border sides have uniform colors but non-uniform widths/styles - New helper methods: Added `outerBorderIsUniform` property and `distinctVisibleOuterColors()` method to determine border uniformity - Optimized paint method: Refactored the paint logic to handle three scenarios: 1. Fully uniform borders (existing optimized path) 2. Outer borders with uniform colors but non-uniform widths (new non-uniform border radius support) 3. Completely non-uniform borders (fallback to standard border painting) ### Before/After - Before: TableBorder with border radius required all sides (including inner borders) to be completely identical. - After: TableBorder with border radius only requires outer border colors to be the same, allowing different widths per side. ### Example Usage ```dart TableBorder( top: BorderSide(color: Colors.blue, width: 3.0), right: BorderSide(color: Colors.blue, width: 1.0), // Different width bottom: BorderSide(color: Colors.blue, width: 2.0), // Different width left: BorderSide.none, // No border horizontalInside: BorderSide(color: Colors.red, width: 1.0), // Different color OK verticalInside: BorderSide(color: Colors.red, width: 1.0), // Different color OK borderRadius: BorderRadius.circular(8), // ✅ Now works! ) ``` Fixes: #173193 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
Re-implementation of PR flutter#172441 <!-- Thanks for filing a pull request! Reviewers are typically assigned within a week of filing a request. To learn more about code review, see our documentation on Tree Hygiene: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md --> ## Add non-uniform border radius support to TableBorder This PR extends TableBorder to support border radius even when the outer border sides have different widths but the same color, similar to the non-uniform border support added to Border in flutter#121921. ### Changes - Enhanced border rendering logic: TableBorder can now apply border radius when outer border sides have uniform colors but non-uniform widths/styles - New helper methods: Added `outerBorderIsUniform` property and `distinctVisibleOuterColors()` method to determine border uniformity - Optimized paint method: Refactored the paint logic to handle three scenarios: 1. Fully uniform borders (existing optimized path) 2. Outer borders with uniform colors but non-uniform widths (new non-uniform border radius support) 3. Completely non-uniform borders (fallback to standard border painting) ### Before/After - Before: TableBorder with border radius required all sides (including inner borders) to be completely identical. - After: TableBorder with border radius only requires outer border colors to be the same, allowing different widths per side. ### Example Usage ```dart TableBorder( top: BorderSide(color: Colors.blue, width: 3.0), right: BorderSide(color: Colors.blue, width: 1.0), // Different width bottom: BorderSide(color: Colors.blue, width: 2.0), // Different width left: BorderSide.none, // No border horizontalInside: BorderSide(color: Colors.red, width: 1.0), // Different color OK verticalInside: BorderSide(color: Colors.red, width: 1.0), // Different color OK borderRadius: BorderRadius.circular(8), // ✅ Now works! ) ``` Fixes: flutter#173193 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
Re-implementation of PR flutter#172441 <!-- Thanks for filing a pull request! Reviewers are typically assigned within a week of filing a request. To learn more about code review, see our documentation on Tree Hygiene: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md --> ## Add non-uniform border radius support to TableBorder This PR extends TableBorder to support border radius even when the outer border sides have different widths but the same color, similar to the non-uniform border support added to Border in flutter#121921. ### Changes - Enhanced border rendering logic: TableBorder can now apply border radius when outer border sides have uniform colors but non-uniform widths/styles - New helper methods: Added `outerBorderIsUniform` property and `distinctVisibleOuterColors()` method to determine border uniformity - Optimized paint method: Refactored the paint logic to handle three scenarios: 1. Fully uniform borders (existing optimized path) 2. Outer borders with uniform colors but non-uniform widths (new non-uniform border radius support) 3. Completely non-uniform borders (fallback to standard border painting) ### Before/After - Before: TableBorder with border radius required all sides (including inner borders) to be completely identical. - After: TableBorder with border radius only requires outer border colors to be the same, allowing different widths per side. ### Example Usage ```dart TableBorder( top: BorderSide(color: Colors.blue, width: 3.0), right: BorderSide(color: Colors.blue, width: 1.0), // Different width bottom: BorderSide(color: Colors.blue, width: 2.0), // Different width left: BorderSide.none, // No border horizontalInside: BorderSide(color: Colors.red, width: 1.0), // Different color OK verticalInside: BorderSide(color: Colors.red, width: 1.0), // Different color OK borderRadius: BorderRadius.circular(8), // ✅ Now works! ) ``` Fixes: flutter#173193 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md


Add non-uniform border radius support to TableBorder
This PR extends TableBorder to support border radius even when the outer border sides have different widths but the same color, similar to the non-uniform border support added to Border in #121921.
Changes
outerBorderIsUniformproperty anddistinctVisibleOuterColors()method to determine border uniformityBefore/After
Example Usage
Fixes: #173193
Pre-launch Checklist
///).