doc: Move the new widget documentation to a new file
This will help with discoverability
This commit is contained in:
parent
8be1104615
commit
b1e69dba8c
|
@ -0,0 +1,113 @@
|
||||||
|
# Creating new widget
|
||||||
|
|
||||||
|
All widgets have to be generated via this function so that
|
||||||
|
the needed signals are added and mouse input handling is set up.
|
||||||
|
|
||||||
|
The returned widget will have a `:buttons` member function that can be used to
|
||||||
|
register a set of mouse button events with the widget.
|
||||||
|
|
||||||
|
To implement your own widget, you can implement some member functions on a
|
||||||
|
freshly-created widget. Note that all of these functions should be deterministic
|
||||||
|
in the sense that they will show the same behavior if they are repeatedly called
|
||||||
|
with the same arguments (same width and height). If your widget is updated and
|
||||||
|
needs to change, suitable signals have to be emitted. This will be explained
|
||||||
|
later.
|
||||||
|
|
||||||
|
The first callback is `:fit`. This function is called to select the size of your
|
||||||
|
widget. The arguments to this function is the available space and it should
|
||||||
|
return its desired size. Note that this function only provides a hint which is
|
||||||
|
not necessarily followed. The widget must also be able to draw itself at
|
||||||
|
different sizes than the one requested.
|
||||||
|
|
||||||
|
function widget:fit(context, width, height)
|
||||||
|
-- Find the maximum square available
|
||||||
|
local m = math.min(width, height)
|
||||||
|
return m, m
|
||||||
|
end
|
||||||
|
|
||||||
|
The next callback is `:draw`. As the name suggests, this function is called to
|
||||||
|
draw the widget. The arguments to this widget are the context that the widget is
|
||||||
|
drawn in, the cairo context on which it should be drawn and the widget's size.
|
||||||
|
The cairo context is set up in such a way that the widget as its top-left corner
|
||||||
|
at (0, 0) and its bottom-right corner at (width, height). In other words, no
|
||||||
|
special transformation needs to be done. Note that during this callback a
|
||||||
|
suitable clip will already be applied to the cairo context so that this callback
|
||||||
|
will not be able to draw outside of the area that was registered for the widget
|
||||||
|
by the layout that placed this widget. You should not call `cr:reset_clip()`, as
|
||||||
|
redraws will not be handled correctly in this case.
|
||||||
|
|
||||||
|
function widget:draw(context, cr, width, height)
|
||||||
|
cr:move_to(0, 0)
|
||||||
|
cr:line_to(width, height)
|
||||||
|
cr:move_to(0, height)
|
||||||
|
cr:line_to(width, 0)
|
||||||
|
cr:stroke()
|
||||||
|
end
|
||||||
|
|
||||||
|
There are two signals configured for a widget. When the result that `:fit` would
|
||||||
|
return changes, the `widget::layout_changed` signal has to be emitted. If this
|
||||||
|
actually causes layout changes, the affected areas will be redrawn. The other
|
||||||
|
signal is `widget::redraw_needed`. This signal signals that `:draw` has to be
|
||||||
|
called to redraw the widget, but it is safe to assume that `:fit` does still
|
||||||
|
return the same values as before. If in doubt, you can emit both signals to be
|
||||||
|
safe.
|
||||||
|
|
||||||
|
If your widget only needs to draw something to the screen, the above is all that
|
||||||
|
is needed. The following callbacks can be used when implementing layouts which
|
||||||
|
place other widgets on the screen.
|
||||||
|
|
||||||
|
The `:layout` callback is used to figure out which other widgets should be drawn
|
||||||
|
relative to this widget. Note that it is allowed to place widgets outside of the
|
||||||
|
extents of your own widget, for example at a negative position or at twice the
|
||||||
|
size of this widget. Use this mechanism if your widget needs to draw outside of
|
||||||
|
its own extents. If the result of this callback changes,
|
||||||
|
`widget::layout_changed` has to be emitted. You can use `:fit_widget` to call
|
||||||
|
the `:fit` callback of other widgets. Never call `:fit` directly! For example,
|
||||||
|
if you want to place another widget `child` inside of your widget, you can do it
|
||||||
|
like this:
|
||||||
|
|
||||||
|
-- For readability
|
||||||
|
local base = wibox.widget.base
|
||||||
|
function widget:layout(width, height)
|
||||||
|
local result = {}
|
||||||
|
table.insert(result, base.place_widget_at(child, width/2, 0, width/2, height)
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
Finally, if you want to influence how children are drawn, there are four
|
||||||
|
callbacks available that all get similar arguments:
|
||||||
|
|
||||||
|
function widget:before_draw_children(context, cr, width, height)
|
||||||
|
function widget:after_draw_children(context, cr, width, height)
|
||||||
|
function widget:before_draw_child(context, index, child, cr, width, height)
|
||||||
|
function widget:after_draw_child(context, index, child, cr, width, height)
|
||||||
|
|
||||||
|
All of these are called with the same arguments as the `:draw()` method. Please
|
||||||
|
note that a larger clip will be active during these callbacks that also contains
|
||||||
|
the area of all children. These callbacks can be used to influence the way in
|
||||||
|
which children are drawn, but they should not cause the drawing to cover a
|
||||||
|
different area. As an example, these functions can be used to draw children
|
||||||
|
translucently:
|
||||||
|
|
||||||
|
function widget:before_draw_children(context, cr, width, height)
|
||||||
|
cr:push_group()
|
||||||
|
end
|
||||||
|
function widget:after_draw_children(context, cr, width, height)
|
||||||
|
cr:pop_group_to_source()
|
||||||
|
cr:paint_with_alpha(0.5)
|
||||||
|
end
|
||||||
|
|
||||||
|
In pseudo-code, the call sequence for the drawing callbacks during a redraw
|
||||||
|
looks like this:
|
||||||
|
|
||||||
|
widget:draw(context, cr, width, height)
|
||||||
|
widget:before_draw_children(context, cr, width, height)
|
||||||
|
for child do
|
||||||
|
widget:before_draw_child(context, cr, child_index, child, width, height)
|
||||||
|
cr:save()
|
||||||
|
-- Draw child and all of its children recursively, taking into account the
|
||||||
|
-- position and size given to base.place_widget_at() in :layout().
|
||||||
|
cr:restore()
|
||||||
|
widget:after_draw_child(context, cr, child_index, child, width, height)
|
||||||
|
end
|
||||||
|
widget:after_draw_children(context, cr, width, height)
|
|
@ -20,6 +20,7 @@ topics={
|
||||||
'01-readme.md',
|
'01-readme.md',
|
||||||
'02-contributing.md',
|
'02-contributing.md',
|
||||||
'03-declarative-layout.md',
|
'03-declarative-layout.md',
|
||||||
|
'04-new-widgets.md',
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Setup @client to be an alias for "@tparam client.object"
|
-- Setup @client to be an alias for "@tparam client.object"
|
||||||
|
|
|
@ -437,126 +437,14 @@ function base.widget:setup(args)
|
||||||
rawset(self, "get_children_by_id", get_children_by_id)
|
rawset(self, "get_children_by_id", get_children_by_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[--
|
--- Create an empty widget skeleton
|
||||||
Create a new widget. All widgets have to be generated via this function so that
|
-- See [Creating new widgets](../documentation/04-new-widget.md.html)
|
||||||
the needed signals are added and mouse input handling is set up.
|
-- @param proxy If this is set, the returned widget will be a proxy for this
|
||||||
|
-- widget. It will be equivalent to this widget. This means it
|
||||||
The returned widget will have a :buttons member function that can be used to
|
-- looks the same on the screen.
|
||||||
register a set of mouse button events with the widget.
|
-- @tparam[opt] string widget_name Name of the widget. If not set, it will be
|
||||||
|
-- set automatically via `gears.object.modulename`.
|
||||||
To implement your own widget, you can implement some member functions on a
|
-- @see fit_widget
|
||||||
freshly-created widget. Note that all of these functions should be deterministic
|
|
||||||
in the sense that they will show the same behavior if they are repeatedly called
|
|
||||||
with the same arguments (same width and height). If your widget is updated and
|
|
||||||
needs to change, suitable signals have to be emitted. This will be explained
|
|
||||||
later.
|
|
||||||
|
|
||||||
The first callback is :fit. This function is called to select the size of your
|
|
||||||
widget. The arguments to this function is the available space and it should
|
|
||||||
return its desired size. Note that this function only provides a hint which is
|
|
||||||
not necessarily followed. The widget must also be able to draw itself at
|
|
||||||
different sizes than the one requested.
|
|
||||||
|
|
||||||
function widget:fit(context, width, height)
|
|
||||||
-- Find the maximum square available
|
|
||||||
local m = math.min(width, height)
|
|
||||||
return m, m
|
|
||||||
end
|
|
||||||
|
|
||||||
The next callback is :draw. As the name suggests, this function is called to
|
|
||||||
draw the widget. The arguments to this widget are the context that the widget is
|
|
||||||
drawn in, the cairo context on which it should be drawn and the widget's size.
|
|
||||||
The cairo context is set up in such a way that the widget as its top-left corner
|
|
||||||
at (0, 0) and its bottom-right corner at (width, height). In other words, no
|
|
||||||
special transformation needs to be done. Note that during this callback a
|
|
||||||
suitable clip will already be applied to the cairo context so that this callback
|
|
||||||
will not be able to draw outside of the area that was registered for the widget
|
|
||||||
by the layout that placed this widget. You should not call `cr:reset_clip()`, as
|
|
||||||
redraws will not be handled correctly in this case.
|
|
||||||
|
|
||||||
function widget:draw(context, cr, width, height)
|
|
||||||
cr:move_to(0, 0)
|
|
||||||
cr:line_to(width, height)
|
|
||||||
cr:move_to(0, height)
|
|
||||||
cr:line_to(width, 0)
|
|
||||||
cr:stroke()
|
|
||||||
end
|
|
||||||
|
|
||||||
There are two signals configured for a widget. When the result that :fit would
|
|
||||||
return changes, the `widget::layout_changed` signal has to be emitted. If this
|
|
||||||
actually causes layout changes, the affected areas will be redrawn. The other
|
|
||||||
signal is `widget::redraw_needed`. This signal signals that :draw has to be
|
|
||||||
called to redraw the widget, but it is safe to assume that :fit does still
|
|
||||||
return the same values as before. If in doubt, you can emit both signals to be
|
|
||||||
safe.
|
|
||||||
|
|
||||||
If your widget only needs to draw something to the screen, the above is all that
|
|
||||||
is needed. The following callbacks can be used when implementing layouts which
|
|
||||||
place other widgets on the screen.
|
|
||||||
|
|
||||||
The :layout callback is used to figure out which other widgets should be drawn
|
|
||||||
relative to this widget. Note that it is allowed to place widgets outside of the
|
|
||||||
extents of your own widget, for example at a negative position or at twice the
|
|
||||||
size of this widget. Use this mechanism if your widget needs to draw outside of
|
|
||||||
its own extents. If the result of this callback changes,
|
|
||||||
`widget::layout_changed` has to be emitted. You can use @{fit_widget} to call
|
|
||||||
the `:fit` callback of other widgets. Never call `:fit` directly! For example,
|
|
||||||
if you want to place another widget `child` inside of your widget, you can do it
|
|
||||||
like this:
|
|
||||||
|
|
||||||
-- For readability
|
|
||||||
local base = wibox.widget.base
|
|
||||||
function widget:layout(width, height)
|
|
||||||
local result = {}
|
|
||||||
table.insert(result, base.place_widget_at(child, width/2, 0, width/2, height)
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
|
|
||||||
Finally, if you want to influence how children are drawn, there are four
|
|
||||||
callbacks available that all get similar arguments:
|
|
||||||
|
|
||||||
function widget:before_draw_children(context, cr, width, height)
|
|
||||||
function widget:after_draw_children(context, cr, width, height)
|
|
||||||
function widget:before_draw_child(context, index, child, cr, width, height)
|
|
||||||
function widget:after_draw_child(context, index, child, cr, width, height)
|
|
||||||
|
|
||||||
All of these are called with the same arguments as the :draw() method. Please
|
|
||||||
note that a larger clip will be active during these callbacks that also contains
|
|
||||||
the area of all children. These callbacks can be used to influence the way in
|
|
||||||
which children are drawn, but they should not cause the drawing to cover a
|
|
||||||
different area. As an example, these functions can be used to draw children
|
|
||||||
translucently:
|
|
||||||
|
|
||||||
function widget:before_draw_children(context, cr, width, height)
|
|
||||||
cr:push_group()
|
|
||||||
end
|
|
||||||
function widget:after_draw_children(context, cr, width, height)
|
|
||||||
cr:pop_group_to_source()
|
|
||||||
cr:paint_with_alpha(0.5)
|
|
||||||
end
|
|
||||||
|
|
||||||
In pseudo-code, the call sequence for the drawing callbacks during a redraw
|
|
||||||
looks like this:
|
|
||||||
|
|
||||||
widget:draw(context, cr, width, height)
|
|
||||||
widget:before_draw_children(context, cr, width, height)
|
|
||||||
for child do
|
|
||||||
widget:before_draw_child(context, cr, child_index, child, width, height)
|
|
||||||
cr:save()
|
|
||||||
-- Draw child and all of its children recursively, taking into account the
|
|
||||||
-- position and size given to base.place_widget_at() in :layout().
|
|
||||||
cr:restore()
|
|
||||||
widget:after_draw_child(context, cr, child_index, child, width, height)
|
|
||||||
end
|
|
||||||
widget:after_draw_children(context, cr, width, height)
|
|
||||||
|
|
||||||
@param proxy If this is set, the returned widget will be a proxy for this
|
|
||||||
widget. It will be equivalent to this widget. This means it
|
|
||||||
looks the same on the screen.
|
|
||||||
@tparam[opt] string widget_name Name of the widget. If not set, it will be
|
|
||||||
set automatically via `gears.object.modulename`.
|
|
||||||
@see fit_widget
|
|
||||||
--]]--
|
|
||||||
function base.make_widget(proxy, widget_name)
|
function base.make_widget(proxy, widget_name)
|
||||||
local ret = object()
|
local ret = object()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue