Skip to content

Commit

Permalink
feat: add stubs for fieldset widget
Browse files Browse the repository at this point in the history
  • Loading branch information
urbanophile committed Nov 29, 2023
1 parent 52663ac commit 2931fbf
Show file tree
Hide file tree
Showing 4 changed files with 232 additions and 5 deletions.
1 change: 1 addition & 0 deletions packages/controls/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ export * from './widget_tagsinput';
export * from './widget_string';
export * from './widget_description';
export * from './widget_upload';
export * from './widget_fieldset';

export const version = (require('../package.json') as any).version;
127 changes: 127 additions & 0 deletions packages/controls/src/widget_fieldset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.

import {
DOMWidgetView,
unpack_models,
ViewList,
JupyterLuminoPanelWidget,
reject,
WidgetModel,
WidgetView,
} from '@jupyter-widgets/base';

import { CoreDOMWidgetModel } from './widget_core';

import { ArrayExt } from '@lumino/algorithm';

import { MessageLoop } from '@lumino/messaging';

import { Widget } from '@lumino/widgets';

import $ from 'jquery';

export class FieldsetModel extends CoreDOMWidgetModel {
defaults(): Backbone.ObjectHash {
return {
...super.defaults(),
_view_name: 'FieldsetView',
_model_name: 'FieldsetModel',
children: [],
box_style: '',
};
}

static serializers = {
...CoreDOMWidgetModel.serializers,
children: { deserialize: unpack_models },
};
}


export class FieldsetView extends DOMWidgetView {
_createElement(tagName: string): HTMLElement {
this.luminoWidget = new JupyterLuminoPanelWidget({ view: this });
return this.luminoWidget.node;
}

_setElement(el: HTMLElement): void {
if (this.el || el !== this.luminoWidget.node) {
// Boxes don't allow setting the element beyond the initial creation.
throw new Error('Cannot reset the DOM element.');
}

this.el = this.luminoWidget.node;
this.$el = $(this.luminoWidget.node);
}

initialize(parameters: WidgetView.IInitializeParameters): void {
super.initialize(parameters);
this.children_views = new ViewList(this.add_child_model, null, this);
this.listenTo(this.model, 'change:children', this.update_children);
this.listenTo(this.model, 'change:fieldset_style', this.update_fieldset_style);

this.luminoWidget.addClass('jupyter-widgets');
this.luminoWidget.addClass('widget-container');
}

render(): void {
super.render();
this.update_children();
this.set_fieldset_style();
}

update_children(): void {
this.children_views
?.update(this.model.get('children'))
.then((views: DOMWidgetView[]) => {
// Notify all children that their sizes may have changed.
views.forEach((view) => {
MessageLoop.postMessage(
view.luminoWidget,
Widget.ResizeMessage.UnknownSize
);
});
});
}

update_fieldset_style(): void {
this.update_mapped_classes(FieldsetView.class_map, 'fieldset_style');
}

set_fieldset_style(): void {
this.set_mapped_classes(FieldsetView.class_map, 'fieldset_style');
}

add_child_model(model: WidgetModel): Promise<DOMWidgetView> {
// we insert a dummy element so the order is preserved when we add
// the rendered content later.
const dummy = new Widget();
this.luminoWidget.addWidget(dummy);

return this.create_child_view(model)
.then((view: DOMWidgetView) => {
// replace the dummy widget with the new one.
const i = ArrayExt.firstIndexOf(this.luminoWidget.widgets, dummy);
this.luminoWidget.insertWidget(i, view.luminoWidget);
dummy.dispose();
return view;
})
.catch(reject('Could not add child view to fieldset', true));
}

remove(): void {
this.children_views = null;
super.remove();
}

children_views: ViewList<DOMWidgetView> | null;
luminoWidget: JupyterLuminoPanelWidget;

static class_map = {
success: ['alert', 'alert-success'],
info: ['alert', 'alert-info'],
warning: ['alert', 'alert-warning'],
danger: ['alert', 'alert-danger'],
};
}
41 changes: 36 additions & 5 deletions python/ipywidgets/ipywidgets/widgets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,53 @@
from .widget_bool import Checkbox, ToggleButton, Valid
from .widget_button import Button, ButtonStyle
from .widget_box import Box, HBox, VBox, GridBox
from .widget_float import FloatText, BoundedFloatText, FloatSlider, FloatProgress, FloatRangeSlider, FloatLogSlider
from .widget_int import IntText, BoundedIntText, IntSlider, IntProgress, IntRangeSlider, Play, SliderStyle
from .widget_float import (
FloatText,
BoundedFloatText,
FloatSlider,
FloatProgress,
FloatRangeSlider,
FloatLogSlider,
)
from .widget_int import (
IntText,
BoundedIntText,
IntSlider,
IntProgress,
IntRangeSlider,
Play,
SliderStyle,
)
from .widget_color import ColorPicker
from .widget_date import DatePicker
from .widget_datetime import DatetimePicker, NaiveDatetimePicker
from .widget_time import TimePicker
from .widget_output import Output
from .widget_selection import RadioButtons, ToggleButtons, ToggleButtonsStyle, Dropdown, Select, SelectionSlider, SelectMultiple, SelectionRangeSlider
from .widget_selectioncontainer import Tab, Accordion, Stack
from .widget_selection import (
RadioButtons,
ToggleButtons,
ToggleButtonsStyle,
Dropdown,
Select,
SelectionSlider,
SelectMultiple,
SelectionRangeSlider,
)
from .....branches.widget_selectioncontainer import Tab, Accordion, Stack
from .widget_string import HTML, HTMLMath, Label, Text, Textarea, Password, Combobox
from .widget_controller import Controller
from .interaction import interact, interactive, fixed, interact_manual, interactive_output
from .interaction import (
interact,
interactive,
fixed,
interact_manual,
interactive_output,
)
from .widget_link import jslink, jsdlink
from .widget_layout import Layout
from .widget_media import Image, Video, Audio
from .widget_tagsinput import TagsInput, ColorsInput, FloatsInput, IntsInput
from .widget_style import Style
from .widget_templates import TwoByTwoLayout, AppLayout, GridspecLayout
from .widget_upload import FileUpload
from .widget_fieldset import Fieldset
68 changes: 68 additions & 0 deletions python/ipywidgets/ipywidgets/widgets/widget_fieldset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.

