Skip to content

Commit 2931fbf

Browse files
committed
feat: add stubs for fieldset widget
1 parent 52663ac commit 2931fbf

File tree

4 files changed

+232
-5
lines changed

4 files changed

+232
-5
lines changed

packages/controls/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,6 @@ export * from './widget_tagsinput';
2323
export * from './widget_string';
2424
export * from './widget_description';
2525
export * from './widget_upload';
26+
export * from './widget_fieldset';
2627

2728
export const version = (require('../package.json') as any).version;
+127
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// Copyright (c) Jupyter Development Team.
2+
// Distributed under the terms of the Modified BSD License.
3+
4+
import {
5+
DOMWidgetView,
6+
unpack_models,
7+
ViewList,
8+
JupyterLuminoPanelWidget,
9+
reject,
10+
WidgetModel,
11+
WidgetView,
12+
} from '@jupyter-widgets/base';
13+
14+
import { CoreDOMWidgetModel } from './widget_core';
15+
16+
import { ArrayExt } from '@lumino/algorithm';
17+
18+
import { MessageLoop } from '@lumino/messaging';
19+
20+
import { Widget } from '@lumino/widgets';
21+
22+
import $ from 'jquery';
23+
24+
export class FieldsetModel extends CoreDOMWidgetModel {
25+
defaults(): Backbone.ObjectHash {
26+
return {
27+
...super.defaults(),
28+
_view_name: 'FieldsetView',
29+
_model_name: 'FieldsetModel',
30+
children: [],
31+
box_style: '',
32+
};
33+
}
34+
35+
static serializers = {
36+
...CoreDOMWidgetModel.serializers,
37+
children: { deserialize: unpack_models },
38+
};
39+
}
40+
41+
42+
export class FieldsetView extends DOMWidgetView {
43+
_createElement(tagName: string): HTMLElement {
44+
this.luminoWidget = new JupyterLuminoPanelWidget({ view: this });
45+
return this.luminoWidget.node;
46+
}
47+
48+
_setElement(el: HTMLElement): void {
49+
if (this.el || el !== this.luminoWidget.node) {
50+
// Boxes don't allow setting the element beyond the initial creation.
51+
throw new Error('Cannot reset the DOM element.');
52+
}
53+
54+
this.el = this.luminoWidget.node;
55+
this.$el = $(this.luminoWidget.node);
56+
}
57+
58+
initialize(parameters: WidgetView.IInitializeParameters): void {
59+
super.initialize(parameters);
60+
this.children_views = new ViewList(this.add_child_model, null, this);
61+
this.listenTo(this.model, 'change:children', this.update_children);
62+
this.listenTo(this.model, 'change:fieldset_style', this.update_fieldset_style);
63+
64+
this.luminoWidget.addClass('jupyter-widgets');
65+
this.luminoWidget.addClass('widget-container');
66+
}
67+
68+
render(): void {
69+
super.render();
70+
this.update_children();
71+
this.set_fieldset_style();
72+
}
73+
74+
update_children(): void {
75+
this.children_views
76+
?.update(this.model.get('children'))
77+
.then((views: DOMWidgetView[]) => {
78+
// Notify all children that their sizes may have changed.
79+
views.forEach((view) => {
80+
MessageLoop.postMessage(
81+
view.luminoWidget,
82+
Widget.ResizeMessage.UnknownSize
83+
);
84+
});
85+
});
86+
}
87+
88+
update_fieldset_style(): void {
89+
this.update_mapped_classes(FieldsetView.class_map, 'fieldset_style');
90+
}
91+
92+
set_fieldset_style(): void {
93+
this.set_mapped_classes(FieldsetView.class_map, 'fieldset_style');
94+
}
95+
96+
add_child_model(model: WidgetModel): Promise<DOMWidgetView> {
97+
// we insert a dummy element so the order is preserved when we add
98+
// the rendered content later.
99+
const dummy = new Widget();
100+
this.luminoWidget.addWidget(dummy);
101+
102+
return this.create_child_view(model)
103+
.then((view: DOMWidgetView) => {
104+
// replace the dummy widget with the new one.
105+
const i = ArrayExt.firstIndexOf(this.luminoWidget.widgets, dummy);
106+
this.luminoWidget.insertWidget(i, view.luminoWidget);
107+
dummy.dispose();
108+
return view;
109+
})
110+
.catch(reject('Could not add child view to fieldset', true));
111+
}
112+
113+
remove(): void {
114+
this.children_views = null;
115+
super.remove();
116+
}
117+
118+
children_views: ViewList<DOMWidgetView> | null;
119+
luminoWidget: JupyterLuminoPanelWidget;
120+
121+
static class_map = {
122+
success: ['alert', 'alert-success'],
123+
info: ['alert', 'alert-info'],
124+
warning: ['alert', 'alert-warning'],
125+
danger: ['alert', 'alert-danger'],
126+
};
127+
}

python/ipywidgets/ipywidgets/widgets/__init__.py

