Skip to content

Commit f2f71cb

Browse files
authored
Expose column header renderer trait in ipydatagrid (#158)
* add header_renderer trait to ipydatagrid backend * add columnHeaderRenderer (header_renderer) to ipydatagrid frontend model * add custom columnHeaderRenderer support to feathergrid
1 parent bdbaad7 commit f2f71cb

File tree

3 files changed

+67
-20
lines changed

3 files changed

+67
-20
lines changed

ipydatagrid/datagrid.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,8 @@ class DataGrid(DOMWidget):
196196
column name, and value specifies the renderer
197197
default_renderer : CellRenderer (default: TextRenderer)
198198
Default renderer to use for cell rendering
199+
header_renderer : CellRenderer (default: TextRenderer)
200+
Renderer to use for header cell rendering
199201
selection_mode : {'row', 'column', 'cell', 'none'} (default: 'none')
200202
Selection mode used when user clicks on grid or makes selections
201203
programmatically.
@@ -246,6 +248,7 @@ class DataGrid(DOMWidget):
246248

247249
renderers = Dict(Instance(CellRenderer)).tag(sync=True, **widget_serialization)
248250
default_renderer = Instance(CellRenderer).tag(sync=True, **widget_serialization)
251+
header_renderer = Instance(CellRenderer, allow_none=True).tag(sync=True, **widget_serialization)
249252
selection_mode = Enum(default_value='none', values=['row', 'column', 'cell', 'none']).tag(sync=True)
250253
selections = List(Dict).tag(sync=True, **widget_serialization)
251254
editable = Bool(False).tag(sync=True)

src/datagrid.ts

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export class DataGridModel extends DOMWidgetModel {
5151
_data: {},
5252
renderers: {},
5353
default_renderer: null,
54+
header_renderer: null,
5455
selection_mode: 'none',
5556
selections: [],
5657
editable: false,
@@ -221,6 +222,7 @@ export class DataGridModel extends DOMWidgetModel {
221222
transforms: { deserialize: unpack_models as any },
222223
renderers: { deserialize: unpack_models as any },
223224
default_renderer: { deserialize: unpack_models as any },
225+
header_renderer: { deserialize: unpack_models as any },
224226
_data: { deserialize: unpack_data as any },
225227
};
226228

@@ -366,7 +368,7 @@ export class DataGridView extends DOMWidgetView {
366368
});
367369

368370
this.model.on_some_change(
369-
['default_renderer', 'renderers'],
371+
['header_renderer', 'default_renderer', 'renderers'],
370372
() => {
371373
this.updateRenderers().then(this.updateGridRenderers.bind(this));
372374
},
@@ -394,6 +396,9 @@ export class DataGridView extends DOMWidgetView {
394396
if (this.default_renderer) {
395397
this.stopListening(this.default_renderer, 'renderer-changed');
396398
}
399+
if (this.header_renderer) {
400+
this.stopListening(this.header_renderer, 'renderer-changed');
401+
}
397402
for (const key in this.renderers) {
398403
this.stopListening(this.renderers[key], 'renderer-changed');
399404
}
@@ -416,6 +421,23 @@ export class DataGridView extends DOMWidgetView {
416421
),
417422
);
418423

424+
const header_renderer = this.model.get('header_renderer');
425+
if (header_renderer) {
426+
promises.push(
427+
this.create_child_view(header_renderer).then(
428+
(headerRendererView: any) => {
429+
this.header_renderer = headerRendererView;
430+
431+
this.listenTo(
432+
this.header_renderer,
433+
'renderer-changed',
434+
this.updateGridRenderers.bind(this),
435+
);
436+
},
437+
),
438+
);
439+
}
440+
419441
const renderer_promises: Dict<Promise<any>> = {};
420442
_.each(
421443
this.model.get('renderers'),
@@ -460,11 +482,21 @@ export class DataGridView extends DOMWidgetView {
460482

461483
private updateGridRenderers() {
462484
const defaultRenderer = this.default_renderer.renderer;
485+
let columnHeaderRenderer = null;
486+
if (this.header_renderer) {
487+
columnHeaderRenderer = this.header_renderer.renderer;
488+
}
489+
463490
const renderers: Dict<CellRenderer> = {};
464491
Object.entries(this.renderers).forEach(([name, rendererView]) => {
465492
renderers[name] = rendererView.renderer;
466493
});
494+
467495
this.grid.defaultRenderer = defaultRenderer;
496+
// Set column header renderer only if received from backend
497+
if (columnHeaderRenderer) {
498+
this.grid.columnHeaderRenderer = columnHeaderRenderer;
499+
}
468500
this.grid.renderers = renderers;
469501
}
470502

@@ -487,6 +519,7 @@ export class DataGridView extends DOMWidgetView {
487519

488520
renderers: Dict<CellRendererView>;
489521
default_renderer: CellRendererView;
522+
header_renderer: CellRendererView;
490523
grid: FeatherGrid;
491524
pWidget: JupyterPhosphorPanelWidget;
492525
model: DataGridModel;

src/feathergrid.ts

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ export class FeatherGrid extends Widget {
216216
font: '12px sans-serif',
217217
textColor: Theme.getFontColor(),
218218
backgroundColor: Theme.getBackgroundColor(),
219-
horizontalAlignment: 'left',
219+
horizontalAlignment: 'center',
220220
verticalAlignment: 'center',
221221
});
222222

@@ -270,7 +270,6 @@ export class FeatherGrid extends Widget {
270270
}
271271

272272
this.grid.dataModel = this._dataModel;
273-
this._updateHeaderRenderer();
274273
this._filterDialog.model = this._dataModel;
275274
this._updateColumnWidths();
276275
}
@@ -387,6 +386,20 @@ export class FeatherGrid extends Widget {
387386
return this._defaultRenderer;
388387
}
389388

389+
set columnHeaderRenderer(renderer: CellRenderer) {
390+
this._columnHeaderRenderer = renderer;
391+
392+
if (!this.grid) {
393+
return;
394+
}
395+
396+
this._updateGridRenderers();
397+
}
398+
399+
get columnHeaderRenderer(): CellRenderer {
400+
return this._columnHeaderRenderer;
401+
}
402+
390403
set renderers(renderers: Dict<CellRenderer>) {
391404
this._renderers = renderers;
392405

@@ -490,8 +503,6 @@ export class FeatherGrid extends Widget {
490503
}
491504

492505
public updateGridStyle() {
493-
this._updateHeaderRenderer();
494-
495506
if (!this._defaultRendererSet) {
496507
this._defaultRenderer = new TextRenderer({
497508
font: '12px sans-serif',
@@ -509,6 +520,13 @@ export class FeatherGrid extends Widget {
509520
verticalAlignment: 'center',
510521
});
511522

523+
this._columnHeaderRenderer = new TextRenderer({
524+
textColor: Theme.getFontColor(1),
525+
backgroundColor: Theme.getBackgroundColor(2),
526+
horizontalAlignment: 'left',
527+
verticalAlignment: 'center',
528+
});
529+
512530
const scrollShadow = {
513531
size: 4,
514532
color1: Theme.getBorderColor(1, 1.0),
@@ -769,6 +787,13 @@ export class FeatherGrid extends Widget {
769787

770788
private _updateGridRenderers() {
771789
this.grid.cellRenderers.update({ body: this._rendererResolver.bind(this) });
790+
this.grid.cellRenderers.update({
791+
'column-header': this._columnHeaderRenderer,
792+
});
793+
// Treating corner header as column header for rendering purposes
794+
this.grid.cellRenderers.update({
795+
'corner-header': this._columnHeaderRenderer,
796+
});
772797
this.grid.cellRenderers.update({
773798
'row-header': this._rendererResolver.bind(this),
774799
});
@@ -811,21 +836,6 @@ export class FeatherGrid extends Widget {
811836
}
812837
}
813838

814-
private _updateHeaderRenderer() {
815-
const headerRenderer = new HeaderRenderer({
816-
textOptions: {
817-
textColor: Theme.getFontColor(1),
818-
backgroundColor: Theme.getBackgroundColor(2),
819-
horizontalAlignment: 'center',
820-
},
821-
isLightTheme: this._isLightTheme,
822-
grid: this.grid,
823-
});
824-
825-
this.grid.cellRenderers.update({ 'column-header': headerRenderer });
826-
this.grid.cellRenderers.update({ 'corner-header': headerRenderer });
827-
}
828-
829839
private _createCommandRegistry(): CommandRegistry {
830840
const commands = new CommandRegistry();
831841
commands.addCommand(FeatherGridContextMenu.CommandID.SortAscending, {
@@ -950,6 +960,7 @@ export class FeatherGrid extends Widget {
950960
private _editable: boolean;
951961
private _renderers: Dict<CellRenderer> = {};
952962
private _defaultRenderer: CellRenderer;
963+
private _columnHeaderRenderer: CellRenderer;
953964
private _rowHeaderRenderer: CellRenderer;
954965
private _defaultRendererSet = false;
955966
private _cellClicked = new Signal<this, FeatherGrid.ICellClickedEvent>(this);

0 commit comments

Comments
 (0)