"""Fieldset widget.
This widget is used to group other control widgets into a fieldset.
"""

from .widget import register, widget_serialization, Widget
from .domwidget import DOMWidget
from .widget_core import CoreWidget
from .docutils import doc_subst
from .trait_types import TypedTuple
from traitlets import Unicode, CaselessStrEnum, Instance


_doc_snippets = {}
_doc_snippets[
"box_params"
] = """
children: iterable of Widget instances
list of widgets to display
box_style: str
one of 'success', 'info', 'warning' or 'danger', or ''.
Applies a predefined style to the box. Defaults to '',
which applies no pre-defined style.
"""


@register
@doc_subst(_doc_snippets)
class Fieldset(DOMWidget, CoreWidget):
"""Displays controls grouped together, optionally with a caption.
The widgets are laid out horizontally.
Parameters
----------
{box_params}
Examples
--------
>>> import ipywidgets as widgets
>>> slider = widgets.IntSlider()
>>> widgets.Fieldset(legend="Fieldset Example", children=[slider])
"""

_model_name = Unicode("FieldsetModel").tag(sync=True)
_view_name = Unicode("FieldsetView").tag(sync=True)

# Child widgets in the container.
# Using a tuple here to force reassignment to update the list.
# When a proper notifying-list trait exists, use that instead.
children = TypedTuple(trait=Instance(Widget), help="List of widget children").tag(
sync=True, **widget_serialization
)

box_style = CaselessStrEnum(
values=["success", "info", "warning", "danger", ""],
default_value="",
help="""Use a predefined styling for the box.""",
).tag(sync=True)

def __init__(self, legend="", children=(), **kwargs):
kwargs["legend"] = legend
kwargs["children"] = children
super().__init__(**kwargs)

0 comments on commit 2931fbf

Please sign in to comment.