StructBond Module
The StructBondModule submodule of PlutoExtras defines and exports functionality to easily create widgets for custom structure and combine multiple bonds together in a convenient floating side table.
The StructBondModule is currently not re-exported by PlutoExtras so it has to be explicitly used with using PlutoExtras.StructBondModule
Open the structbond test notebook static html to see the look of the widgets exported.
Or open the related notebook directy in Pluto to check their functionality in action!
The notebook must be run from the original folder (test/notebooks
) within the PlutoExtras
package folder to properly load the PlutoExtras package
StructBond
Generating automatic widgets for custom structs is quite straightforward with the aid of the @fielddata
macro and the StructBond
type.
The StructBond
structure wraps another structure and generates a widget that can be used together with @bind
to obtain instances of a custom structure. In order to correctly display the widget, the description and widget associated to each field of the structure must be specified either.
This can be done either using @fielddata
as in the example video below or by using the separate @fieldbond
and @fielddescription
separately.
@NTBond
Sometimes custom structs are not needed and it would be useful to just use the same nice bond structure of StructBond
to simply create arbitrary NamedTuples.
This is possible with the convenience macro @NTBond
which can be called as shown below to create a nice display for an interactive bond creating an arbitrary NamedTuple.
The macro simply create a StructBond
wrapping the desired NamedTuple type.
@BondsList
In some cases, one does not want to have a single bond wrapping either a Structure or a NamedTuple because single independent bonds are more convenient.
@BondsList
is a convenience macro to create an object of type BondsList
which simply allow to add a description to separate bonds and group them all together in a table-like format equivalent to those of StructBond
.
Unlike StructBond
, a BondsList is already composed of bond created with @bind
and it just groups them up with a description. The output of @BondsList
is not supposed to be bound to a variable using @bind
.
The bonds grouped in a BondsList still act and update independently from one another.
See the example below for understanding the synthax. The header of a BondsList is shown in an orange background to easily differentiate it from StructBond
.
Popout/popoutwrap
The structures above can also be used nested within one another. To facilitate accessing nested structures, one can use the Popout
type.
In its simple form, you can give an instance of a StructBond, a bond wrapping a StructBond or a BondsList as input to Popout to create a table that is hidden behind a popup window. If an instance present, but you want a custom type for which you have defined custom bonds and descriptions with @fielddata
to appear as popout, you can use the function popoutwrap(TYPE)
to generate a small icon which hides a popup containing the StructBond
of the provided type TYPE
.
The StructBond table appears on hover upon the icon, can be made fixed by clicking on the icon and can then be moved around or resized. A double click on the header of the popout hides it again:
The ability to also wrap pre-existing bonds around StructBonds is convenient for organizing the various bonds one have in a BondsList
or BondTable
As an example, one can create a BondsList
containing the two StructBond
bonds generated at the beginning of this notebook (the videos in the structbond section above) like in the following example:
BondTable
The final convenience structure provided by this module is the BondTable
. It can be created to group a list of bonds in a floating table that stays on the left side of the notebook (similar to the TableOfContents of PlutoUI) and can be moved around and resized or hidden for convenience.
The BondTable is intended to be used either with bonds containing StructBond
or with BondsList
. Future types with similar structure will also be added.
Here is an example of a bondtable containing all the examples seen so far.
API
Main
PlutoExtras.StructBondModule.StructBond
— TypeStructBond(T;description = typedescription(T))
Create an HTML widget to be used with @bind
from Pluto that allows to define the custom type T
by assigning a widget to each of its fields. The widget will automatically use the docstring of each field as its description if present, or the fieldname otherwise.
When used with @bind
, it automatically generates a instance of T
by using the various fields as keyword arguments. *This means that the the structure T
has to support a keyword-only contruction, such as those generated with Base.@kwdef
or Parameters.@with_kw
.
In order to work, the widget (and optionally the description) to associate to eachfield of type T
has to be provided using the convenience macro @fielddata
.
The optional description
kwarg default to the Type name but can be overridden with anything showable as MIME"text/html"
See also: BondTable
, @NTBond
, @BondsList
, Popout
, popoutwrap
, @fielddata
, @fieldhtml
, @typeasfield
, @popoutasfield
PlutoExtras.StructBondModule.@fielddata
— Macro@fielddata typename block
Convenience macro to define custom widgets for each field of typename
. This is mostly inteded to be used in combintation with StructBond
.
Given for example the following structure ASD
, one can create a nice widget to create instances of type ASD
wih the following code:
begin
Base.@kwdef struct ASD
a::Int
b::Int
c::String
d::String
end
@fielddata ASD begin
a = (md"Magical field with markdown description", Slider(1:10))
b = (@htl("<span>Field with HTML description</span>"), Scrubbable(1:10))
c = ("Normal String Description", TextField())
d = TextField()
end
@bind asd StructBond(ASD)
end
where asd
will be an instance of type ASD
with each field interactively controllable by the specified widgets and showing the field description next to each widget. The rightside argument of each :(=)
in the block
can either be a single element or a tuple of 2 elements. In case a single elemnent is provided, the provided value is interpreted as the fieldbond
, so the bond/widget to show for that field. If two elements are given, the first is assigned to the description and the second as the bond to show
See also: BondTable
, StructBond
, @NTBond
, Popout
, popoutwrap
, @fieldbond
, @fielddescription
, @fieldhtml
, @typeasfield
, @popoutasfield
PlutoExtras.StructBondModule.@NTBond
— Macro@NTBond description block
Convenience macro to create a StructBond
wrapping a NamedTuple with field names provided in the second argument block
.
Useful when one wants a quick way of generating a bond that creates a NamedTuple. An example usage is given in the code below:
@bind nt @NTBond "My Fancy NTuple" begin
a = ("Description", Slider(1:10))
b = (md"*Bold* field", Slider(1:10))
c = Slider(1:10) # No description, defaults to the name of the field
end
which will create a NamedTuple{(:a, :b, :c)}
and assign it to variable nt
.
See also: BondTable
, @NTBond
, @BondsList
, Popout
, popoutwrap
, @fielddata
, @fieldhtml
, @typeasfield
, @popoutasfield
PlutoExtras.StructBondModule.@BondsList
— Macro@BondsList description block
Convenience macro to create a BondsList
, which is a grouping of a various bonds (created with @bind
) inside a table-like HTML output that can be used inside BondTable
. Each bond can additionally be associated to a custom description. The block
given as second input to this macro must be a begin
or let
block where each line is an assignment of the type description = bond
. The description can be anything that has a show
method for MIME type text/html
.
An example usage is given in the code below:
@BondsList "My Group of Bonds" let tv = PlutoUI.Experimental.transformed_value
# We use transformed_value to translate GHz to Hz in the bound variable `freq`
"Frequency [GHz]" = @bind freq tv(x -> x * 1e9, Slider(1:10))
md"Altitude ``h`` [m]" = @bind alt Scrubbable(100:10:200)
end
which will create a table-like display grouping together the bonds for the frequency freq
and the altitude alt
.
Unlike StructBond
, the output of @BondsList
is not supposed to be bound using @bind
, as it just groups pre-existing bonds. Also unlike StructBond
, each row of a BondsList
upates its corresponding bond independently from the other rows.
To help identify and differentiate a BondsList
from a StructBond
See also: BondTable
, @NTBond
, StructBond
, Popout
, popoutwrap
, @fielddata
, @fieldhtml
, @typeasfield
, @popoutasfield
PlutoExtras.StructBondModule.popoutwrap
— Functionpopoutwrap(T)
Convenience function to construct a Popout
wrapping a StructBond
of type T
. This is convenient when one wants to create nested StructBond
types.
Given for example the following two structures
Base.@kwdef struct ASD
a::Int
b::Int
c::String
end
Base.@kwdef struct LOL
asd::ASD
text::String
end
one can create a nice widget to create instances of type LOL
that also include a popout of widget generating ASD
wih the following code:
# Define the widget for ASD
@fieldbond ASD begin
a = Slider(1:10)
b = Scrubbable(1:10)
c = TextField()
end
@fielddescription ASD begin
a = md"Magical field with markdown description"
b = @htl "<span>Field with HTML description</span>"
c = "Normal String Description"
end
# Define the widget for LOL
@fieldbond LOL begin
asd = popoutwrap(ASD)
text = TextField(;default = "Some Text")
end
@fielddescription LOL begin
asd = "Click on the icon to show the widget to generate this field"
text = "Boring Description"
end
@bind lol StructBond(LOL)
where lol
will be an instance of type LOL
with each field interactively controllable by the specified widgets and showing the field description next to each widget.
See also: BondTable
, StructBond
, Popout
, @fieldbond
, @fielddescription
, @fieldhtml
, @typeasfield
, @popoutasfield
PlutoExtras.StructBondModule.BondTable
— TypeBondTable(bondarray; description, collapsed)
Take as input an array of bonds and creates a floating table that show all the bonds in the input array.
If description
is not provided, it defaults to the text BondTable. Description can be either a string or a HTML output.
The optional collapsed
kwarg can be used to specify whether the BondTable should stay collapsed or not when shown. If not provided, the BondTable will not be collapsed.
The collapsed status of the BondTable is persistent across reactive runs of the cell showing the BondTable.
See also: StructBond
, Popout
, popoutwrap
, @fieldbond
, @fielddescription
, @fieldhtml
, @typeasfield
, @popoutasfield
Secondary/Advanced
PlutoExtras.StructBondModule.@fieldbond
— Macro@fieldbond typename block
Convenience macro to define custom widgets for each field of typename
. This is mostly inteded to be used in combintation with StructBond
.
Given for example the following structure
Base.@kwdef struct ASD
a::Int
b::Int
c::String
end
one can create a nice widget to create instances of type ASD
wih the following code:
@fieldbond ASD begin
a = Slider(1:10)
b = Scrubbable(1:10)
c = TextField()
end
@fielddescription ASD begin
a = md"Magical field with markdown description"
b = @htl "<span>Field with HTML description</span>"
c = "Normal String Description"
end
@bind asd StructBond(ASD)
where asd
will be an instance of type ASD
with each field interactively controllable by the specified widgets and showing the field description next to each widget.
See also: BondTable
, StructBond
, Popout
, popoutwrap
, @fielddescription
, @fieldhtml
, @typeasfield
, @popoutasfield
PlutoExtras.StructBondModule.@fielddescription
— Macro@fielddescription typename block
Convenience macro to define custom descriptions for the widgets of each field of typename
. This is mostly inteded to be used in combintation with StructBond
.
Given for example the following structure
Base.@kwdef struct ASD
a::Int
b::Int
c::String
end
one can create a nice widget to create instances of type ASD
wih the following code:
@fieldbond ASD begin
a = Slider(1:10)
b = Scrubbable(1:10)
c = TextField()
end
@fielddescription ASD begin
a = md"Magical field with markdown description"
b = @htl "<span>Field with HTML description</span>"
c = "Normal String Description"
end
@bind asd StructBond(ASD)
where asd
will be an instance of type ASD
with each field interactively controllable by the specified widgets and showing the field description next to each widget.
See also: BondTable
, StructBond
, Popout
, popoutwrap
, @fieldbond
, @fieldhtml
, @typeasfield
, @popoutasfield
PlutoExtras.StructBondModule.Popout
— TypePopout(T)
Create an HTML widget wrapping the widget T
and showing it either on hover or upon click.
This is useful to generat widgets to be used with StructBond
for custom fields whose types are custom Types.
The convenience function popoutwrap
can be used to directly create a Popup
of a StructBond{T}
to facilitate nested StructBond
views.
See also: BondTable
, StructBond
, popoutwrap
, @fieldbond
, @fielddescription
, @fieldhtml
, @typeasfield
, @popoutasfield
PlutoExtras.StructBondModule.@popoutasfield
— Macro@popoutasfield T
@popoutasfield T1 T2 ...
This macro will make the default widget for fields of type T
a Popout
wrapping a StructBond{T}
type. For this to work, the StructBond{T}
must have a default widget associated to each of its field, either by using @fieldbond
or @typeasfield
Example (in Pluto)
# ╔═╡ 8db82e94-5c81-4c52-9228-7e22395fb68f
using PlutoExtras.StructBondModule
# ╔═╡ 86a80228-f495-43e8-b1d4-c93b7b52c8d8
begin
@kwdef struct MAH
a::Int
end
@kwdef struct BOH
mah::MAH
end
# This will make the default widget for an Int a Slider
@typeasfield Int = Slider(1:10)
# This will make the default widget for fields of type ASD a popout that wraps a StructBond{ASD}
@popoutasfield MAH
@bind boh StructBond(BOH)
end
# ╔═╡ 2358f686-1950-40f9-9d5c-dac2d98f4c24
boh === BOH(MAH(1))
PlutoExtras.StructBondModule.@typeasfield
— Macro@typeasfield T = Widget
@typeasfield begin
T1 = Widget1
T2 = Widget2
...
end
Macro to give a default widget for a specific type T
, T1
, or T2
. This can be over-ridden by specifying a more specific default for a custom type using @fieldbond
When a custom type is wrapped inside a StructBond
and a custom widget for one of its field is not defined, the show method will use the one defined by this macro for the field type.
Examples
The following julia code will error because a default widget is not defined for field a
using PlutoExtras.StructBondModule
struct ASD
a::Int
end
StructBond(ASD)
Apart from defining a specific value for ASD
with @fieldbond
, one can also define a default widget for Int with:
@typeasfield Int = Slider(1:10)
Now calling StructBond(ASD)
will not error and will default to showing a Slider(1:10)
as bond for field a
of ASD
.