ipydatagrid icon indicating copy to clipboard operation
ipydatagrid copied to clipboard

Come with an automatic way of setting the minimum grid size

Open gaborbernat opened this issue 3 years ago • 1 comments

Seems we generate extra space at the bottom of short grids:

FWIW I just checked on the binder link provided by the repo and I get the same effect, so at least you should be able to reproduce it easily... image

We do have a workaround for it:

The issue you are seeing with the blank space is the default canvas size. We don't have an intelligent way (yet) of determining a good default size for a given grid, so they all have the same one, and I agree it does look a bit odd for smaller grids. The good news is that this is a layout property and as such you pass it as a parameter to the grid constructor:

from ipydatagrid import DataGrid
import pandas as pd

df = pd.DataFrame({"A":[1,2,3], "B":[4,5,6]})
grid = DataGrid(df, layout={"height":"120px", "width":"200px", "align-content":"center"})
grid

This issue is to track in finding an automated way of setting the grid size to a just-right size.

gaborbernat avatar Mar 11 '21 08:03 gaborbernat

I have a solution to this.

from copy import deepcopy
from ipydatagrid import DataGrid


class DataGrid2(DataGrid):
    _max_width = 576
    _max_height = 600
    _adjustment = 25
    def __init__(self, dataframe, **kwargs):

        if "index_name" in kwargs:
            self._index_name = kwargs["index_name"]
        else:
            self._index_name = None

        self._first_call = True
        self._layout_init = kwargs.get('layout', {})

        self.data = dataframe
        df = self.data
        kwargs = self.auto_resize_grid(df, **kwargs)

        super().__init__(dataframe, **kwargs)

    def auto_resize_grid(self, data, **kwargs):
        df = data
        max_width = kwargs.pop('max_width', self._max_width)
        max_height = kwargs.pop('max_height', self._max_height)
        adjustment = kwargs.pop('adjustment', self._adjustment)

        column_widths = kwargs.get('column_widths', {})
        base_row_size = kwargs.get('base_row_size', 20)
        base_column_size = kwargs.get('base_column_size', 64)
        base_row_header_size = kwargs.get('base_row_header_size', 64)
        base_column_header_size = kwargs.get('base_column_header_size', 20)
        index_names = [*df.index.names]
        index_size = np.sum([column_widths.get(v, base_row_header_size) for v in index_names])
        columns_size = np.sum([column_widths.get(v, base_column_size) for v in df.columns])
        print(column_widths)
        print([column_widths.get(v, base_column_size) for v in df.columns])

        width = index_size + columns_size + adjustment
        height = len(df) * base_row_size + df.columns.nlevels * base_column_header_size + adjustment
        layout = kwargs.pop('layout', {})
        lo_width = layout.get('width', f"{width if width < max_width else ''}px")
        lo_height = layout.get('height', f"{height if height < max_height else ''}px")
        if lo_width != 'px':
            layout['width'] = lo_width
        if lo_height != 'px':
            layout['height'] = lo_height
        layout["align-content"] = "center"
        kwargs['layout'] = layout
        return kwargs

    @DataGrid.data.setter
    def data(self, dataframe):
        # Reference for the original frame column and index names
        # This is used to when returning the view data model
        self.__dataframe_reference_index_names = dataframe.index.names
        self.__dataframe_reference_columns = dataframe.columns
        dataframe = dataframe.copy()

        # Primary key used
        index_key = self.get_dataframe_index(dataframe)

        self._data = self.generate_data_object(
            dataframe, "ipydguuid", index_key
        )

        if not self._first_call:
            kwargs = self.auto_resize_grid(
                self.data,
                column_widths=self.column_widths,
                base_row_size=self.base_row_size,
                base_column_size=self.base_column_size,
                base_row_header_size=self.base_row_header_size,
                base_column_header_size=self.base_column_header_size,
                layout=deepcopy(self._layout_init)
            )

            self.layout = kwargs['layout']
        else:
            self._first_call = False

gioxc88 avatar Oct 12 '22 22:10 gioxc88