+36-5
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,53 @@
1111
from .widget_bool import Checkbox, ToggleButton, Valid
1212
from .widget_button import Button, ButtonStyle
1313
from .widget_box import Box, HBox, VBox, GridBox
14-
from .widget_float import FloatText, BoundedFloatText, FloatSlider, FloatProgress, FloatRangeSlider, FloatLogSlider
15-
from .widget_int import IntText, BoundedIntText, IntSlider, IntProgress, IntRangeSlider, Play, SliderStyle
14+
from .widget_float import (
15+
FloatText,
16+
BoundedFloatText,
17+
FloatSlider,
18+
FloatProgress,
19+
FloatRangeSlider,
20+
FloatLogSlider,
21+
)
22+
from .widget_int import (
23+
IntText,
24+
BoundedIntText,
25+
IntSlider,
26+
IntProgress,
27+
IntRangeSlider,
28+
Play,
29+
SliderStyle,
30+
)
1631
from .widget_color import ColorPicker
1732
from .widget_date import DatePicker
1833
from .widget_datetime import DatetimePicker, NaiveDatetimePicker
1934
from .widget_time import TimePicker
2035
from .widget_output import Output
21-
from .widget_selection import RadioButtons, ToggleButtons, ToggleButtonsStyle, Dropdown, Select, SelectionSlider, SelectMultiple, SelectionRangeSlider
22-
from .widget_selectioncontainer import Tab, Accordion, Stack
36+
from .widget_selection import (
37+
RadioButtons,
38+
ToggleButtons,
39+
ToggleButtonsStyle,
40+
Dropdown,
41+
Select,
42+
SelectionSlider,
43+
SelectMultiple,
44+
SelectionRangeSlider,
45+
)
46+
from .....branches.widget_selectioncontainer import Tab, Accordion, Stack
2347
from .widget_string import HTML, HTMLMath, Label, Text, Textarea, Password, Combobox
2448
from .widget_controller import Controller
25-
from .interaction import interact, interactive, fixed, interact_manual, interactive_output
49+
from .interaction import (
50+
interact,
51+
interactive,
52+
fixed,
53+
interact_manual,
54+
interactive_output,
55+
)
2656
from .widget_link import jslink, jsdlink
2757
from .widget_layout import Layout
2858
from .widget_media import Image, Video, Audio
2959
from .widget_tagsinput import TagsInput, ColorsInput, FloatsInput, IntsInput
3060
from .widget_style import Style
3161
from .widget_templates import TwoByTwoLayout, AppLayout, GridspecLayout
3262
from .widget_upload import FileUpload
63+
from .widget_fieldset import Fieldset
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Copyright (c) Jupyter Development Team.
2+
# Distributed under the terms of the Modified BSD License.
3+
4+
"""Fieldset widget.
5+
6+
This widget is used to group other control widgets into a fieldset.
7+
"""
8+
9+
from .widget import register, widget_serialization, Widget
10+
from .domwidget import DOMWidget
11+
from .widget_core import CoreWidget
12+
from .docutils import doc_subst
13+
from .trait_types import TypedTuple
14+
from traitlets import Unicode, CaselessStrEnum, Instance
15+
16+
17+
_doc_snippets = {}
18+
_doc_snippets[
19+
"box_params"
20+
] = """
21+
children: iterable of Widget instances
22+
list of widgets to display
23+
24+
box_style: str
25+
one of 'success', 'info', 'warning' or 'danger', or ''.
26+
Applies a predefined style to the box. Defaults to '',
27+
which applies no pre-defined style.
28+
"""
29+
30+
31+
@register
32+
@doc_subst(_doc_snippets)
33+
class Fieldset(DOMWidget, CoreWidget):
34+
"""Displays controls grouped together, optionally with a caption.
35+
36+
The widgets are laid out horizontally.
37+
38+
Parameters
39+
----------
40+
{box_params}
41+
42+
Examples
43+
--------
44+
>>> import ipywidgets as widgets
45+
>>> slider = widgets.IntSlider()
46+
>>> widgets.Fieldset(legend="Fieldset Example", children=[slider])
47+
"""
48+
49+
_model_name = Unicode("FieldsetModel").tag(sync=True)
50+
_view_name = Unicode("FieldsetView").tag(sync=True)
51+
52+
# Child widgets in the container.
53+
# Using a tuple here to force reassignment to update the list.
54+
# When a proper notifying-list trait exists, use that instead.
55+
children = TypedTuple(trait=Instance(Widget), help="List of widget children").tag(
56+
sync=True, **widget_serialization
57+
)
58+
59+
box_style = CaselessStrEnum(
60+
values=["success", "info", "warning", "danger", ""],
61+
default_value="",
62+
help="""Use a predefined styling for the box.""",
63+
).tag(sync=True)
64+
65+
def __init__(self, legend="", children=(), **kwargs):
66+
kwargs["legend"] = legend
67+
kwargs["children"] = children
68+
super().__init__(**kwargs)

0 commit comments

Comments
 (0)