Skip to content
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

[two_dimensional_scrollables] TableSpanDecoration error in reverse #141704

Closed
Piinks opened this issue Jan 17, 2024 · 1 comment · Fixed by flutter/packages#5916
Closed

[two_dimensional_scrollables] TableSpanDecoration error in reverse #141704

Piinks opened this issue Jan 17, 2024 · 1 comment · Fixed by flutter/packages#5916
Assignees
Labels
f: scrolling Viewports, list views, slivers, etc. framework flutter/packages/flutter repository. See also f: labels. p: two_dimensional_scrollables Issues pertaining to the two_dimensional_scrollables package P2 Important issues not at the top of the work list team-framework Owned by Framework team triaged-framework Triaged by Framework team waiting for PR to land (fixed) A fix is in flight

Comments

@Piinks
Copy link
Contributor

Piinks commented Jan 17, 2024

image

Tweaking the example code in the package can reproduce. Found while working on merged cells. It looks like in reverse, the rect for the TableSpanDecoration is not computed correctly.

// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:two_dimensional_scrollables/two_dimensional_scrollables.dart';

// Print statements are only for illustrative purposes, not recommended for
// production applications.
// ignore_for_file: avoid_print

void main() {
  runApp(const TableExampleApp());
}

/// A sample application that utilizes the TableView API.
class TableExampleApp extends StatelessWidget {
  /// Creates an instance of the TableView example app.
  const TableExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Table Example',
      theme: ThemeData(
        useMaterial3: true,
      ),
      home: const TableExample(),
    );
  }
}

/// The class containing the TableView for the sample application.
class TableExample extends StatefulWidget {
  /// Creates a screen that demonstrates the TableView widget.
  const TableExample({super.key});

  @override
  State<TableExample> createState() => _TableExampleState();
}

class _TableExampleState extends State<TableExample> {
  late final ScrollController _verticalController = ScrollController();
  int _rowCount = 20;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Table Example'),
      ),
      body: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 50),
        child: TableView.builder(
          verticalDetails:
              ScrollableDetails.vertical(controller: _verticalController, reverse: true,),
          horizontalDetails: ScrollableDetails.horizontal(reverse: true),
          cellBuilder: _buildCell,
          columnCount: 20,
          columnBuilder: _buildColumnSpan,
          rowCount: _rowCount,
          rowBuilder: _buildRowSpan,
        ),
      ),
      persistentFooterButtons: <Widget>[
        TextButton(
          onPressed: () {
            _verticalController.jumpTo(0);
          },
          child: const Text('Jump to Top'),
        ),
        TextButton(
          onPressed: () {
            _verticalController
                .jumpTo(_verticalController.position.maxScrollExtent);
          },
          child: const Text('Jump to Bottom'),
        ),
        TextButton(
          onPressed: () {
            setState(() {
              _rowCount += 10;
            });
          },
          child: const Text('Add 10 Rows'),
        ),
      ],
    );
  }

  Widget _buildCell(BuildContext context, TableVicinity vicinity) {
    return Center(
      child: Text('Tile c: ${vicinity.column}, r: ${vicinity.row}'),
    );
  }

  TableSpan _buildColumnSpan(int index) {
    final TableSpanDecoration decoration = TableSpanDecoration(
      color: Colors.blue[100]!.withOpacity(0.6),
      border: const TableSpanBorder(
        leading: BorderSide(),
        trailing: BorderSide(),
      ),
    );

    switch (index % 5) {
      case 0:
        return TableSpan(
          foregroundDecoration: decoration,
          extent: const FixedTableSpanExtent(100),
          onEnter: (_) => print('Entered column $index'),
          recognizerFactories: <Type, GestureRecognizerFactory>{
            TapGestureRecognizer:
                GestureRecognizerFactoryWithHandlers<TapGestureRecognizer>(
              () => TapGestureRecognizer(),
              (TapGestureRecognizer t) =>
                  t.onTap = () => print('Tap column $index'),
            ),
          },
        );
      case 1:
        return TableSpan(
          foregroundDecoration: decoration,
          extent: const FractionalTableSpanExtent(0.5),
          onEnter: (_) => print('Entered column $index'),
          cursor: SystemMouseCursors.contextMenu,
        );
      case 2:
        return TableSpan(
          foregroundDecoration: decoration,
          extent: const FixedTableSpanExtent(120),
          onEnter: (_) => print('Entered column $index'),
        );
      case 3:
        return TableSpan(
          foregroundDecoration: decoration,
          extent: const FixedTableSpanExtent(145),
          onEnter: (_) => print('Entered column $index'),
        );
      case 4:
        return TableSpan(
          foregroundDecoration: decoration,
          extent: const FixedTableSpanExtent(200),
          onEnter: (_) => print('Entered column $index'),
        );
    }
    throw AssertionError(
        'This should be unreachable, as every index is accounted for in the switch clauses.');
  }

  TableSpan _buildRowSpan(int index) {
    final TableSpanDecoration decoration = TableSpanDecoration(
      color: Colors.purple[100]!.withOpacity(0.6),
      border: const TableSpanBorder(
        leading: BorderSide(),
        trailing: BorderSide(),
      ),
    );

    switch (index % 3) {
      case 0:
        return TableSpan(
          backgroundDecoration: decoration,
          extent: const FixedTableSpanExtent(50),
          recognizerFactories: <Type, GestureRecognizerFactory>{
            TapGestureRecognizer:
                GestureRecognizerFactoryWithHandlers<TapGestureRecognizer>(
              () => TapGestureRecognizer(),
              (TapGestureRecognizer t) =>
                  t.onTap = () => print('Tap row $index'),
            ),
          },
        );
      case 1:
        return TableSpan(
          backgroundDecoration: decoration,
          extent: const FixedTableSpanExtent(65),
          cursor: SystemMouseCursors.click,
        );
      case 2:
        return TableSpan(
          backgroundDecoration: decoration,
          extent: const FractionalTableSpanExtent(0.15),
        );
    }
    throw AssertionError(
        'This should be unreachable, as every index is accounted for in the switch clauses.');
  }
}
@Piinks Piinks added framework flutter/packages/flutter repository. See also f: labels. f: scrolling Viewports, list views, slivers, etc. P2 Important issues not at the top of the work list team-framework Owned by Framework team triaged-framework Triaged by Framework team p: two_dimensional_scrollables Issues pertaining to the two_dimensional_scrollables package labels Jan 17, 2024
@Piinks Piinks self-assigned this Jan 17, 2024
@Piinks Piinks added the waiting for PR to land (fixed) A fix is in flight label Jan 17, 2024
auto-submit bot pushed a commit to flutter/packages that referenced this issue Jan 22, 2024
… are reversed (#5916)

Fixes flutter/flutter#141704

This fixes the rect computation for TableSpanDecorations when one or both axes are reversed.
We previously fixed similar issues when the clipRects applied to areas of the table did not account for reversed. This is another similar case.
- #5187
- #5038

![image](https://github.com/flutter/packages/assets/16964204/ae7c6872-c740-4617-95a4-8302a3085d59)
Copy link

github-actions bot commented Feb 6, 2024

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 6, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
f: scrolling Viewports, list views, slivers, etc. framework flutter/packages/flutter repository. See also f: labels. p: two_dimensional_scrollables Issues pertaining to the two_dimensional_scrollables package P2 Important issues not at the top of the work list team-framework Owned by Framework team triaged-framework Triaged by Framework team waiting for PR to land (fixed) A fix is in flight
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

1 participant