Merge pull request #923 from Elv13/widget_api_refactor
Widget api refactor
This commit is contained in:
commit
fc659b79ce
|
@ -84,14 +84,14 @@ install:
|
|||
- travis_retry sudo luarocks install lua-discount
|
||||
|
||||
# Instal luacov-coveralls for code coverage testing.
|
||||
- if [ "$DO_COVERAGE" = "true" ]; then sudo luarocks install luacov-coveralls; fi
|
||||
- if [ "$DO_COVERAGE" = "true" ]; then sudo luarocks install luacov-coveralls; else export DO_COVERAGE=0; fi
|
||||
|
||||
# Determine custom version.
|
||||
- export AWESOME_VERSION="${TRAVIS_BRANCH}-g$(git rev-parse --short HEAD)"
|
||||
- 'if [ "$TRAVIS_PULL_REQUEST" != false ]; then AWESOME_VERSION="${AWESOME_VERSION}-PR${TRAVIS_PULL_REQUEST}"; fi'
|
||||
|
||||
script:
|
||||
- export CMAKE_ARGS="-DLUA_LIBRARY=${LUALIBRARY} -DLUA_INCLUDE_DIR=${LUAINCLUDE} -D OVERRIDE_VERSION=$AWESOME_VERSION"
|
||||
- export CMAKE_ARGS="-DLUA_LIBRARY=${LUALIBRARY} -DLUA_INCLUDE_DIR=${LUAINCLUDE} -D OVERRIDE_VERSION=$AWESOME_VERSION -D DO_COVERAGE=${DO_COVERAGE}"
|
||||
- |
|
||||
if [ -n "$BUILD_IN_DIR" ]; then
|
||||
SOURCE_DIRECTORY="$PWD"
|
||||
|
|
|
@ -300,13 +300,13 @@ if(GENERATE_DOC)
|
|||
# Load the common documentation
|
||||
include(docs/load_ldoc.cmake)
|
||||
|
||||
# Generate some images and examples
|
||||
include(docs/generate_examples.cmake)
|
||||
|
||||
# Use `include`, rather than `add_subdirectory`, to keep the variables
|
||||
# The file is a valid CMakeLists.txt and can be executed directly if only
|
||||
# the image artefacts are needed.
|
||||
include(tests/examples/CMakeLists.txt)
|
||||
|
||||
# Generate the widget lists
|
||||
include(docs/widget_lists.cmake)
|
||||
endif()
|
||||
|
||||
# {{{ Configure files
|
||||
|
@ -345,8 +345,18 @@ set(AWESOME_ADDITIONAL_FILES
|
|||
foreach(file ${AWESOME_ADDITIONAL_FILES})
|
||||
configure_file(${SOURCE_DIR}/${file}
|
||||
${BUILD_DIR}/${file}
|
||||
COPYONLY)
|
||||
@ONLY)
|
||||
endforeach()
|
||||
#}}}
|
||||
|
||||
# The examples coverage need to be done again after the configure_file has
|
||||
# inserted the additional code. Otherwise, the result will be off, rendering
|
||||
# the coverage useless as a tool to track untested code.
|
||||
if(GENERATE_DOC AND DO_COVERAGE)
|
||||
message(STATUS "Running tests again with coverage")
|
||||
set(USE_LCOV 1)
|
||||
|
||||
include(tests/examples/CMakeLists.txt)
|
||||
endif()
|
||||
|
||||
# vim: filetype=cmake:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80:foldmethod=marker
|
||||
|
|
|
@ -115,7 +115,7 @@ mykeyboardlayout = awful.widget.keyboardlayout()
|
|||
|
||||
-- {{{ Wibox
|
||||
-- Create a textclock widget
|
||||
mytextclock = awful.widget.textclock()
|
||||
mytextclock = wibox.widget.textclock()
|
||||
|
||||
-- Create a wibox for each screen and add it
|
||||
mywibox = {}
|
||||
|
|
|
@ -3,7 +3,35 @@
|
|||
This system provide an alternative to the system used in Awesome 3.5 and is
|
||||
inspired by the one once used by Awesome 3.2-3.4 and Qt QML system.
|
||||
|
||||
## A simple layout
|
||||
## The default widgets
|
||||
|
||||
### Widgets
|
||||
|
||||
Awesome provide 2 collections of widgets:
|
||||
|
||||
* `wibox.widget`: Generic widgets, containers and layouts
|
||||
* `awful.widget`: The Awesome specific widgets
|
||||
|
||||
|
||||
@DOC_widget_WIDGET_LIST@
|
||||
|
||||
### Containers
|
||||
|
||||
Containers are widget wrapping another widget. It can be used to add decorations
|
||||
or to modify the content of the child widget.
|
||||
|
||||
@DOC_container_WIDGET_LIST@
|
||||
|
||||
### Layouts
|
||||
|
||||
Layouts are collection of children widgets. They place them according to rules
|
||||
and usually provide some options.
|
||||
|
||||
@DOC_layout_WIDGET_LIST@
|
||||
|
||||
## Placing widgets
|
||||
|
||||
### A simple layout
|
||||
|
||||
* Display `my_first_widget` only on screen one
|
||||
* Add a background color to `my_third_widget`
|
||||
|
@ -17,7 +45,7 @@ Code:
|
|||
{ -- Add a background color/pattern for my_third_widget
|
||||
my_third_widget,
|
||||
bg = beautiful.bg_focus,
|
||||
widget = wibox.widget.background,
|
||||
widget = wibox.container.background,
|
||||
},
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
}
|
||||
|
@ -29,12 +57,12 @@ logic expression can be used as long as it return a valid widget, or a
|
|||
declarative layout, or `nil`.
|
||||
|
||||
|
||||
## Define widgets inline and place them
|
||||
### Define widgets inline and place them
|
||||
|
||||
* Create a `wibox.widget.textbox` with various properties
|
||||
* Force the textbox size using `wibox.layout.constraint`
|
||||
* Add a margin around another textbox
|
||||
* Add a `wibox.widget.background` (for visualization)
|
||||
* Add a `wibox.container.background` (for visualization)
|
||||
|
||||
Code:
|
||||
|
||||
|
@ -48,7 +76,7 @@ Code:
|
|||
widget = wibox.widget.textbox
|
||||
},
|
||||
bg = "#ff0000",
|
||||
widget = wibox.widget.background,
|
||||
widget = wibox.container.background,
|
||||
},
|
||||
width = 300,
|
||||
strategy = "min",
|
||||
|
@ -62,13 +90,13 @@ Code:
|
|||
widget = wibox.widget.textbox
|
||||
},
|
||||
bg = "#0000ff",
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
left = 10,
|
||||
right = 10,
|
||||
top = 1,
|
||||
bottom = 2,
|
||||
layout = wibox.layout.margin
|
||||
layout = wibox.container.margin
|
||||
},
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
}
|
||||
|
@ -78,7 +106,7 @@ Result:
|
|||
![Example2 screenshot](../images/widgetlayout1.png)
|
||||
|
||||
|
||||
## Use an `wibox.layout.align` layout
|
||||
### Use an `wibox.layout.align` layout
|
||||
The `wibox.layout.align` is a little different. While most layouts will
|
||||
ignore any `nil` lines, the `align` layout rely on them so `left`, `middle`
|
||||
and `right` can be defined
|
||||
|
@ -94,7 +122,7 @@ Code:
|
|||
|
||||
|
||||
|
||||
## Define new widgets
|
||||
### Define new widgets
|
||||
|
||||
New trivial widgets can be created directly in the layout declaration. Here
|
||||
is a simple circle widget:
|
||||
|
@ -126,7 +154,7 @@ For more information about how to draw widgets, refer to the `Cairo` api:
|
|||
* [Pango text](https://developer.gnome.org/pango/stable/)
|
||||
|
||||
|
||||
## Externally defined widgets and layouts
|
||||
### Externally defined widgets and layouts
|
||||
|
||||
This is useful when the widget is provided by an external module or when it
|
||||
requires complex manipulations which would make the declaration unreadable.
|
||||
|
@ -146,7 +174,7 @@ Code:
|
|||
|
||||
|
||||
|
||||
## Accessing widgets
|
||||
### Accessing widgets
|
||||
|
||||
For each widget or container, it is possible to add an `identifier` attribute
|
||||
so the widget can be accessed later.
|
||||
|
@ -188,7 +216,7 @@ Code:
|
|||
|
||||
|
||||
|
||||
## Extending the system
|
||||
### Extending the system
|
||||
|
||||
This system is very flexible. Each section attribute (the entries with string
|
||||
keys) is directly linked to the layout or widget API. When setting the
|
||||
|
@ -221,7 +249,7 @@ used directly in the layout declaration. This example will update the textbox
|
|||
every 3 seconds to show the CPU usage.
|
||||
|
||||
|
||||
## Handling sections
|
||||
### Handling sections
|
||||
|
||||
The system allows sections to be defined externally, then composed into
|
||||
the final layout declaration. Here is an example re-using one of the above
|
||||
|
|
|
@ -29,11 +29,9 @@
|
|||
-- @name swap_widgets
|
||||
-- @class function
|
||||
|
||||
--- Get all children of this layout.
|
||||
--- Get all direct children of this layout.
|
||||
-- @param layout The layout you are modifying.
|
||||
-- @return a list of all widgets
|
||||
-- @name get_children
|
||||
-- @class function
|
||||
-- @property children
|
||||
|
||||
--- Reset a ratio layout. This removes all widgets from the layout.
|
||||
-- @param layout The layout you are modifying.
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
--- Disonnect to a signal.
|
||||
-- @tparam string name The name of the signal
|
||||
-- @tparam function func The callback that should be disconnected
|
||||
-- @see add_signal
|
||||
-- @function disconnect_signal
|
||||
|
||||
--- Emit a signal.
|
||||
--
|
||||
-- @tparam string name The name of the signal
|
||||
-- @param ... Extra arguments for the callback functions. Each connected
|
||||
-- function receives the object as first argument and then any extra arguments
|
||||
-- that are given to emit_signal()
|
||||
-- @function emit_signal
|
||||
|
||||
--- Add a signal to an object. All signals must be added before they can be used.
|
||||
--
|
||||
-- @tparam string name The name of the new signal.
|
||||
-- @function add_signal
|
||||
|
||||
--- Connect to a signal.
|
||||
-- @tparam string name The name of the signal
|
||||
-- @tparam function func The callback to call when the signal is emitted
|
||||
-- @see add_signal
|
||||
-- @function connect_signal
|
||||
|
||||
--- Connect to a signal weakly. This allows the callback function to be garbage
|
||||
-- collected and automatically disconnects the signal when that happens.
|
||||
--
|
||||
-- **Warning:**
|
||||
-- Only use this function if you really, really, really know what you
|
||||
-- are doing.
|
||||
-- @tparam string name The name of the signal
|
||||
-- @tparam function func The callback to call when the signal is emitted
|
||||
-- @function weak_connect_signal
|
|
@ -0,0 +1,110 @@
|
|||
|
||||
--- Get a widex index.
|
||||
-- @param widget The widget to look for
|
||||
-- @param[opt] recursive Also check sub-widgets
|
||||
-- @param[opt] ... Aditional widgets to add at the end of the "path"
|
||||
-- @return The index
|
||||
-- @return The parent layout
|
||||
-- @return The path between "self" and "widget"
|
||||
-- @function index
|
||||
|
||||
--- Get all direct and indirect children widgets.
|
||||
-- This will scan all containers recursively to find widgets
|
||||
-- Warning: This method it prone to stack overflow id the widget, or any of its
|
||||
-- children, contain (directly or indirectly) itself.
|
||||
-- @treturn table The children
|
||||
-- @function get_all_children
|
||||
|
||||
--- Set a declarative widget hierarchy description.
|
||||
-- See [The declarative layout system](../documentation/03-declarative-layout.md.html)
|
||||
-- @param args An array containing the widgets disposition
|
||||
-- @function setup
|
||||
|
||||
--- Force a widget height.
|
||||
-- @property forced_height
|
||||
-- @tparam number|nil height The height (`nil` for automatic)
|
||||
|
||||
--- Force a widget width.
|
||||
-- @property forced_width
|
||||
-- @tparam number|nil width The width (`nil` for automatic)
|
||||
|
||||
--- The widget opacity (transparency).
|
||||
-- @property opacity
|
||||
-- @tparam[opt=1] number opacity The opacity (between 0 and 1)
|
||||
|
||||
--- The widget visibility.
|
||||
-- @property visible
|
||||
-- @param boolean
|
||||
|
||||
--- Set/get a widget's buttons.
|
||||
-- @param _buttons The table of buttons that should bind to the widget.
|
||||
-- @function buttons
|
||||
|
||||
|
||||
--- When the layout (size) change.
|
||||
-- This signal is emited when the previous results of `:layout()` and `:fit()`
|
||||
-- are no longer valid.
|
||||
-- @signal widget::layout_changed
|
||||
-- @see widget::redraw_needed
|
||||
|
||||
--- When the widget content changed.
|
||||
-- Unless this signal is emitted, `:layout()` and `:fit()` must return the same
|
||||
-- result when called with the same arguments. In case this isn't the case,
|
||||
-- use `widget::layout_changed`.
|
||||
-- @signal widget::redraw_needed
|
||||
|
||||
--- When a mouse button is pressed over the widget.
|
||||
-- The position of the mouse press relative to the widget while geometry
|
||||
-- contains the geometry of the widget relative to the wibox.
|
||||
-- @signal button::press
|
||||
-- @tparam table widget The widget
|
||||
-- @tparam number lx The relative horizontal position.
|
||||
-- @tparam number ly The relative vertical position.
|
||||
-- @tparam number button The button number.
|
||||
-- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift)
|
||||
-- @tparam table geometry
|
||||
-- @tparam number geometry.x The vertical position
|
||||
-- @tparam number geometry.y The horizontal position
|
||||
-- @tparam number geometry.width The widget
|
||||
-- @tparam number geometry.height The height
|
||||
-- @tparam drawable geometry.drawable The `drawable`
|
||||
-- @see mouse
|
||||
|
||||
--- When a mouse button is released over the widget.
|
||||
-- The position of the mouse press relative to the widget while geometry
|
||||
-- contains the geometry of the widget relative to the wibox.
|
||||
-- @signal button::release
|
||||
-- @tparam table widget The widget
|
||||
-- @tparam number lx The relative horizontal position.
|
||||
-- @tparam number ly The relative vertical position.
|
||||
-- @tparam number button The button number.
|
||||
-- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift)
|
||||
-- @tparam table geometry
|
||||
-- @tparam number geometry.x The vertical position
|
||||
-- @tparam number geometry.y The horizontal position
|
||||
-- @tparam number geometry.width The widget
|
||||
-- @tparam number geometry.height The height
|
||||
-- @tparam drawable geometry.drawable The `drawable`
|
||||
-- @see mouse
|
||||
|
||||
--- When the mouse enter a widget.
|
||||
-- @signal mouse::enter
|
||||
-- @tparam table widget The widget
|
||||
-- @tparam table geometry
|
||||
-- @tparam number geometry.x The vertical position
|
||||
-- @tparam number geometry.y The horizontal position
|
||||
-- @tparam number geometry.width The widget
|
||||
-- @tparam number geometry.height The height
|
||||
-- @tparam drawable geometry.drawable The `drawable`
|
||||
-- @see mouse
|
||||
|
||||
--- When the mouse leave a widget.
|
||||
-- @signal mouse::leave
|
||||
-- @tparam table widget The widget
|
||||
-- @tparam table geometry
|
||||
-- @tparam number geometry.x The vertical position
|
||||
-- @tparam number geometry.y The horizontal position
|
||||
-- @tparam number geometry.width The widget
|
||||
-- @tparam number geometry.height The height
|
||||
-- @tparam drawable geometry.drawable The `drawable`
|
||||
-- @see mouse
|
|
@ -82,6 +82,7 @@ file = {
|
|||
'../lib/gears/init.lua',
|
||||
'../lib/wibox/layout/init.lua',
|
||||
'../lib/wibox/widget/init.lua',
|
||||
'../lib/wibox/container/init.lua',
|
||||
|
||||
-- Ignore some parts of the widget library
|
||||
'../lib/awful/widget/init.lua',
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
|
||||
# Get and update the LUA_PATH so the scripts can be executed without Awesome
|
||||
execute_process(COMMAND lua -e print\(package.path\) OUTPUT_VARIABLE LUA_PATH_)
|
||||
set(ENV{LUA_PATH} "${SOURCE_DIR}/lib/?;${SOURCE_DIR}/lib/?.lua;${LUA_PATH_}")
|
||||
|
||||
file(MAKE_DIRECTORY "${BUILD_DIR}/doc/images")
|
||||
|
||||
set(ENV{BUILD_DIRECTORY} "${BUILD_DIR}/")
|
||||
set(ENV{AWESOME_LIB_DIR} "${SOURCE_DIR}/lib/")
|
||||
|
||||
#
|
||||
# Shape API
|
||||
#
|
||||
foreach (SHAPE_NAME "circle" "arrow" "rounded_rect" "hexagon" "infobubble"
|
||||
"powerline" "isosceles_triangle" "cross" "octogon" "parallelogram"
|
||||
"losange" "partially_rounded_rect" "radial_progress" "rounded_bar"
|
||||
"rectangle" "rectangular_tag")
|
||||
set(SHAPE_FILE "${SOURCE_DIR}/tests/shape/${SHAPE_NAME}.lua")
|
||||
set(SHAPE_SVG "${BUILD_DIR}/doc/images/shape_${SHAPE_NAME}.svg")
|
||||
|
||||
# Generate some SVG for the documentation and load the examples for the doc
|
||||
execute_process(
|
||||
COMMAND lua ${SOURCE_DIR}/tests/shape/test-shape.lua ${SHAPE_FILE} ${SHAPE_SVG} ${SOURCE_DIR}/.luacov
|
||||
ERROR_VARIABLE SHAPE_ERROR
|
||||
)
|
||||
|
||||
if (NOT SHAPE_ERROR STREQUAL "")
|
||||
message(${SHAPE_ERROR})
|
||||
message(FATAL_ERROR ${SHAPE_NAME} " SVG generation failed, bye")
|
||||
endif()
|
||||
|
||||
# Set the SVG paths for the doc
|
||||
set(SHAPE_${SHAPE_NAME}_SVG "../images/shape_${SHAPE_NAME}.svg")
|
||||
|
||||
# Use the .lua as code example
|
||||
file(READ ${SHAPE_FILE} SHAPE_EXAMPLE)
|
||||
STRING(REGEX REPLACE "\n" ";" SHAPE_EXAMPLE "${SHAPE_EXAMPLE}")
|
||||
SET(SHAPE_COMMENTED
|
||||
"![Shape example](../images/shape_${SHAPE_NAME}.svg)\n--\n-- @usage"
|
||||
)
|
||||
foreach (EXAMPLE_FILE ${SHAPE_EXAMPLE})
|
||||
if(NOT EXAMPLE_FILE MATCHES "^.+--DOC_HIDE$")
|
||||
SET(SHAPE_COMMENTED ${SHAPE_COMMENTED}\n--${EXAMPLE_FILE})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(SHAPE_${SHAPE_NAME}_EXAMPLE ${SHAPE_COMMENTED})
|
||||
|
||||
endforeach()
|
||||
|
||||
# vim: filetype=cmake:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80:foldmethod=marker
|
|
@ -0,0 +1,48 @@
|
|||
# This file gather the different default example screenshots and create an HTML
|
||||
# table. Those tables are re-used in the official documentation.
|
||||
|
||||
# Ldoc wont parse the HTML content and discount tables are disabled, so here is
|
||||
# some raw HTML
|
||||
function(add_to_table name namespace group current_table new_table)
|
||||
|
||||
set(${new_table} "${current_table}\n\
|
||||
<tr>\n\
|
||||
<td>
|
||||
<a href='../classes/${namespace}${name}.html'>${namespace}${name}</a>
|
||||
</td>\n\
|
||||
<td><img src='../images/AUTOGEN_wibox_${group}_defaults_${name}.svg' /></td>\n\
|
||||
</tr>\n\
|
||||
" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Use the generated "defaults" images to build a list
|
||||
function(generate_widget_list name)
|
||||
file(GLOB ex_files RELATIVE "${SOURCE_DIR}/tests/examples/wibox/${name}/defaults"
|
||||
"${SOURCE_DIR}/tests/examples/wibox/${name}/defaults/*")
|
||||
|
||||
# Add the table header
|
||||
set(MY_LIST "<table class='widget_list' border=1>\n\
|
||||
<tr style='font-weight: bold;'>\n\
|
||||
<th align='center'>Name</th>\n\
|
||||
<th align='center'>Example</th>\n\
|
||||
</tr>"
|
||||
)
|
||||
|
||||
# Loop all examples (and assume an image exist for them)
|
||||
foreach(ex_file_name ${ex_files})
|
||||
string(REGEX REPLACE "\\.lua" "" ex_file_name ${ex_file_name})
|
||||
|
||||
if(NOT ${ex_file_name} STREQUAL "template")
|
||||
add_to_table(${ex_file_name} "wibox.${name}." "${name}" "${MY_LIST}" MY_LIST)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Add the table footer
|
||||
set(MY_LIST "${MY_LIST}</table>\n\n")
|
||||
|
||||
set(DOC_${name}_WIDGET_LIST ${MY_LIST} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
generate_widget_list( "container" )
|
||||
generate_widget_list( "layout" )
|
||||
generate_widget_list( "widget" )
|
|
@ -195,7 +195,7 @@ local function group_label(group, color)
|
|||
)
|
||||
)
|
||||
)
|
||||
local margin = wibox.layout.margin()
|
||||
local margin = wibox.container.margin()
|
||||
margin:set_widget(textbox)
|
||||
margin:set_top(widget.group_margin)
|
||||
return margin
|
||||
|
@ -315,7 +315,7 @@ local function create_wibox(s, available_groups)
|
|||
else
|
||||
available_width_px = available_width_px - item.max_width
|
||||
end
|
||||
local column_margin = wibox.layout.margin()
|
||||
local column_margin = wibox.container.margin()
|
||||
column_margin:set_widget(item.layout)
|
||||
column_margin:set_left(widget.group_margin)
|
||||
columns:add(column_margin)
|
||||
|
|
|
@ -249,7 +249,7 @@ function menu:exec(num, opts)
|
|||
self.active_child:hide()
|
||||
end
|
||||
self.active_child = self.child[num]
|
||||
if not self.active_child.visible then
|
||||
if not self.active_child:get_visible() then
|
||||
self.active_child:show()
|
||||
end
|
||||
elseif type(cmd) == "string" then
|
||||
|
@ -384,7 +384,7 @@ function menu:add(args, index)
|
|||
item.width = item.width or theme.width
|
||||
item.height = item.height or theme.height
|
||||
wibox.widget.base.check_widget(item.widget)
|
||||
item._background = wibox.widget.background()
|
||||
item._background = wibox.container.background()
|
||||
item._background:set_widget(item.widget)
|
||||
item._background:set_fg(item.theme.fg_normal)
|
||||
item._background:set_bg(item.theme.bg_normal)
|
||||
|
@ -431,7 +431,7 @@ function menu:delete(num)
|
|||
local item = self.items[num]
|
||||
if not item then return end
|
||||
item.widget:disconnect_signal("mouse::enter", item._mouse)
|
||||
item.widget.visible = false
|
||||
item.widget:set_visible(false)
|
||||
table.remove(self.items, num)
|
||||
if self.sel == num then
|
||||
self:item_leave(self.sel)
|
||||
|
@ -516,7 +516,7 @@ function menu.entry(parent, args) -- luacheck: no unused args
|
|||
end, 1))
|
||||
-- Set icon if needed
|
||||
local icon, iconbox
|
||||
local margin = wibox.layout.margin()
|
||||
local margin = wibox.container.margin()
|
||||
margin:set_widget(label)
|
||||
if args.icon then
|
||||
icon = surface.load(args.icon)
|
||||
|
|
|
@ -204,8 +204,8 @@ function titlebar.widget.button(c, name, selector, action)
|
|||
local ret = imagebox()
|
||||
|
||||
if titlebar.enable_tooltip then
|
||||
ret.tooltip = atooltip({ objects = {ret}, delay_show = 1 })
|
||||
ret.tooltip:set_text(name)
|
||||
ret._private.tooltip = atooltip({ objects = {ret}, delay_show = 1 })
|
||||
ret._private.tooltip:set_text(name)
|
||||
end
|
||||
|
||||
local function update()
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
-- How to create a tooltip?
|
||||
-- ---
|
||||
--
|
||||
-- myclock = awful.widget.textclock({}, "%T", 1)
|
||||
-- myclock = wibox.widget.textclock({}, "%T", 1)
|
||||
-- myclock_t = awful.tooltip({
|
||||
-- objects = { myclock },
|
||||
-- timer_function = function()
|
||||
|
@ -48,7 +48,7 @@ local a_placement = require("awful.placement")
|
|||
local abutton = require("awful.button")
|
||||
local beautiful = require("beautiful")
|
||||
local textbox = require("wibox.widget.textbox")
|
||||
local background = require("wibox.widget.background")
|
||||
local background = require("wibox.container.background")
|
||||
local dpi = require("beautiful").xresources.apply_dpi
|
||||
local setmetatable = setmetatable
|
||||
local ipairs = ipairs
|
||||
|
@ -265,7 +265,7 @@ tooltip.new = function(args)
|
|||
-- Add margin.
|
||||
local m_lr = args.margin_leftright or dpi(5)
|
||||
local m_tb = args.margin_topbottom or dpi(3)
|
||||
self.marginbox = wibox.layout.margin(self.background, m_lr, m_lr, m_tb, m_tb)
|
||||
self.marginbox = wibox.container.margin(self.background, m_lr, m_lr, m_tb, m_tb)
|
||||
|
||||
-- Add tooltip to objects
|
||||
if args.objects then
|
||||
|
|
|
@ -60,6 +60,36 @@ function util.deprecate(see)
|
|||
gears_debug.print_warning(msg .. ".\n" .. tb)
|
||||
end
|
||||
|
||||
--- Create a class proxy with deprecation messages.
|
||||
-- This is useful when a class has moved somewhere else.
|
||||
-- @tparam table fallback The new class
|
||||
-- @tparam string old_name The old class name
|
||||
-- @tparam string new_name The new class name
|
||||
-- @treturn table A proxy class.
|
||||
function util.deprecate_class(fallback, old_name, new_name)
|
||||
local message = old_name.." has been renamed to "..new_name
|
||||
|
||||
local function call(_,...)
|
||||
util.deprecate(message)
|
||||
|
||||
return fallback(...)
|
||||
end
|
||||
|
||||
local function index(_, k)
|
||||
util.deprecate(message)
|
||||
|
||||
return fallback[k]
|
||||
end
|
||||
|
||||
local function newindex(_, k, v)
|
||||
util.deprecate(message)
|
||||
|
||||
fallback[k] = v
|
||||
end
|
||||
|
||||
return setmetatable({}, {__call = call, __index = index, __newindex = newindex})
|
||||
end
|
||||
|
||||
--- Get a valid color for Pango markup
|
||||
-- @param color The color.
|
||||
-- @tparam string fallback The color to return if the first is invalid. (default: black)
|
||||
|
@ -336,13 +366,22 @@ function util.table.join(...)
|
|||
return ret
|
||||
end
|
||||
|
||||
--- Override elements in the first table by the one in the second
|
||||
--- Override elements in the first table by the one in the second.
|
||||
--
|
||||
-- Note that this method doesn't copy entries found in `__index`.
|
||||
-- @tparam table t the table to be overriden
|
||||
-- @tparam table set the table used to override members of `t`
|
||||
-- @tparam[opt=false] boolean raw Use rawset (avoid the metatable)
|
||||
-- @treturn table t (for convenience)
|
||||
function util.table.crush(t, set)
|
||||
for k, v in pairs(set) do
|
||||
t[k] = v
|
||||
function util.table.crush(t, set, raw)
|
||||
if raw then
|
||||
for k, v in pairs(set) do
|
||||
rawset(t, k, v)
|
||||
end
|
||||
else
|
||||
for k, v in pairs(set) do
|
||||
t[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
return t
|
||||
|
|
|
@ -7,26 +7,7 @@
|
|||
-- @module awful.wibox
|
||||
---------------------------------------------------------------------------
|
||||
local util = require("awful.util")
|
||||
local wibar = require("awful.wibar")
|
||||
|
||||
local function call(_,...)
|
||||
util.deprecate("awful.wibox has been renamed to awful.wibar")
|
||||
|
||||
return wibar(...)
|
||||
end
|
||||
|
||||
local function index(_, k)
|
||||
util.deprecate("awful.wibox has been renamed to awful.wibar")
|
||||
|
||||
return wibar[k]
|
||||
end
|
||||
|
||||
local function newindex(_, k, v)
|
||||
util.deprecate("awful.wibox has been renamed to awful.wibar")
|
||||
|
||||
wibar[k] = v
|
||||
end
|
||||
|
||||
return setmetatable({}, {__call = call, __index = index, __newindex = newindex})
|
||||
return util.deprecate_class(require("awful.wibar"), "awful.wibox", "awful.wibar")
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -60,9 +60,9 @@ function common.list_update(w, buttons, label, data, objects)
|
|||
else
|
||||
ib = wibox.widget.imagebox()
|
||||
tb = wibox.widget.textbox()
|
||||
bgb = wibox.widget.background()
|
||||
tbm = wibox.layout.margin(tb, dpi(4), dpi(4))
|
||||
ibm = wibox.layout.margin(ib, dpi(4))
|
||||
bgb = wibox.container.background()
|
||||
tbm = wibox.container.margin(tb, dpi(4), dpi(4))
|
||||
ibm = wibox.container.margin(ib, dpi(4))
|
||||
l = wibox.layout.fixed.horizontal()
|
||||
|
||||
-- All of this is added in a fixed widget
|
||||
|
|
|
@ -1,279 +1,17 @@
|
|||
---------------------------------------------------------------------------
|
||||
--- A graph widget.
|
||||
--- This module has been moved to `wibox.widget.graph`
|
||||
--
|
||||
-- @author Julien Danjou <julien@danjou.info>
|
||||
-- @copyright 2009 Julien Danjou
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod awful.widget.graph
|
||||
---------------------------------------------------------------------------
|
||||
local util = require("awful.util")
|
||||
|
||||
local setmetatable = setmetatable
|
||||
local ipairs = ipairs
|
||||
local math = math
|
||||
local table = table
|
||||
local type = type
|
||||
local color = require("gears.color")
|
||||
local base = require("wibox.widget.base")
|
||||
|
||||
local graph = { mt = {} }
|
||||
|
||||
--- Set the graph border color.
|
||||
-- If the value is nil, no border will be drawn.
|
||||
--
|
||||
-- @function set_border_color
|
||||
-- @param graph The graph.
|
||||
-- @param color The border color to set.
|
||||
|
||||
--- Set the graph foreground color.
|
||||
--
|
||||
-- @function set_color
|
||||
-- @param graph The graph.
|
||||
-- @param color The graph color.
|
||||
-- @see gears.color.create_pattern
|
||||
|
||||
--- Set the graph background color.
|
||||
--
|
||||
-- @function set_background_color
|
||||
-- @param graph The graph.
|
||||
-- @param color The graph background color.
|
||||
|
||||
--- Set the maximum value the graph should handle.
|
||||
-- If "scale" is also set, the graph never scales up below this value, but it
|
||||
-- automatically scales down to make all data fit.
|
||||
--
|
||||
-- @function set_max_value
|
||||
-- @param graph The graph.
|
||||
-- @param value The value.
|
||||
|
||||
--- Set the graph to automatically scale its values. Default is false.
|
||||
--
|
||||
-- @function set_scale
|
||||
-- @param graph The graph.
|
||||
-- @param scale A boolean value
|
||||
|
||||
--- Set the graph to draw stacks. Default is false.
|
||||
--
|
||||
-- @function set_stack
|
||||
-- @param graph The graph.
|
||||
-- @param stack A boolean value.
|
||||
|
||||
--- Set the graph stacking colors. Order matters.
|
||||
--
|
||||
-- @function set_stack_colors
|
||||
-- @param graph The graph.
|
||||
-- @param stack_colors A table with stacking colors.
|
||||
|
||||
local properties = { "width", "height", "border_color", "stack",
|
||||
"stack_colors", "color", "background_color",
|
||||
"max_value", "scale" }
|
||||
|
||||
function graph.draw(_graph, _, cr, width, height)
|
||||
local max_value = _graph._data.max_value
|
||||
local values = _graph._data.values
|
||||
|
||||
cr:set_line_width(1)
|
||||
|
||||
-- Draw the background first
|
||||
cr:set_source(color(_graph._data.background_color or "#000000aa"))
|
||||
cr:paint()
|
||||
|
||||
-- Account for the border width
|
||||
cr:save()
|
||||
if _graph._data.border_color then
|
||||
cr:translate(1, 1)
|
||||
width, height = width - 2, height - 2
|
||||
end
|
||||
|
||||
-- Draw a stacked graph
|
||||
if _graph._data.stack then
|
||||
|
||||
if _graph._data.scale then
|
||||
for _, v in ipairs(values) do
|
||||
for _, sv in ipairs(v) do
|
||||
if sv > max_value then
|
||||
max_value = sv
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for i = 0, width do
|
||||
local rel_i = 0
|
||||
local rel_x = i + 0.5
|
||||
|
||||
if _graph._data.stack_colors then
|
||||
for idx, col in ipairs(_graph._data.stack_colors) do
|
||||
local stack_values = values[idx]
|
||||
if stack_values and i < #stack_values then
|
||||
local value = stack_values[#stack_values - i] + rel_i
|
||||
cr:move_to(rel_x, height * (1 - (rel_i / max_value)))
|
||||
cr:line_to(rel_x, height * (1 - (value / max_value)))
|
||||
cr:set_source(color(col or "#ff0000"))
|
||||
cr:stroke()
|
||||
rel_i = value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
if _graph._data.scale then
|
||||
for _, v in ipairs(values) do
|
||||
if v > max_value then
|
||||
max_value = v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Draw the background on no value
|
||||
if #values ~= 0 then
|
||||
-- Draw reverse
|
||||
for i = 0, #values - 1 do
|
||||
local value = values[#values - i]
|
||||
if value >= 0 then
|
||||
value = value / max_value
|
||||
cr:move_to(i + 0.5, height * (1 - value))
|
||||
cr:line_to(i + 0.5, height)
|
||||
end
|
||||
end
|
||||
cr:set_source(color(_graph._data.color or "#ff0000"))
|
||||
cr:stroke()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Undo the cr:translate() for the border
|
||||
cr:restore()
|
||||
|
||||
-- Draw the border last so that it overlaps already drawn values
|
||||
if _graph._data.border_color then
|
||||
-- We decremented these by two above
|
||||
width, height = width + 2, height + 2
|
||||
|
||||
-- Draw the border
|
||||
cr:rectangle(0.5, 0.5, width - 1, height - 1)
|
||||
cr:set_source(color(_graph._data.border_color or "#ffffff"))
|
||||
cr:stroke()
|
||||
end
|
||||
end
|
||||
|
||||
function graph.fit(_graph)
|
||||
return _graph._data.width, _graph._data.height
|
||||
end
|
||||
|
||||
--- Add a value to the graph
|
||||
--
|
||||
-- @param value The value to be added to the graph
|
||||
-- @param group The stack color group index.
|
||||
function graph:add_value(value, group)
|
||||
value = value or 0
|
||||
local values = self._data.values
|
||||
local max_value = self._data.max_value
|
||||
value = math.max(0, value)
|
||||
if not self._data.scale then
|
||||
value = math.min(max_value, value)
|
||||
end
|
||||
|
||||
if self._data.stack and group then
|
||||
if not self._data.values[group]
|
||||
or type(self._data.values[group]) ~= "table"
|
||||
then
|
||||
self._data.values[group] = {}
|
||||
end
|
||||
values = self._data.values[group]
|
||||
end
|
||||
table.insert(values, value)
|
||||
|
||||
local border_width = 0
|
||||
if self._data.border_color then border_width = 2 end
|
||||
|
||||
-- Ensure we never have more data than we can draw
|
||||
while #values > self._data.width - border_width do
|
||||
table.remove(values, 1)
|
||||
end
|
||||
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
return self
|
||||
end
|
||||
|
||||
--- Clear the graph.
|
||||
function graph:clear()
|
||||
self._data.values = {}
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set the graph height.
|
||||
-- @param height The height to set.
|
||||
function graph:set_height(height)
|
||||
if height >= 5 then
|
||||
self._data.height = height
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set the graph width.
|
||||
-- @param width The width to set.
|
||||
function graph:set_width(width)
|
||||
if width >= 5 then
|
||||
self._data.width = width
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
-- Build properties function
|
||||
for _, prop in ipairs(properties) do
|
||||
if not graph["set_" .. prop] then
|
||||
graph["set_" .. prop] = function(_graph, value)
|
||||
if _graph._data[prop] ~= value then
|
||||
_graph._data[prop] = value
|
||||
_graph:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
return _graph
|
||||
end
|
||||
end
|
||||
if not graph["get_" .. prop] then
|
||||
graph["get_" .. prop] = function(_graph)
|
||||
return _graph._data[prop]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Create a graph widget.
|
||||
-- @param args Standard widget() arguments. You should add width and height
|
||||
-- key to set graph geometry.
|
||||
-- @return A graph widget.
|
||||
function graph.new(args)
|
||||
args = args or {}
|
||||
|
||||
local width = args.width or 100
|
||||
local height = args.height or 20
|
||||
|
||||
if width < 5 or height < 5 then return end
|
||||
|
||||
local _graph = base.make_widget()
|
||||
|
||||
_graph._data = { width = width, height = height, values = {}, max_value = 1 }
|
||||
|
||||
-- Set methods
|
||||
_graph.add_value = graph["add_value"]
|
||||
_graph.clear = graph["clear"]
|
||||
_graph.draw = graph.draw
|
||||
_graph.fit = graph.fit
|
||||
|
||||
for _, prop in ipairs(properties) do
|
||||
_graph["set_" .. prop] = graph["set_" .. prop]
|
||||
_graph["get_" .. prop] = graph["get_" .. prop]
|
||||
end
|
||||
|
||||
return _graph
|
||||
end
|
||||
|
||||
function graph.mt:__call(...)
|
||||
return graph.new(...)
|
||||
end
|
||||
|
||||
return setmetatable(graph, graph.mt)
|
||||
return util.deprecate_class(
|
||||
require("wibox.widget.graph"),
|
||||
"awful.widget.graph",
|
||||
"wibox.widget.graph"
|
||||
)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -1,230 +1,17 @@
|
|||
---------------------------------------------------------------------------
|
||||
--- A progressbar widget.
|
||||
--- This module has been moved to `wibox.widget.progressbar`
|
||||
--
|
||||
-- @author Julien Danjou <julien@danjou.info>
|
||||
-- @copyright 2009 Julien Danjou
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod awful.widget.progressbar
|
||||
---------------------------------------------------------------------------
|
||||
local util = require("awful.util")
|
||||
|
||||
local setmetatable = setmetatable
|
||||
local ipairs = ipairs
|
||||
local math = math
|
||||
local base = require("wibox.widget.base")
|
||||
local color = require("gears.color")
|
||||
|
||||
local progressbar = { mt = {} }
|
||||
|
||||
local data = setmetatable({}, { __mode = "k" })
|
||||
|
||||
--- Set the progressbar border color.
|
||||
-- If the value is nil, no border will be drawn.
|
||||
--
|
||||
-- @function set_border_color
|
||||
-- @param progressbar The progressbar.
|
||||
-- @param color The border color to set.
|
||||
|
||||
--- Set the progressbar foreground color.
|
||||
--
|
||||
-- @function set_color
|
||||
-- @param progressbar The progressbar.
|
||||
-- @param color The progressbar color.
|
||||
|
||||
--- Set the progressbar background color.
|
||||
--
|
||||
-- @function set_background_color
|
||||
-- @param progressbar The progressbar.
|
||||
-- @param color The progressbar background color.
|
||||
|
||||
--- Set the progressbar to draw vertically. Default is false.
|
||||
--
|
||||
-- @function set_vertical
|
||||
-- @param progressbar The progressbar.
|
||||
-- @param vertical A boolean value.
|
||||
|
||||
--- Set the progressbar to draw ticks. Default is false.
|
||||
--
|
||||
-- @function set_ticks
|
||||
-- @param progressbar The progressbar.
|
||||
-- @param ticks A boolean value.
|
||||
|
||||
--- Set the progressbar ticks gap.
|
||||
--
|
||||
-- @function set_ticks_gap
|
||||
-- @param progressbar The progressbar.
|
||||
-- @param value The value.
|
||||
|
||||
--- Set the progressbar ticks size.
|
||||
--
|
||||
-- @function set_ticks_size
|
||||
-- @param progressbar The progressbar.
|
||||
-- @param value The value.
|
||||
|
||||
--- Set the maximum value the progressbar should handle.
|
||||
--
|
||||
-- @function set_max_value
|
||||
-- @param progressbar The progressbar.
|
||||
-- @param value The value.
|
||||
|
||||
local properties = { "width", "height", "border_color",
|
||||
"color", "background_color",
|
||||
"vertical", "value", "max_value",
|
||||
"ticks", "ticks_gap", "ticks_size" }
|
||||
|
||||
function progressbar.draw(pbar, _, cr, width, height)
|
||||
local ticks_gap = data[pbar].ticks_gap or 1
|
||||
local ticks_size = data[pbar].ticks_size or 4
|
||||
|
||||
-- We want one pixel wide lines
|
||||
cr:set_line_width(1)
|
||||
|
||||
local value = data[pbar].value
|
||||
local max_value = data[pbar].max_value
|
||||
if value >= 0 then
|
||||
value = value / max_value
|
||||
end
|
||||
|
||||
local over_drawn_width = width
|
||||
local over_drawn_height = height
|
||||
local border_width = 0
|
||||
if data[pbar].border_color then
|
||||
-- Draw border
|
||||
cr:rectangle(0.5, 0.5, width - 1, height - 1)
|
||||
cr:set_source(color(data[pbar].border_color))
|
||||
cr:stroke()
|
||||
|
||||
over_drawn_width = width - 2 -- remove 2 for borders
|
||||
over_drawn_height = height - 2 -- remove 2 for borders
|
||||
border_width = 1
|
||||
end
|
||||
|
||||
cr:rectangle(border_width, border_width,
|
||||
over_drawn_width, over_drawn_height)
|
||||
cr:set_source(color(data[pbar].color or "#ff0000"))
|
||||
cr:fill()
|
||||
|
||||
-- Cover the part that is not set with a rectangle
|
||||
if data[pbar].vertical then
|
||||
local rel_height = over_drawn_height * (1 - value)
|
||||
cr:rectangle(border_width,
|
||||
border_width,
|
||||
over_drawn_width,
|
||||
rel_height)
|
||||
cr:set_source(color(data[pbar].background_color or "#000000aa"))
|
||||
cr:fill()
|
||||
|
||||
-- Place smaller pieces over the gradient if ticks are enabled
|
||||
if data[pbar].ticks then
|
||||
for i=0, height / (ticks_size+ticks_gap)-border_width do
|
||||
local rel_offset = over_drawn_height / 1 - (ticks_size+ticks_gap) * i
|
||||
|
||||
if rel_offset >= rel_height then
|
||||
cr:rectangle(border_width,
|
||||
rel_offset,
|
||||
over_drawn_width,
|
||||
ticks_gap)
|
||||
end
|
||||
end
|
||||
cr:set_source(color(data[pbar].background_color or "#000000aa"))
|
||||
cr:fill()
|
||||
end
|
||||
else
|
||||
local rel_x = over_drawn_width * value
|
||||
cr:rectangle(border_width + rel_x,
|
||||
border_width,
|
||||
over_drawn_width - rel_x,
|
||||
over_drawn_height)
|
||||
cr:set_source(color(data[pbar].background_color or "#000000aa"))
|
||||
cr:fill()
|
||||
|
||||
if data[pbar].ticks then
|
||||
for i=0, width / (ticks_size+ticks_gap)-border_width do
|
||||
local rel_offset = over_drawn_width / 1 - (ticks_size+ticks_gap) * i
|
||||
|
||||
if rel_offset <= rel_x then
|
||||
cr:rectangle(rel_offset,
|
||||
border_width,
|
||||
ticks_gap,
|
||||
over_drawn_height)
|
||||
end
|
||||
end
|
||||
cr:set_source(color(data[pbar].background_color or "#000000aa"))
|
||||
cr:fill()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function progressbar.fit(pbar)
|
||||
return data[pbar].width, data[pbar].height
|
||||
end
|
||||
|
||||
--- Set the progressbar value.
|
||||
-- @param value The progress bar value between 0 and 1.
|
||||
function progressbar:set_value(value)
|
||||
value = value or 0
|
||||
local max_value = data[self].max_value
|
||||
data[self].value = math.min(max_value, math.max(0, value))
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set the progressbar height.
|
||||
-- @param height The height to set.
|
||||
function progressbar:set_height(height)
|
||||
data[self].height = height
|
||||
self:emit_signal("widget::layout_changed")
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set the progressbar width.
|
||||
-- @param width The width to set.
|
||||
function progressbar:set_width(width)
|
||||
data[self].width = width
|
||||
self:emit_signal("widget::layout_changed")
|
||||
return self
|
||||
end
|
||||
|
||||
-- Build properties function
|
||||
for _, prop in ipairs(properties) do
|
||||
if not progressbar["set_" .. prop] then
|
||||
progressbar["set_" .. prop] = function(pbar, value)
|
||||
data[pbar][prop] = value
|
||||
pbar:emit_signal("widget::redraw_needed")
|
||||
return pbar
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Create a progressbar widget.
|
||||
-- @param args Standard widget() arguments. You should add width and height
|
||||
-- key to set progressbar geometry.
|
||||
-- @return A progressbar widget.
|
||||
function progressbar.new(args)
|
||||
args = args or {}
|
||||
local width = args.width or 100
|
||||
local height = args.height or 20
|
||||
|
||||
args.type = "imagebox"
|
||||
|
||||
local pbar = base.make_widget()
|
||||
|
||||
data[pbar] = { width = width, height = height, value = 0, max_value = 1 }
|
||||
|
||||
-- Set methods
|
||||
for _, prop in ipairs(properties) do
|
||||
pbar["set_" .. prop] = progressbar["set_" .. prop]
|
||||
end
|
||||
|
||||
pbar.draw = progressbar.draw
|
||||
pbar.fit = progressbar.fit
|
||||
|
||||
return pbar
|
||||
end
|
||||
|
||||
function progressbar.mt:__call(...)
|
||||
return progressbar.new(...)
|
||||
end
|
||||
|
||||
return setmetatable(progressbar, progressbar.mt)
|
||||
return util.deprecate_class(
|
||||
require("wibox.widget.progressbar"),
|
||||
"awful.widget.progressbar",
|
||||
"wibox.widget.progressbar"
|
||||
)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -1,52 +1,17 @@
|
|||
---------------------------------------------------------------------------
|
||||
--- Text clock widget.
|
||||
-- This widget has moved to `wibox.widget.textclock`
|
||||
--
|
||||
-- @author Julien Danjou <julien@danjou.info>
|
||||
-- @copyright 2009 Julien Danjou
|
||||
-- @copyright 2008-2009 Julien Danjou
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod awful.widget.textclock
|
||||
---------------------------------------------------------------------------
|
||||
local util = require("awful.util")
|
||||
|
||||
local setmetatable = setmetatable
|
||||
local os = os
|
||||
local textbox = require("wibox.widget.textbox")
|
||||
local timer = require("gears.timer")
|
||||
local DateTime = require("lgi").GLib.DateTime
|
||||
|
||||
local textclock = { mt = {} }
|
||||
|
||||
--- This lowers the timeout so that it occurs "correctly". For example, a timeout
|
||||
-- of 60 is rounded so that it occurs the next time the clock reads ":00 seconds".
|
||||
local function calc_timeout(real_timeout)
|
||||
return real_timeout - os.time() % real_timeout
|
||||
end
|
||||
|
||||
--- Create a textclock widget. It draws the time it is in a textbox.
|
||||
--
|
||||
-- @param format The time format. Default is " %a %b %d, %H:%M ".
|
||||
-- @param timeout How often update the time. Default is 60.
|
||||
-- @return A textbox widget.
|
||||
function textclock.new(format, timeout)
|
||||
format = format or " %a %b %d, %H:%M "
|
||||
timeout = timeout or 60
|
||||
|
||||
local w = textbox()
|
||||
local t
|
||||
function w._textclock_update_cb()
|
||||
w:set_markup(DateTime.new_now_local():format(format))
|
||||
t.timeout = calc_timeout(timeout)
|
||||
t:again()
|
||||
return true -- Continue the timer
|
||||
end
|
||||
t = timer.weak_start_new(timeout, w._textclock_update_cb)
|
||||
t:emit_signal("timeout")
|
||||
return w
|
||||
end
|
||||
|
||||
function textclock.mt:__call(...)
|
||||
return textclock.new(...)
|
||||
end
|
||||
|
||||
return setmetatable(textclock, textclock.mt)
|
||||
return util.deprecate_class(
|
||||
require("wibox.widget.textclock"),
|
||||
"awful.widget.textclock",
|
||||
"wibox.widget.textclock"
|
||||
)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -230,7 +230,7 @@ end
|
|||
--
|
||||
-- @tparam[opt=2] integer level Level for `debug.getinfo(level, "S")`.
|
||||
-- Typically 2 or 3.
|
||||
-- @treturn string The module name, e.g. "wibox.widget.background".
|
||||
-- @treturn string The module name, e.g. "wibox.container.background".
|
||||
function object.modulename(level)
|
||||
return debug.getinfo(level, "S").source:gsub(".*/lib/", ""):gsub("/", "."):gsub("%.lua", "")
|
||||
end
|
||||
|
|
|
@ -28,13 +28,15 @@ local module = {}
|
|||
--- Add a rounded rectangle to the current path.
|
||||
-- Note: If the radius is bigger than either half side, it will be reduced.
|
||||
--
|
||||
-- @SHAPE_rounded_rect_EXAMPLE@
|
||||
-- @DOC_gears_shape_rounded_rect_EXAMPLE@
|
||||
--
|
||||
-- @param cr A cairo content
|
||||
-- @tparam number width The rectangle width
|
||||
-- @tparam number height The rectangle height
|
||||
-- @tparam number radius the corner radius
|
||||
function module.rounded_rect(cr, width, height, radius)
|
||||
radius = radius or 10
|
||||
|
||||
if width / 2 < radius then
|
||||
radius = width / 2
|
||||
end
|
||||
|
@ -53,7 +55,7 @@ end
|
|||
|
||||
--- Add a rectangle delimited by 2 180 degree arcs to the path.
|
||||
--
|
||||
-- @SHAPE_rounded_bar_EXAMPLE@
|
||||
-- @DOC_gears_shape_rounded_bar_EXAMPLE@
|
||||
--
|
||||
-- @param cr A cairo content
|
||||
-- @param width The rectangle width
|
||||
|
@ -64,7 +66,7 @@ end
|
|||
|
||||
--- A rounded rect with only some of the corners rounded.
|
||||
--
|
||||
-- @SHAPE_partially_rounded_rect_EXAMPLE@
|
||||
-- @DOC_gears_shape_partially_rounded_rect_EXAMPLE@
|
||||
--
|
||||
-- @param cr A cairo context
|
||||
-- @tparam number width The shape width
|
||||
|
@ -117,7 +119,7 @@ end
|
|||
|
||||
--- A rounded rectangle with a triangle at the top.
|
||||
--
|
||||
-- @SHAPE_infobubble_EXAMPLE@
|
||||
-- @DOC_gears_shape_infobubble_EXAMPLE@
|
||||
--
|
||||
-- @param cr A cairo context
|
||||
-- @tparam number width The shape width
|
||||
|
@ -152,7 +154,7 @@ end
|
|||
|
||||
--- A rectangle terminated by an arrow.
|
||||
--
|
||||
-- @SHAPE_rectangular_tag_EXAMPLE@
|
||||
-- @DOC_gears_shape_rectangular_tag_EXAMPLE@
|
||||
--
|
||||
-- @param cr A cairo context
|
||||
-- @tparam number width The shape width
|
||||
|
@ -179,7 +181,7 @@ end
|
|||
|
||||
--- A simple arrow shape.
|
||||
--
|
||||
-- @SHAPE_arrow_EXAMPLE@
|
||||
-- @DOC_gears_shape_arrow_EXAMPLE@
|
||||
--
|
||||
-- @param cr A cairo context
|
||||
-- @tparam number width The shape width
|
||||
|
@ -206,7 +208,7 @@ end
|
|||
|
||||
--- A squeezed hexagon filling the rectangle.
|
||||
--
|
||||
-- @SHAPE_hexagon_EXAMPLE@
|
||||
-- @DOC_gears_shape_hexagon_EXAMPLE@
|
||||
--
|
||||
-- @param cr A cairo context
|
||||
-- @tparam number width The shape width
|
||||
|
@ -224,7 +226,7 @@ end
|
|||
|
||||
--- Double arrow popularized by the vim-powerline module.
|
||||
--
|
||||
-- @SHAPE_powerline_EXAMPLE@
|
||||
-- @DOC_gears_shape_powerline_EXAMPLE@
|
||||
--
|
||||
-- @param cr A cairo context
|
||||
-- @tparam number width The shape width
|
||||
|
@ -252,7 +254,7 @@ end
|
|||
|
||||
--- An isosceles triangle.
|
||||
--
|
||||
-- @SHAPE_isosceles_triangle_EXAMPLE@
|
||||
-- @DOC_gears_shape_isosceles_triangle_EXAMPLE@
|
||||
--
|
||||
-- @param cr A cairo context
|
||||
-- @tparam number width The shape width
|
||||
|
@ -266,7 +268,7 @@ end
|
|||
|
||||
--- A cross (**+**) symbol.
|
||||
--
|
||||
-- @SHAPE_cross_EXAMPLE@
|
||||
-- @DOC_gears_shape_cross_EXAMPLE@
|
||||
--
|
||||
-- @param cr A cairo context
|
||||
-- @tparam number width The shape width
|
||||
|
@ -293,7 +295,7 @@ end
|
|||
|
||||
--- A similar shape to the `rounded_rect`, but with sharp corners.
|
||||
--
|
||||
-- @SHAPE_octogon_EXAMPLE@
|
||||
-- @DOC_gears_shape_octogon_EXAMPLE@
|
||||
--
|
||||
-- @param cr A cairo context
|
||||
-- @tparam number width The shape width
|
||||
|
@ -316,7 +318,7 @@ end
|
|||
|
||||
--- A circle shape.
|
||||
--
|
||||
-- @SHAPE_circle_EXAMPLE@
|
||||
-- @DOC_gears_shape_circle_EXAMPLE@
|
||||
--
|
||||
-- @param cr A cairo context
|
||||
-- @tparam number width The shape width
|
||||
|
@ -329,7 +331,7 @@ end
|
|||
|
||||
--- A simple rectangle.
|
||||
--
|
||||
-- @SHAPE_rectangle_EXAMPLE@
|
||||
-- @DOC_gears_shape_rectangle_EXAMPLE@
|
||||
--
|
||||
-- @param cr A cairo context
|
||||
-- @tparam number width The shape width
|
||||
|
@ -341,7 +343,7 @@ end
|
|||
--- A diagonal parallelogram with the bottom left corner at x=0 and top right
|
||||
-- at x=width.
|
||||
--
|
||||
-- @SHAPE_parallelogram_EXAMPLE@
|
||||
-- @DOC_gears_shape_parallelogram_EXAMPLE@
|
||||
--
|
||||
-- @param cr A cairo context
|
||||
-- @tparam number width The shape width
|
||||
|
@ -358,7 +360,7 @@ end
|
|||
|
||||
--- A losange.
|
||||
--
|
||||
-- @SHAPE_losange_EXAMPLE@
|
||||
-- @DOC_gears_shape_losange_EXAMPLE@
|
||||
--
|
||||
-- @param cr A cairo context
|
||||
-- @tparam number width The shape width
|
||||
|
@ -377,7 +379,7 @@ end
|
|||
-- Note that this shape is not closed and thus filling it doesn't make much
|
||||
-- sense.
|
||||
--
|
||||
-- @SHAPE_radial_progress_EXAMPLE@
|
||||
-- @DOC_gears_shape_radial_progress_EXAMPLE@
|
||||
--
|
||||
-- @param cr A cairo context
|
||||
-- @tparam number w The shape width
|
||||
|
|
|
@ -522,7 +522,7 @@ function naughty.notify(args)
|
|||
|
||||
-- create textbox
|
||||
local textbox = wibox.widget.textbox()
|
||||
local marginbox = wibox.layout.margin()
|
||||
local marginbox = wibox.container.margin()
|
||||
marginbox:set_margins(margin)
|
||||
marginbox:set_widget(textbox)
|
||||
textbox:set_valign("middle")
|
||||
|
@ -538,7 +538,7 @@ function naughty.notify(args)
|
|||
if actions then
|
||||
for action, callback in pairs(actions) do
|
||||
local actiontextbox = wibox.widget.textbox()
|
||||
local actionmarginbox = wibox.layout.margin()
|
||||
local actionmarginbox = wibox.container.margin()
|
||||
actionmarginbox:set_margins(margin)
|
||||
actionmarginbox:set_widget(actiontextbox)
|
||||
actiontextbox:set_valign("middle")
|
||||
|
@ -582,7 +582,7 @@ function naughty.notify(args)
|
|||
-- if we have an icon, use it
|
||||
if icon then
|
||||
iconbox = wibox.widget.imagebox()
|
||||
iconmargin = wibox.layout.margin(iconbox, margin, margin, margin, margin)
|
||||
iconmargin = wibox.container.margin(iconbox, margin, margin, margin, margin)
|
||||
if icon_size then
|
||||
local scaled = cairo.ImageSurface(cairo.Format.ARGB32, icon_size, icon_size)
|
||||
local cr = cairo.Context(scaled)
|
||||
|
|
|
@ -0,0 +1,292 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- A container capable of changing the background color, foreground color
|
||||
-- widget shape.
|
||||
--
|
||||
--@DOC_wibox_container_defaults_background_EXAMPLE@
|
||||
-- @author Uli Schlachter
|
||||
-- @copyright 2010 Uli Schlachter
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.container.background
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local base = require("wibox.widget.base")
|
||||
local color = require("gears.color")
|
||||
local surface = require("gears.surface")
|
||||
local beautiful = require("beautiful")
|
||||
local cairo = require("lgi").cairo
|
||||
local util = require("awful.util")
|
||||
local setmetatable = setmetatable
|
||||
local type = type
|
||||
local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
|
||||
|
||||
local background = { mt = {} }
|
||||
|
||||
-- Draw this widget
|
||||
function background:draw(context, cr, width, height)
|
||||
if not self._private.widget or not self._private.widget:get_visible() then
|
||||
return
|
||||
end
|
||||
|
||||
-- Keep the shape path in case there is a border
|
||||
self._private.path = nil
|
||||
|
||||
if self._private.shape then
|
||||
-- Only add the offset if there is something to draw
|
||||
local offset = ((self._private.shape_border_width and self._private.shape_border_color)
|
||||
and self._private.shape_border_width or 0) / 2
|
||||
|
||||
cr:translate(offset, offset)
|
||||
self._private.shape(cr, width - 2*offset, height - 2*offset, unpack(self._private.shape_args or {}))
|
||||
cr:translate(-offset, -offset)
|
||||
self._private.path = cr:copy_path()
|
||||
cr:clip()
|
||||
end
|
||||
|
||||
if self._private.background then
|
||||
cr:set_source(self._private.background)
|
||||
cr:paint()
|
||||
end
|
||||
if self._private.bgimage then
|
||||
if type(self._private.bgimage) == "function" then
|
||||
self._private.bgimage(context, cr, width, height,unpack(self._private.bgimage_args))
|
||||
else
|
||||
local pattern = cairo.Pattern.create_for_surface(self._private.bgimage)
|
||||
cr:set_source(pattern)
|
||||
cr:paint()
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Draw the border
|
||||
function background:after_draw_children(_, cr)
|
||||
-- Draw the border
|
||||
if self._private.path and self._private.shape_border_width and self._private.shape_border_width > 0 then
|
||||
cr:append_path(self._private.path)
|
||||
cr:set_source(color(self._private.shape_border_color or self._private.foreground or beautiful.fg_normal))
|
||||
|
||||
cr:set_line_width(self._private.shape_border_width)
|
||||
cr:stroke()
|
||||
self._private.path = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Prepare drawing the children of this widget
|
||||
function background:before_draw_children(_, cr)
|
||||
if self._private.foreground then
|
||||
cr:set_source(self._private.foreground)
|
||||
end
|
||||
|
||||
-- Clip the shape
|
||||
if self._private.path and self._private.shape_clip then
|
||||
cr:append_path(self._private.path)
|
||||
cr:clip()
|
||||
end
|
||||
end
|
||||
|
||||
-- Layout this widget
|
||||
function background:layout(_, width, height)
|
||||
if self._private.widget then
|
||||
return { base.place_widget_at(self._private.widget, 0, 0, width, height) }
|
||||
end
|
||||
end
|
||||
|
||||
-- Fit this widget into the given area
|
||||
function background:fit(context, width, height)
|
||||
if not self._private.widget then
|
||||
return 0, 0
|
||||
end
|
||||
|
||||
return base.fit_widget(self, context, self._private.widget, width, height)
|
||||
end
|
||||
|
||||
--- The widget displayed in the background widget.
|
||||
-- @property widget
|
||||
-- @tparam widget widget The widget to be disaplayed inside of the background
|
||||
-- area
|
||||
|
||||
function background:set_widget(widget)
|
||||
if widget then
|
||||
base.check_widget(widget)
|
||||
end
|
||||
self._private.widget = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
function background:get_widget()
|
||||
return self._private.widget
|
||||
end
|
||||
|
||||
-- Get children element
|
||||
-- @treturn table The children
|
||||
function background:get_children()
|
||||
return {self._private.widget}
|
||||
end
|
||||
|
||||
-- Replace the layout children
|
||||
-- This layout only accept one children, all others will be ignored
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function background:set_children(children)
|
||||
self:set_widget(children[1])
|
||||
end
|
||||
|
||||
--- The background color/pattern/gradient to use.
|
||||
--@DOC_wibox_container_background_bg_EXAMPLE@
|
||||
-- @property bg
|
||||
-- @param bg A color string, pattern or gradient
|
||||
-- @see gears.color
|
||||
|
||||
function background:set_bg(bg)
|
||||
if bg then
|
||||
self._private.background = color(bg)
|
||||
else
|
||||
self._private.background = nil
|
||||
end
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
function background:get_bg()
|
||||
return self._private.background
|
||||
end
|
||||
|
||||
--- The foreground (text) color/pattern/gradient to use.
|
||||
--@DOC_wibox_container_background_fg_EXAMPLE@
|
||||
-- @property fg
|
||||
-- @param fg A color string, pattern or gradient
|
||||
-- @see gears.color
|
||||
|
||||
function background:set_fg(fg)
|
||||
if fg then
|
||||
self._private.foreground = color(fg)
|
||||
else
|
||||
self._private.foreground = nil
|
||||
end
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
function background:get_fg()
|
||||
return self._private.foreground
|
||||
end
|
||||
|
||||
--- The background shap e.
|
||||
--
|
||||
-- Use `set_shape` to set additional shape paramaters.
|
||||
--
|
||||
--@DOC_wibox_container_background_shape_EXAMPLE@
|
||||
-- @property shape
|
||||
-- @param shape A function taking a context, width and height as arguments
|
||||
-- @see gears.shape
|
||||
-- @see set_shape
|
||||
|
||||
--- Set the background shape.
|
||||
--
|
||||
-- Any other arguments will be passed to the shape function
|
||||
-- @param shape A function taking a context, width and height as arguments
|
||||
-- @see gears.shape
|
||||
-- @see shape
|
||||
function background:set_shape(shape, ...)
|
||||
self._private.shape = shape
|
||||
self._private.shape_args = {...}
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
function background:get_shape()
|
||||
return self._private.shape
|
||||
end
|
||||
|
||||
--- When a `shape` is set, also draw a border.
|
||||
--
|
||||
-- See `wibox.container.background.shape` for an usage example.
|
||||
-- @property shape_border_width
|
||||
-- @tparam number width The border width
|
||||
|
||||
function background:set_shape_border_width(width)
|
||||
self._private.shape_border_width = width
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
function background:get_shape_border_width()
|
||||
return self._private.shape_border_width
|
||||
end
|
||||
|
||||
--- When a `shape` is set, also draw a border.
|
||||
--
|
||||
-- See `wibox.container.background.shape` for an usage example.
|
||||
-- @property shape_border_color
|
||||
-- @param[opt=self._private.foreground] fg The border color, pattern or gradient
|
||||
-- @see gears.color
|
||||
|
||||
function background:set_shape_border_color(fg)
|
||||
self._private.shape_border_color = fg
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
function background:get_shape_border_color()
|
||||
return self._private.shape_border_color
|
||||
end
|
||||
|
||||
--- When a `shape` is set, make sure nothing is drawn outside of it.
|
||||
--@DOC_wibox_container_background_clip_EXAMPLE@
|
||||
-- @property shape_clip
|
||||
-- @tparam boolean value If the shape clip is enable
|
||||
|
||||
function background:set_shape_clip(value)
|
||||
self._private.shape_clip = value
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
function background:get_shape_clip()
|
||||
return self._private.shape_clip or false
|
||||
end
|
||||
|
||||
--- The background image to use
|
||||
-- If `image` is a function, it will be called with `(context, cr, width, height)`
|
||||
-- as arguments. Any other arguments passed to this method will be appended.
|
||||
-- @property bgimage
|
||||
-- @param image A background image or a function
|
||||
-- @see gears.surface
|
||||
|
||||
function background:set_bgimage(image, ...)
|
||||
self._private.bgimage = type(image) == "function" and image or surface.load(image)
|
||||
self._private.bgimage_args = {...}
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
function background:get_bgimage()
|
||||
return self._private.bgimage
|
||||
end
|
||||
|
||||
--- Returns a new background container.
|
||||
--
|
||||
-- A background container applies a background and foreground color
|
||||
-- to another widget.
|
||||
-- @param[opt] widget The widget to display.
|
||||
-- @param[opt] bg The background to use for that widget.
|
||||
-- @param[opt] shape A `gears.shape` compatible shape function
|
||||
-- @function wibox.container.background
|
||||
local function new(widget, bg, shape)
|
||||
local ret = base.make_widget(nil, nil, {
|
||||
enable_properties = true,
|
||||
})
|
||||
|
||||
util.table.crush(ret, background, true)
|
||||
|
||||
ret._private.shape = shape
|
||||
|
||||
ret:set_widget(widget)
|
||||
ret:set_bg(bg)
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function background.mt:__call(...)
|
||||
return new(...)
|
||||
end
|
||||
|
||||
--@DOC_widget_COMMON@
|
||||
|
||||
--@DOC_object_COMMON@
|
||||
|
||||
return setmetatable(background, background.mt)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -0,0 +1,171 @@
|
|||
---------------------------------------------------------------------------
|
||||
--
|
||||
--@DOC_wibox_container_defaults_constraint_EXAMPLE@
|
||||
-- @author Lukáš Hrázký
|
||||
-- @copyright 2012 Lukáš Hrázký
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.container.constraint
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local setmetatable = setmetatable
|
||||
local base = require("wibox.widget.base")
|
||||
local util = require("awful.util")
|
||||
local math = math
|
||||
|
||||
local constraint = { mt = {} }
|
||||
|
||||
-- Layout a constraint layout
|
||||
function constraint:layout(_, width, height)
|
||||
if self._private.widget then
|
||||
return { base.place_widget_at(self._private.widget, 0, 0, width, height) }
|
||||
end
|
||||
end
|
||||
|
||||
-- Fit a constraint layout into the given space
|
||||
function constraint:fit(context, width, height)
|
||||
local w, h
|
||||
if self._private.widget then
|
||||
w = self._private.strategy(width, self._private.width)
|
||||
h = self._private.strategy(height, self._private.height)
|
||||
|
||||
w, h = base.fit_widget(self, context, self._private.widget, w, h)
|
||||
else
|
||||
w, h = 0, 0
|
||||
end
|
||||
|
||||
w = self._private.strategy(w, self._private.width)
|
||||
h = self._private.strategy(h, self._private.height)
|
||||
|
||||
return w, h
|
||||
end
|
||||
|
||||
--- The widget to be constrained.
|
||||
-- @property widget
|
||||
-- @tparam widget widget The widget
|
||||
|
||||
function constraint:set_widget(widget)
|
||||
self._private.widget = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
function constraint:get_widget()
|
||||
return self._private.widget
|
||||
end
|
||||
|
||||
--- Get the number of children element
|
||||
-- @treturn table The children
|
||||
function constraint:get_children()
|
||||
return {self._private.widget}
|
||||
end
|
||||
|
||||
--- Replace the layout children
|
||||
-- This layout only accept one children, all others will be ignored
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function constraint:set_children(children)
|
||||
self:set_widget(children[1])
|
||||
end
|
||||
|
||||
--- Set the strategy to use for the constraining. Valid values are 'max',
|
||||
-- 'min' or 'exact'. Throws an error on invalid values.
|
||||
-- @property strategy
|
||||
|
||||
function constraint:set_strategy(val)
|
||||
local func = {
|
||||
min = function(real_size, limit)
|
||||
return limit and math.max(limit, real_size) or real_size
|
||||
end,
|
||||
max = function(real_size, limit)
|
||||
return limit and math.min(limit, real_size) or real_size
|
||||
end,
|
||||
exact = function(real_size, limit)
|
||||
return limit or real_size
|
||||
end
|
||||
}
|
||||
|
||||
if not func[val] then
|
||||
error("Invalid strategy for constraint layout: " .. tostring(val))
|
||||
end
|
||||
|
||||
self._private.strategy = func[val]
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
function constraint:get_strategy()
|
||||
return self._private.strategy
|
||||
end
|
||||
|
||||
--- Set the maximum width to val. nil for no width limit.
|
||||
-- @property height
|
||||
-- @param number
|
||||
|
||||
function constraint:set_width(val)
|
||||
self._private.width = val
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
function constraint:get_width()
|
||||
return self._private.width
|
||||
end
|
||||
|
||||
--- Set the maximum height to val. nil for no height limit.
|
||||
-- @property width
|
||||
-- @param number
|
||||
|
||||
function constraint:set_height(val)
|
||||
self._private.height = val
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
function constraint:get_height()
|
||||
return self._private.height
|
||||
end
|
||||
|
||||
--- Reset this layout. The widget will be unreferenced, strategy set to "max"
|
||||
-- and the constraints set to nil.
|
||||
function constraint:reset()
|
||||
self._private.width = nil
|
||||
self._private.height = nil
|
||||
self:set_strategy("max")
|
||||
self:set_widget(nil)
|
||||
end
|
||||
|
||||
--- Returns a new constraint container.
|
||||
-- This container will constraint the size of a
|
||||
-- widget according to the strategy. Note that this will only work for layouts
|
||||
-- that respect the widget's size, eg. fixed layout. In layouts that don't
|
||||
-- (fully) respect widget's requested size, the inner widget still might get
|
||||
-- drawn with a size that does not fit the constraint, eg. in flex layout.
|
||||
-- @param[opt] widget A widget to use.
|
||||
-- @param[opt] strategy How to constraint the size. 'max' (default), 'min' or
|
||||
-- 'exact'.
|
||||
-- @param[opt] width The maximum width of the widget. nil for no limit.
|
||||
-- @param[opt] height The maximum height of the widget. nil for no limit.
|
||||
-- @treturn table A new constraint container
|
||||
-- @function wibox.container.constraint
|
||||
local function new(widget, strategy, width, height)
|
||||
local ret = base.make_widget(nil, nil, {enable_properties = true})
|
||||
|
||||
util.table.crush(ret, constraint, true)
|
||||
|
||||
ret:set_strategy(strategy or "max")
|
||||
ret:set_width(width)
|
||||
ret:set_height(height)
|
||||
|
||||
if widget then
|
||||
ret:set_widget(widget)
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function constraint.mt:__call(...)
|
||||
return new(...)
|
||||
end
|
||||
|
||||
--@DOC_widget_COMMON@
|
||||
|
||||
--@DOC_object_COMMON@
|
||||
|
||||
return setmetatable(constraint, constraint.mt)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -0,0 +1,20 @@
|
|||
---------------------------------------------------------------------------
|
||||
--- Collection of containers that can be used in widget boxes
|
||||
--
|
||||
-- @author Uli Schlachter
|
||||
-- @copyright 2010 Uli Schlachter
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.container
|
||||
---------------------------------------------------------------------------
|
||||
local base = require("wibox.widget.base")
|
||||
|
||||
return setmetatable({
|
||||
rotate = require("wibox.container.rotate");
|
||||
margin = require("wibox.container.margin");
|
||||
mirror = require("wibox.container.mirror");
|
||||
constraint = require("wibox.container.constraint");
|
||||
scroll = require("wibox.container.scroll");
|
||||
background = require("wibox.container.background");
|
||||
}, {__call = function(_, args) return base.make_widget_declarative(args) end})
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -0,0 +1,219 @@
|
|||
---------------------------------------------------------------------------
|
||||
--
|
||||
--@DOC_wibox_container_defaults_margin_EXAMPLE@
|
||||
-- @author Uli Schlachter
|
||||
-- @copyright 2010 Uli Schlachter
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.container.margin
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local pairs = pairs
|
||||
local setmetatable = setmetatable
|
||||
local base = require("wibox.widget.base")
|
||||
local gcolor = require("gears.color")
|
||||
local cairo = require("lgi").cairo
|
||||
local util = require("awful.util")
|
||||
|
||||
local margin = { mt = {} }
|
||||
|
||||
-- Draw a margin layout
|
||||
function margin:draw(_, cr, width, height)
|
||||
local x = self._private.left
|
||||
local y = self._private.top
|
||||
local w = self._private.right
|
||||
local h = self._private.bottom
|
||||
local color = self._private.color
|
||||
|
||||
if not self._private.widget or width <= x + w or height <= y + h then
|
||||
return
|
||||
end
|
||||
|
||||
if color then
|
||||
cr:set_source(color)
|
||||
cr:rectangle(0, 0, width, height)
|
||||
cr:rectangle(x, y, width - x - w, height - y - h)
|
||||
cr:set_fill_rule(cairo.FillRule.EVEN_ODD)
|
||||
cr:fill()
|
||||
end
|
||||
end
|
||||
|
||||
-- Layout a margin layout
|
||||
function margin:layout(_, width, height)
|
||||
if self._private.widget then
|
||||
local x = self._private.left
|
||||
local y = self._private.top
|
||||
local w = self._private.right
|
||||
local h = self._private.bottom
|
||||
|
||||
return { base.place_widget_at(self._private.widget, x, y, width - x - w, height - y - h) }
|
||||
end
|
||||
end
|
||||
|
||||
-- Fit a margin layout into the given space
|
||||
function margin:fit(context, width, height)
|
||||
local extra_w = self._private.left + self._private.right
|
||||
local extra_h = self._private.top + self._private.bottom
|
||||
local w, h = 0, 0
|
||||
if self._private.widget then
|
||||
w, h = base.fit_widget(self, context, self._private.widget, width - extra_w, height - extra_h)
|
||||
end
|
||||
|
||||
if self._private.draw_empty == false and (w == 0 or h == 0) then
|
||||
return 0, 0
|
||||
end
|
||||
|
||||
return w + extra_w, h + extra_h
|
||||
end
|
||||
|
||||
--- The widget to be wrapped the the margins.
|
||||
-- @property widget
|
||||
-- @tparam widget widget The widget
|
||||
|
||||
function margin:set_widget(widget)
|
||||
if widget then
|
||||
base.check_widget(widget)
|
||||
end
|
||||
self._private.widget = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
function margin:get_widget()
|
||||
return self._private.widget
|
||||
end
|
||||
|
||||
-- Get the number of children element
|
||||
-- @treturn table The children
|
||||
function margin:get_children()
|
||||
return {self._private.widget}
|
||||
end
|
||||
|
||||
-- Replace the layout children
|
||||
-- This layout only accept one children, all others will be ignored
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function margin:set_children(children)
|
||||
self:set_widget(children[1])
|
||||
end
|
||||
|
||||
--- Set all the margins to val.
|
||||
-- @property margins
|
||||
-- @tparam number val The margin value
|
||||
|
||||
function margin:set_margins(val)
|
||||
if self._private.left == val and
|
||||
self._private.right == val and
|
||||
self._private.top == val and
|
||||
self._private.bottom == val then
|
||||
return
|
||||
end
|
||||
|
||||
self._private.left = val
|
||||
self._private.right = val
|
||||
self._private.top = val
|
||||
self._private.bottom = val
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Set the margins color to create a border.
|
||||
-- @property color
|
||||
-- @param color A color used to fill the margin.
|
||||
|
||||
function margin:set_color(color)
|
||||
self._private.color = color and gcolor(color)
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
function margin:get_color()
|
||||
return self._private.color
|
||||
end
|
||||
|
||||
--- Draw the margin even if the content size is 0x0 (default: true)
|
||||
-- @function draw_empty
|
||||
-- @tparam boolean draw_empty Draw nothing is content is 0x0 or draw the margin anyway
|
||||
|
||||
function margin:set_draw_empty(draw_empty)
|
||||
self._private.draw_empty = draw_empty
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
function margin:get_draw_empty()
|
||||
return self._private.draw_empty
|
||||
end
|
||||
|
||||
--- Reset this layout. The widget will be unreferenced, the margins set to 0
|
||||
-- and the color erased
|
||||
function margin:reset()
|
||||
self:set_widget(nil)
|
||||
self:set_margins(0)
|
||||
self:set_color(nil)
|
||||
end
|
||||
|
||||
--- Set the left margin that this layout adds to its widget.
|
||||
-- @param margin The new margin to use.
|
||||
-- @property left
|
||||
|
||||
--- Set the right margin that this layout adds to its widget.
|
||||
-- @param margin The new margin to use.
|
||||
-- @property right
|
||||
|
||||
--- Set the top margin that this layout adds to its widget.
|
||||
-- @param margin The new margin to use.
|
||||
-- @property top
|
||||
|
||||
--- Set the bottom margin that this layout adds to its widget.
|
||||
-- @param margin The new margin to use.
|
||||
-- @property bottom
|
||||
|
||||
-- Create setters for each direction
|
||||
for _, v in pairs({ "left", "right", "top", "bottom" }) do
|
||||
margin["set_" .. v] = function(layout, val)
|
||||
if layout._private[v] == val then return end
|
||||
layout._private[v] = val
|
||||
layout:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
margin["get_" .. v] = function(layout)
|
||||
return layout._private[v]
|
||||
end
|
||||
end
|
||||
|
||||
--- Returns a new margin container.
|
||||
-- @param[opt] widget A widget to use.
|
||||
-- @param[opt] left A margin to use on the left side of the widget.
|
||||
-- @param[opt] right A margin to use on the right side of the widget.
|
||||
-- @param[opt] top A margin to use on the top side of the widget.
|
||||
-- @param[opt] bottom A margin to use on the bottom side of the widget.
|
||||
-- @param[opt] color A color for the margins.
|
||||
-- @param[opt] draw_empty whether or not to draw the margin when the content is empty
|
||||
-- @treturn table A new margin container
|
||||
-- @function wibox.container.margin
|
||||
local function new(widget, left, right, top, bottom, color, draw_empty)
|
||||
local ret = base.make_widget(nil, nil, {enable_properties = true})
|
||||
|
||||
util.table.crush(ret, margin, true)
|
||||
|
||||
ret:set_left(left or 0)
|
||||
ret:set_right(right or 0)
|
||||
ret:set_top(top or 0)
|
||||
ret:set_bottom(bottom or 0)
|
||||
ret:set_draw_empty(draw_empty)
|
||||
|
||||
ret:set_color(color)
|
||||
|
||||
if widget then
|
||||
ret:set_widget(widget)
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function margin.mt:__call(...)
|
||||
return new(...)
|
||||
end
|
||||
|
||||
--@DOC_widget_COMMON@
|
||||
|
||||
--@DOC_object_COMMON@
|
||||
|
||||
return setmetatable(margin, margin.mt)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -0,0 +1,140 @@
|
|||
---------------------------------------------------------------------------
|
||||
--
|
||||
--@DOC_wibox_container_defaults_mirror_EXAMPLE@
|
||||
-- @author dodo
|
||||
-- @copyright 2012 dodo
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.container.mirror
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local type = type
|
||||
local error = error
|
||||
local ipairs = ipairs
|
||||
local setmetatable = setmetatable
|
||||
local base = require("wibox.widget.base")
|
||||
local matrix = require("gears.matrix")
|
||||
local util = require("awful.util")
|
||||
|
||||
local mirror = { mt = {} }
|
||||
|
||||
-- Layout this layout
|
||||
function mirror:layout(_, width, height)
|
||||
if not self._private.widget then return end
|
||||
|
||||
local m = matrix.identity
|
||||
local t = { x = 0, y = 0 } -- translation
|
||||
local s = { x = 1, y = 1 } -- scale
|
||||
if self._private.horizontal then
|
||||
t.x = width
|
||||
s.x = -1
|
||||
end
|
||||
if self._private.vertical then
|
||||
t.y = height
|
||||
s.y = -1
|
||||
end
|
||||
m = m:translate(t.x, t.y)
|
||||
m = m:scale(s.x, s.y)
|
||||
|
||||
return { base.place_widget_via_matrix(self._private.widget, m, width, height) }
|
||||
end
|
||||
|
||||
-- Fit this layout into the given area
|
||||
function mirror:fit(context, ...)
|
||||
if not self._private.widget then
|
||||
return 0, 0
|
||||
end
|
||||
return base.fit_widget(self, context, self._private.widget, ...)
|
||||
end
|
||||
|
||||
--- The widget to be reflected.
|
||||
-- @property widget
|
||||
-- @tparam widget widget The widget
|
||||
|
||||
function mirror:set_widget(widget)
|
||||
if widget then
|
||||
base.check_widget(widget)
|
||||
end
|
||||
self._private.widget = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
function mirror:get_widget()
|
||||
return self._private.widget
|
||||
end
|
||||
|
||||
--- Get the number of children element
|
||||
-- @treturn table The children
|
||||
function mirror:get_children()
|
||||
return {self._private.widget}
|
||||
end
|
||||
|
||||
--- Replace the layout children
|
||||
-- This layout only accept one children, all others will be ignored
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function mirror:set_children(children)
|
||||
self:set_widget(children[1])
|
||||
end
|
||||
|
||||
--- Reset this layout. The widget will be removed and the axes reset.
|
||||
function mirror:reset()
|
||||
self._private.horizontal = false
|
||||
self._private.vertical = false
|
||||
self:set_widget(nil)
|
||||
end
|
||||
|
||||
function mirror:set_reflection(reflection)
|
||||
if type(reflection) ~= 'table' then
|
||||
error("Invalid type of reflection for mirror layout: " ..
|
||||
type(reflection) .. " (should be a table)")
|
||||
end
|
||||
for _, ref in ipairs({"horizontal", "vertical"}) do
|
||||
if reflection[ref] ~= nil then
|
||||
self._private[ref] = reflection[ref]
|
||||
end
|
||||
end
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Get the reflection of this mirror layout.
|
||||
-- @property reflection
|
||||
-- @param table reflection A table of booleans with the keys "horizontal", "vertical".
|
||||
-- @param boolean reflection.horizontal
|
||||
-- @param boolean reflection.vertical
|
||||
|
||||
function mirror:get_reflection()
|
||||
return { horizontal = self._private.horizontal, vertical = self._private.vertical }
|
||||
end
|
||||
|
||||
--- Returns a new mirror container.
|
||||
-- A mirror container mirrors a given widget. Use
|
||||
-- `:set_widget()` to set the widget and
|
||||
-- `:set_horizontal()` and `:set_vertical()` for the direction.
|
||||
-- horizontal and vertical are by default false which doesn't change anything.
|
||||
-- @param[opt] widget The widget to display.
|
||||
-- @param[opt] reflection A table describing the reflection to apply.
|
||||
-- @treturn table A new mirror container
|
||||
-- @function wibox.container.mirror
|
||||
local function new(widget, reflection)
|
||||
local ret = base.make_widget(nil, nil, {enable_properties = true})
|
||||
ret._private.horizontal = false
|
||||
ret._private.vertical = false
|
||||
|
||||
util.table.crush(ret, mirror, true)
|
||||
|
||||
ret:set_widget(widget)
|
||||
ret:set_reflection(reflection or {})
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function mirror.mt:__call(...)
|
||||
return new(...)
|
||||
end
|
||||
|
||||
--@DOC_widget_COMMON@
|
||||
|
||||
--@DOC_object_COMMON@
|
||||
|
||||
return setmetatable(mirror, mirror.mt)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -0,0 +1,159 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- A container rotating the conained widget by 90 degrees.
|
||||
--
|
||||
--@DOC_wibox_container_defaults_rotate_EXAMPLE@
|
||||
-- @author Uli Schlachter
|
||||
-- @copyright 2010 Uli Schlachter
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.container.rotate
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local error = error
|
||||
local pi = math.pi
|
||||
local setmetatable = setmetatable
|
||||
local tostring = tostring
|
||||
local base = require("wibox.widget.base")
|
||||
local matrix = require("gears.matrix")
|
||||
local util = require("awful.util")
|
||||
|
||||
local rotate = { mt = {} }
|
||||
|
||||
local function transform(layout, width, height)
|
||||
local dir = layout:get_direction()
|
||||
if dir == "east" or dir == "west" then
|
||||
return height, width
|
||||
end
|
||||
return width, height
|
||||
end
|
||||
|
||||
-- Layout this layout
|
||||
function rotate:layout(_, width, height)
|
||||
if not self._private.widget or not self._private.widget._private.visible then
|
||||
return
|
||||
end
|
||||
|
||||
local dir = self:get_direction()
|
||||
|
||||
local m = matrix.identity
|
||||
if dir == "west" then
|
||||
m = m:rotate(pi / 2)
|
||||
m = m:translate(0, -width)
|
||||
elseif dir == "south" then
|
||||
m = m:rotate(pi)
|
||||
m = m:translate(-width, -height)
|
||||
elseif dir == "east" then
|
||||
m = m:rotate(3 * pi / 2)
|
||||
m = m:translate(-height, 0)
|
||||
end
|
||||
|
||||
-- Since we rotated, we might have to swap width and height.
|
||||
-- transform() does that for us.
|
||||
return { base.place_widget_via_matrix(self._private.widget, m, transform(self, width, height)) }
|
||||
end
|
||||
|
||||
-- Fit this layout into the given area
|
||||
function rotate:fit(context, width, height)
|
||||
if not self._private.widget then
|
||||
return 0, 0
|
||||
end
|
||||
return transform(self, base.fit_widget(self, context, self._private.widget, transform(self, width, height)))
|
||||
end
|
||||
|
||||
--- The widget to be rotated.
|
||||
-- @property widget
|
||||
-- @tparam widget widget The widget
|
||||
|
||||
function rotate:set_widget(widget)
|
||||
if widget then
|
||||
base.check_widget(widget)
|
||||
end
|
||||
self._private.widget = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
function rotate:get_widget()
|
||||
return self._private.widget
|
||||
end
|
||||
|
||||
--- Get the number of children element
|
||||
-- @treturn table The children
|
||||
function rotate:get_children()
|
||||
return {self._private.widget}
|
||||
end
|
||||
|
||||
--- Replace the layout children
|
||||
-- This layout only accept one children, all others will be ignored
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function rotate:set_children(children)
|
||||
self:set_widget(children[1])
|
||||
end
|
||||
|
||||
--- Reset this layout. The widget will be removed and the rotation reset.
|
||||
function rotate:reset()
|
||||
self._private.direction = nil
|
||||
self:set_widget(nil)
|
||||
end
|
||||
|
||||
--@DOC_widget_COMMON@
|
||||
|
||||
--@DOC_object_COMMON@
|
||||
|
||||
--- The direction of this rotating container.
|
||||
-- Valid values are:
|
||||
--
|
||||
-- * *north*
|
||||
-- * *east*
|
||||
-- * *south*
|
||||
-- * *north*
|
||||
--
|
||||
--@DOC_wibox_container_rotate_angle_EXAMPLE@
|
||||
-- @property direction
|
||||
-- @tparam string dir The direction
|
||||
|
||||
function rotate:set_direction(dir)
|
||||
local allowed = {
|
||||
north = true,
|
||||
east = true,
|
||||
south = true,
|
||||
west = true
|
||||
}
|
||||
|
||||
if not allowed[dir] then
|
||||
error("Invalid direction for rotate layout: " .. tostring(dir))
|
||||
end
|
||||
|
||||
self._private.direction = dir
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Get the direction of this rotating layout
|
||||
function rotate:get_direction()
|
||||
return self._private.direction or "north"
|
||||
end
|
||||
|
||||
--- Returns a new rotate container.
|
||||
-- A rotate container rotates a given widget. Use
|
||||
-- :set_widget() to set the widget and :set_direction() for the direction.
|
||||
-- The default direction is "north" which doesn't change anything.
|
||||
-- @param[opt] widget The widget to display.
|
||||
-- @param[opt] dir The direction to rotate to.
|
||||
-- @treturn table A new rotate container.
|
||||
-- @function wibox.container.rotate
|
||||
local function new(widget, dir)
|
||||
local ret = base.make_widget(nil, nil, {enable_properties = true})
|
||||
|
||||
util.table.crush(ret, rotate, true)
|
||||
|
||||
ret:set_widget(widget)
|
||||
ret:set_direction(dir or "north")
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function rotate.mt:__call(...)
|
||||
return new(...)
|
||||
end
|
||||
|
||||
return setmetatable(rotate, rotate.mt)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -0,0 +1,519 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- @author Uli Schlachter (based on ideas from Saleur Geoffrey)
|
||||
-- @copyright 2015 Uli Schlachter
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.container.scroll
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local cache = require("gears.cache")
|
||||
local timer = require("gears.timer")
|
||||
local hierarchy = require("wibox.hierarchy")
|
||||
local base = require("wibox.widget.base")
|
||||
local lgi = require("lgi")
|
||||
local GLib = lgi.GLib
|
||||
|
||||
local scroll = {}
|
||||
local scroll_mt = { __index = scroll }
|
||||
local _need_scroll_redraw
|
||||
|
||||
-- "Strip" a context so that we can use it for our own drawing
|
||||
local function cleanup_context(context)
|
||||
local skip = { wibox = true, drawable = true, client = true, position = true }
|
||||
local res = {}
|
||||
for k, v in pairs(context) do
|
||||
if not skip[k] then
|
||||
res[k] = v
|
||||
end
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
-- Create a hierarchy (and some more stuff) for drawing the given widget. This
|
||||
-- allows "some stuff" to be re-used instead of re-created all the time.
|
||||
local hierarchy_cache = cache.new(function(context, widget, width, height)
|
||||
context = cleanup_context(context)
|
||||
local layouts = setmetatable({}, { __mode = "k" })
|
||||
|
||||
-- Create a widget hierarchy and update when needed
|
||||
local hier
|
||||
local function do_pending_updates(layout)
|
||||
layouts[layout] = true
|
||||
hier:update(context, widget, width, height, nil)
|
||||
end
|
||||
local function emit(signal)
|
||||
-- Make the scroll layouts redraw
|
||||
for w in pairs(layouts) do
|
||||
w:emit_signal(signal)
|
||||
end
|
||||
end
|
||||
local function redraw_callback()
|
||||
emit("widget::redraw_needed")
|
||||
end
|
||||
local function layout_callback()
|
||||
emit("widget::redraw_needed")
|
||||
emit("widget::layout_changed")
|
||||
end
|
||||
hier = hierarchy.new(context, widget, width, height, redraw_callback, layout_callback, nil)
|
||||
|
||||
return hier, do_pending_updates, context
|
||||
end)
|
||||
|
||||
--- Calculate all the information needed for scrolling.
|
||||
-- @param self The instance of the scrolling layout.
|
||||
-- @param context A widget context under which we are fit/drawn.
|
||||
-- @param width The available width
|
||||
-- @param height The available height
|
||||
-- @return A table with the following entries
|
||||
-- @field fit_width The width that should be returned from :fit
|
||||
-- @field fit_height The height that should be returned from :fit
|
||||
-- @field surface_width The width for showing the child widget
|
||||
-- @field surface_height The height for showing the child widget
|
||||
-- @field first_x The x offset for drawing the child the first time
|
||||
-- @field first_y The y offset for drawing the child the first time
|
||||
-- @field[opt] second_x The x offset for drawing the child the second time
|
||||
-- @field[opt] second_y The y offset for drawing the child the second time
|
||||
-- @field hierarchy The wibox.hierarchy instance representing "everything"
|
||||
-- @field context The widget context for drawing the hierarchy
|
||||
local function calculate_info(self, context, width, height)
|
||||
local result = {}
|
||||
assert(self._private.widget)
|
||||
|
||||
-- First, get the size of the widget (and the size of extra space)
|
||||
local surface_width, surface_height = width, height
|
||||
local extra_width, extra_height, extra = 0, 0, self._private.expand and self._private.extra_space or 0
|
||||
local w, h
|
||||
if self._private.dir == "h" then
|
||||
w, h = base.fit_widget(self, context, self._private.widget, self._private.space_for_scrolling, height)
|
||||
surface_width = w
|
||||
extra_width = extra
|
||||
else
|
||||
w, h = base.fit_widget(self, context, self._private.widget, width, self._private.space_for_scrolling)
|
||||
surface_height = h
|
||||
extra_height = extra
|
||||
end
|
||||
result.fit_width, result.fit_height = w, h
|
||||
if self._private.dir == "h" then
|
||||
if self._private.max_size then
|
||||
result.fit_width = math.min(w, self._private.max_size)
|
||||
end
|
||||
else
|
||||
if self._private.max_size then
|
||||
result.fit_height = math.min(h, self._private.max_size)
|
||||
end
|
||||
end
|
||||
if w > width or h > height then
|
||||
-- There is less space available than we need, we have to scroll
|
||||
_need_scroll_redraw(self)
|
||||
|
||||
surface_width, surface_height = surface_width + extra_width, surface_height + extra_height
|
||||
|
||||
local x, y = 0, 0
|
||||
local function get_scroll_offset(size, visible_size)
|
||||
return self._private.step_function(self._private.timer:elapsed(), size, visible_size, self._private.speed, self._private.extra_space)
|
||||
end
|
||||
if self._private.dir == "h" then
|
||||
x = -get_scroll_offset(surface_width - extra, width)
|
||||
else
|
||||
y = -get_scroll_offset(surface_height - extra, height)
|
||||
end
|
||||
result.first_x, result.first_y = x, y
|
||||
-- Was the extra space already included elsewhere?
|
||||
local extra_spacer = self._private.expand and 0 or self._private.extra_space
|
||||
if self._private.dir == "h" then
|
||||
x = x + surface_width + extra_spacer
|
||||
else
|
||||
y = y + surface_height + extra_spacer
|
||||
end
|
||||
result.second_x, result.second_y = x, y
|
||||
else
|
||||
result.first_x, result.first_y = 0, 0
|
||||
end
|
||||
result.surface_width, result.surface_height = surface_width, surface_height
|
||||
|
||||
-- Get the hierarchy and subscribe ourselves to updates
|
||||
local hier, do_pending_updates, ctx = hierarchy_cache:get(context,
|
||||
self._private.widget, surface_width, surface_height)
|
||||
result.hierarchy = hier
|
||||
result.context = ctx
|
||||
do_pending_updates(self)
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
-- Draw this scrolling layout.
|
||||
-- @param context The context in which we are drawn.
|
||||
-- @param cr The cairo context to draw to.
|
||||
-- @param width The available width.
|
||||
-- @param height The available height.
|
||||
function scroll:draw(context, cr, width, height)
|
||||
if not self._private.widget then
|
||||
return
|
||||
end
|
||||
|
||||
local info = calculate_info(self, context, width, height)
|
||||
|
||||
-- Draw the first instance of the child
|
||||
cr:save()
|
||||
cr:translate(info.first_x, info.first_y)
|
||||
cr:rectangle(0, 0, info.surface_width, info.surface_height)
|
||||
cr:clip()
|
||||
info.hierarchy:draw(info.context, cr)
|
||||
cr:restore()
|
||||
|
||||
-- If there is one, draw the second instance (same code as above, minus the
|
||||
-- clip)
|
||||
if info.second_x and info.second_y then
|
||||
cr:translate(info.second_x, info.second_y)
|
||||
cr:rectangle(0, 0, info.surface_width, info.surface_height)
|
||||
cr:clip()
|
||||
info.hierarchy:draw(info.context, cr)
|
||||
end
|
||||
end
|
||||
|
||||
-- Fit the scroll layout into the given space.
|
||||
-- @param context The context in which we are fit.
|
||||
-- @param width The available width.
|
||||
-- @param height The available height.
|
||||
function scroll:fit(context, width, height)
|
||||
if not self._private.widget then
|
||||
return 0, 0
|
||||
end
|
||||
local info = calculate_info(self, context, width, height)
|
||||
return info.fit_width, info.fit_height
|
||||
end
|
||||
|
||||
-- Internal function used for triggering redraws for scrolling.
|
||||
-- The purpose is to start a timer for redrawing the widget for scrolling.
|
||||
-- Redrawing works by simply emitting the `widget::redraw_needed` signal.
|
||||
-- Pausing is implemented in this function: We just don't start a timer.
|
||||
-- This function must be idempotent (calling it multiple times right after
|
||||
-- another does not make a difference).
|
||||
_need_scroll_redraw = function(self)
|
||||
if not self._private.paused and not self._private.scroll_timer then
|
||||
self._private.scroll_timer = timer.start_new(1 / self._private.fps, function()
|
||||
self._private.scroll_timer = nil
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
--- Pause the scrolling animation.
|
||||
-- @see continue
|
||||
function scroll:pause()
|
||||
if self._private.paused then
|
||||
return
|
||||
end
|
||||
self._private.paused = true
|
||||
self._private.timer:stop()
|
||||
end
|
||||
|
||||
--- Continue the scrolling animation.
|
||||
-- @see pause
|
||||
function scroll:continue()
|
||||
if not self._private.paused then
|
||||
return
|
||||
end
|
||||
self._private.paused = false
|
||||
self._private.timer:continue()
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Reset the scrolling state to its initial condition.
|
||||
-- For must scroll step functions, the effect of this function should be to
|
||||
-- display the widget without any scrolling applied.
|
||||
-- This function does not undo the effect of @{pause}.
|
||||
function scroll:reset_scrolling()
|
||||
self._private.timer:start()
|
||||
if self._private.paused then
|
||||
self._private.timer:stop()
|
||||
end
|
||||
end
|
||||
|
||||
--- Set the direction in which this widget scroll.
|
||||
-- @param dir Either "h" for horizontal scrolling or "v" for vertical scrolling
|
||||
function scroll:set_direction(dir)
|
||||
if dir == self._private.dir then
|
||||
return
|
||||
end
|
||||
if dir ~= "h" and dir ~= "v" then
|
||||
error("Invalid direction, can only be 'h' or 'v'")
|
||||
end
|
||||
self._private.dir = dir
|
||||
self:emit_signal("widget::layout_changed")
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- The widget to be scrolled.
|
||||
-- @property widget
|
||||
-- @tparam widget widget The widget
|
||||
|
||||
function scroll:set_widget(widget)
|
||||
if widget == self._private.widget then
|
||||
return
|
||||
end
|
||||
if widget then
|
||||
base.check_widget(widget)
|
||||
end
|
||||
self._private.widget = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
function scroll:get_widget()
|
||||
return self._private.widget
|
||||
end
|
||||
|
||||
--- Get the number of children element
|
||||
-- @treturn table The children
|
||||
function scroll:get_children()
|
||||
return {self._private.widget}
|
||||
end
|
||||
|
||||
--- Replace the layout children
|
||||
-- This layout only accept one children, all others will be ignored
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function scroll:set_children(children)
|
||||
self:set_widget(children[1])
|
||||
end
|
||||
|
||||
--- Specify the expand mode that is used for extra space.
|
||||
-- @tparam boolean expand If true, the widget is expanded to include the extra
|
||||
-- space. If false, the extra space is simply left empty.
|
||||
-- @see set_extra_space
|
||||
function scroll:set_expand(expand)
|
||||
if expand == self._private.expand then
|
||||
return
|
||||
end
|
||||
self._private.expand = expand
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set the number of frames per second that this widget should draw.
|
||||
-- @tparam number fps The number of frames per second
|
||||
function scroll:set_fps(fps)
|
||||
if fps == self._private.fps then
|
||||
return
|
||||
end
|
||||
self._private.fps = fps
|
||||
-- No signal needed: If we are scrolling, the next redraw will apply the new
|
||||
-- FPS, else it obviously doesn't make a difference.
|
||||
end
|
||||
|
||||
--- Set the amount of extra space that should be included in the scrolling. This
|
||||
-- extra space will likely be left empty between repetitions of the widgets.
|
||||
-- @tparam number extra_space The amount of extra space
|
||||
-- @see set_expand
|
||||
function scroll:set_extra_space(extra_space)
|
||||
if extra_space == self._private.extra_space then
|
||||
return
|
||||
end
|
||||
self._private.extra_space = extra_space
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set the speed of the scrolling animation. The exact meaning depends on the
|
||||
-- step function that is used, but for the simplest step functions, this will be
|
||||
-- in pixels per second.
|
||||
-- @tparam number speed The speed for the animation
|
||||
function scroll:set_speed(speed)
|
||||
if speed == self._private.speed then
|
||||
return
|
||||
end
|
||||
self._private.speed = speed
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set the maximum size of this widget in the direction set by
|
||||
-- @{set_direction}. If the child widget is smaller than this size, no scrolling
|
||||
-- is done. If the child widget is larger, then only this size will be visible
|
||||
-- and the rest is made visible via scrolling.
|
||||
-- @tparam number max_size The maximum size of this widget or nil for unlimited.
|
||||
function scroll:set_max_size(max_size)
|
||||
if max_size == self._private.max_size then
|
||||
return
|
||||
end
|
||||
self._private.max_size = max_size
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Set the step function that determines the exact behaviour of the scrolling
|
||||
-- animation.
|
||||
-- The step function is called with five arguments:
|
||||
--
|
||||
-- * The time in seconds since the state of the animation
|
||||
-- * The size of the child widget
|
||||
-- * The size of the visible part of the widget
|
||||
-- * The speed of the animation. This should have a linear effect on this
|
||||
-- function's behaviour.
|
||||
-- * The extra space configured by @{set_extra_space}. This was not yet added to
|
||||
-- the size of the child widget, but should likely be added to it in most
|
||||
-- cases.
|
||||
--
|
||||
-- The step function should return a single number. This number is the offset at
|
||||
-- which the widget is drawn and should be between 0 and `size+extra_space`.
|
||||
-- @tparam function step_function A step function.
|
||||
-- @see step_functions
|
||||
function scroll:set_step_function(step_function)
|
||||
-- Call the step functions once to see if it works
|
||||
step_function(0, 42, 10, 10, 5)
|
||||
if step_function == self._private.step_function then
|
||||
return
|
||||
end
|
||||
self._private.step_function = step_function
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set an upper limit for the space for scrolling.
|
||||
-- This restricts the child widget's maximal size.
|
||||
-- @tparam number space_for_scrolling The space for scrolling
|
||||
function scroll:set_space_for_scrolling(space_for_scrolling)
|
||||
if space_for_scrolling == self._private.space_for_scrolling then
|
||||
return
|
||||
end
|
||||
self._private.space_for_scrolling = space_for_scrolling
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
local function get_layout(dir, widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling)
|
||||
local ret = base.make_widget(nil, nil, {enable_properties = true})
|
||||
|
||||
ret._priavte.paused = false
|
||||
ret._private.timer = GLib.Timer()
|
||||
ret._private.scroll_timer = nil
|
||||
|
||||
setmetatable(ret, scroll_mt)
|
||||
|
||||
ret:set_direction(dir)
|
||||
ret:set_widget(widget)
|
||||
ret:set_fps(fps or 20)
|
||||
ret:set_speed(speed or 10)
|
||||
ret:set_extra_space(extra_space or 0)
|
||||
ret:set_expand(expand)
|
||||
ret:set_max_size(max_size)
|
||||
ret:set_step_function(step_function or scroll.step_functions.linear_increase)
|
||||
ret:set_space_for_scrolling(space_for_scrolling or 2^1024)
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
--- Get a new horizontal scrolling container.
|
||||
-- @param[opt] widget The widget that should be scrolled
|
||||
-- @param[opt=20] fps The number of frames per second
|
||||
-- @param[opt=10] speed The speed of the animation
|
||||
-- @param[opt=0] extra_space The amount of extra space to include
|
||||
-- @tparam[opt=false] boolean expand Should the widget be expanded to include the
|
||||
-- extra space?
|
||||
-- @param[opt] max_size The maximum size of the child widget
|
||||
-- @param[opt=step_functions.linear_increase] step_function The step function to be used
|
||||
-- @param[opt=2^1024] space_for_scrolling The space for scrolling
|
||||
function scroll.horizontal(widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling)
|
||||
return get_layout("h", widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling)
|
||||
end
|
||||
|
||||
--- Get a new vertical scrolling container.
|
||||
-- @param[opt] widget The widget that should be scrolled
|
||||
-- @param[opt=20] fps The number of frames per second
|
||||
-- @param[opt=10] speed The speed of the animation
|
||||
-- @param[opt=0] extra_space The amount of extra space to include
|
||||
-- @tparam[opt=false] boolean expand Should the widget be expanded to include the
|
||||
-- extra space?
|
||||
-- @param[opt] max_size The maximum size of the child widget
|
||||
-- @param[opt=step_functions.linear_increase] step_function The step function to be used
|
||||
-- @param[opt=2^1024] space_for_scrolling The space for scrolling
|
||||
function scroll.vertical(widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling)
|
||||
return get_layout("v", widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling)
|
||||
end
|
||||
|
||||
--- A selection of step functions
|
||||
-- @see set_step_function
|
||||
scroll.step_functions = {}
|
||||
|
||||
--- A step function that scrolls the widget in an increasing direction with
|
||||
-- constant speed.
|
||||
function scroll.step_functions.linear_increase(elapsed, size, _, speed, extra_space)
|
||||
return (elapsed * speed) % (size + extra_space)
|
||||
end
|
||||
|
||||
--- A step function that scrolls the widget in an decreasing direction with
|
||||
-- constant speed.
|
||||
function scroll.step_functions.linear_decrease(elapsed, size, _, speed, extra_space)
|
||||
return (-elapsed * speed) % (size + extra_space)
|
||||
end
|
||||
|
||||
--- A step function that scrolls the widget to its end and back to its
|
||||
-- beginning, then back to its end, etc. The speed is constant.
|
||||
function scroll.step_functions.linear_back_and_forth(elapsed, size, visible_size, speed)
|
||||
local state = ((elapsed * speed) % (2 * size)) / size
|
||||
state = state <= 1 and state or 2 - state
|
||||
return (size - visible_size) * state
|
||||
end
|
||||
|
||||
--- A step function that scrolls the widget to its end and back to its
|
||||
-- beginning, then back to its end, etc. The speed is null at the ends and
|
||||
-- maximal in the middle.
|
||||
function scroll.step_functions.nonlinear_back_and_forth(elapsed, size, visible_size, speed)
|
||||
local state = ((elapsed * speed) % (2 * size)) / size
|
||||
local negate = false
|
||||
if state > 1 then
|
||||
negate = true
|
||||
state = state - 1
|
||||
end
|
||||
if state < 1/3 then
|
||||
-- In the first 1/3rd of time, do a quadratic increase in speed
|
||||
state = 2 * state * state
|
||||
elseif state < 2/3 then
|
||||
-- In the center, do a linear increase. That means we need:
|
||||
-- If state is 1/3, result is 2/9 = 2 * 1/3 * 1/3
|
||||
-- If state is 2/3, result is 7/9 = 1 - 2 * (1 - 2/3) * (1 - 2/3)
|
||||
state = 5/3*state - 3/9
|
||||
else
|
||||
-- In the last 1/3rd of time, do a quadratic decrease in speed
|
||||
state = 1 - 2 * (1 - state) * (1 - state)
|
||||
end
|
||||
if negate then
|
||||
state = 1 - state
|
||||
end
|
||||
return (size - visible_size) * state
|
||||
end
|
||||
|
||||
--- A step function that scrolls the widget to its end and back to its
|
||||
-- beginning, then back to its end, etc. The speed is null at the ends and
|
||||
-- maximal in the middle. At both ends the widget stands still for a moment.
|
||||
function scroll.step_functions.waiting_nonlinear_back_and_forth(elapsed, size, visible_size, speed)
|
||||
local state = ((elapsed * speed) % (2 * size)) / size
|
||||
local negate = false
|
||||
if state > 1 then
|
||||
negate = true
|
||||
state = state - 1
|
||||
end
|
||||
if state < 1/5 or state > 4/5 then
|
||||
-- One fifth of time, nothing moves
|
||||
state = state < 1/5 and 0 or 1
|
||||
else
|
||||
state = (state - 1/5) * 5/3
|
||||
if state < 1/3 then
|
||||
-- In the first 1/3rd of time, do a quadratic increase in speed
|
||||
state = 2 * state * state
|
||||
elseif state < 2/3 then
|
||||
-- In the center, do a linear increase. That means we need:
|
||||
-- If state is 1/3, result is 2/9 = 2 * 1/3 * 1/3
|
||||
-- If state is 2/3, result is 7/9 = 1 - 2 * (1 - 2/3) * (1 - 2/3)
|
||||
state = 5/3*state - 3/9
|
||||
else
|
||||
-- In the last 1/3rd of time, do a quadratic decrease in speed
|
||||
state = 1 - 2 * (1 - state) * (1 - state)
|
||||
end
|
||||
end
|
||||
if negate then
|
||||
state = 1 - state
|
||||
end
|
||||
return (size - visible_size) * state
|
||||
end
|
||||
|
||||
--@DOC_widget_COMMON@
|
||||
|
||||
--@DOC_object_COMMON@
|
||||
|
||||
return scroll
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -259,7 +259,7 @@ end
|
|||
-- @param cr The cairo context that is used for drawing.
|
||||
function hierarchy:draw(context, cr)
|
||||
local widget = self:get_widget()
|
||||
if not widget.visible then
|
||||
if not widget._private.visible then
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -272,7 +272,7 @@ function hierarchy:draw(context, cr)
|
|||
|
||||
-- Draw if needed
|
||||
if not empty_clip(cr) then
|
||||
local opacity = widget.opacity
|
||||
local opacity = widget:get_opacity()
|
||||
local function call(func, extra_arg1, extra_arg2)
|
||||
if not func then return end
|
||||
if not extra_arg2 then
|
||||
|
|
|
@ -24,6 +24,7 @@ local base = require("wibox.widget.base")
|
|||
-- wibox
|
||||
local wibox = { mt = {}, object = {} }
|
||||
wibox.layout = require("wibox.layout")
|
||||
wibox.container = require("wibox.container")
|
||||
wibox.widget = require("wibox.widget")
|
||||
wibox.drawable = require("wibox.drawable")
|
||||
wibox.hierarchy = require("wibox.hierarchy")
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
---------------------------------------------------------------------------
|
||||
--
|
||||
--@DOC_wibox_layout_defaults_align_EXAMPLE@
|
||||
-- @author Uli Schlachter
|
||||
-- @copyright 2010 Uli Schlachter
|
||||
-- @release @AWESOME_VERSION@
|
||||
|
@ -14,7 +16,7 @@ local base = require("wibox.widget.base")
|
|||
|
||||
local align = {}
|
||||
|
||||
--- Calculate the layout of an align layout.
|
||||
-- Calculate the layout of an align layout.
|
||||
-- @param context The context in which we are drawn.
|
||||
-- @param width The available width.
|
||||
-- @param height The available height.
|
||||
|
@ -30,7 +32,7 @@ function align:layout(context, width, height)
|
|||
-- allowed.
|
||||
local size_first = 0
|
||||
-- start with all the space given by the parent, subtract as we go along
|
||||
local size_remains = self.dir == "y" and height or width
|
||||
local size_remains = self._private.dir == "y" and height or width
|
||||
-- This is only set & used if expand ~= "inside" and we have second width.
|
||||
-- It contains the size allocated to the second widget.
|
||||
local size_second
|
||||
|
@ -39,84 +41,84 @@ function align:layout(context, width, height)
|
|||
-- if it is, we prioritize the first widget by not doing this block also,
|
||||
-- if the second widget doesn't exist, we will prioritise the first one
|
||||
-- instead
|
||||
if self._expand ~= "inside" and self.second then
|
||||
local w, h = base.fit_widget(self, context, self.second, width, height)
|
||||
size_second = self.dir == "y" and h or w
|
||||
if self._private.expand ~= "inside" and self._private.second then
|
||||
local w, h = base.fit_widget(self, context, self._private.second, width, height)
|
||||
size_second = self._private.dir == "y" and h or w
|
||||
-- if all the space is taken, skip the rest, and draw just the middle
|
||||
-- widget
|
||||
if size_second >= size_remains then
|
||||
return { base.place_widget_at(self.second, 0, 0, width, height) }
|
||||
return { base.place_widget_at(self._private.second, 0, 0, width, height) }
|
||||
else
|
||||
-- the middle widget is sized first, the outside widgets are given
|
||||
-- the remaining space if available we will draw later
|
||||
size_remains = floor((size_remains - size_second) / 2)
|
||||
end
|
||||
end
|
||||
if self.first then
|
||||
if self._private.first then
|
||||
local w, h, _ = width, height, nil
|
||||
-- we use the fit function for the "inside" and "none" modes, but
|
||||
-- ignore it for the "outside" mode, which will force it to expand
|
||||
-- into the remaining space
|
||||
if self._expand ~= "outside" then
|
||||
if self.dir == "y" then
|
||||
_, h = base.fit_widget(self, context, self.first, width, size_remains)
|
||||
if self._private.expand ~= "outside" then
|
||||
if self._private.dir == "y" then
|
||||
_, h = base.fit_widget(self, context, self._private.first, width, size_remains)
|
||||
size_first = h
|
||||
-- for "inside", the third widget will get a chance to use the
|
||||
-- remaining space, then the middle widget. For "none" we give
|
||||
-- the third widget the remaining space if there was no second
|
||||
-- widget to take up any space (as the first if block is skipped
|
||||
-- if this is the case)
|
||||
if self._expand == "inside" or not self.second then
|
||||
if self._private.expand == "inside" or not self._private.second then
|
||||
size_remains = size_remains - h
|
||||
end
|
||||
else
|
||||
w, _ = base.fit_widget(self, context, self.first, size_remains, height)
|
||||
w, _ = base.fit_widget(self, context, self._private.first, size_remains, height)
|
||||
size_first = w
|
||||
if self._expand == "inside" or not self.second then
|
||||
if self._private.expand == "inside" or not self._private.second then
|
||||
size_remains = size_remains - w
|
||||
end
|
||||
end
|
||||
else
|
||||
if self.dir == "y" then
|
||||
if self._private.dir == "y" then
|
||||
h = size_remains
|
||||
else
|
||||
w = size_remains
|
||||
end
|
||||
end
|
||||
table.insert(result, base.place_widget_at(self.first, 0, 0, w, h))
|
||||
table.insert(result, base.place_widget_at(self._private.first, 0, 0, w, h))
|
||||
end
|
||||
-- size_remains will be <= 0 if first used all the space
|
||||
if self.third and size_remains > 0 then
|
||||
if self._private.third and size_remains > 0 then
|
||||
local w, h, _ = width, height, nil
|
||||
if self._expand ~= "outside" then
|
||||
if self.dir == "y" then
|
||||
_, h = base.fit_widget(self, context, self.third, width, size_remains)
|
||||
if self._private.expand ~= "outside" then
|
||||
if self._private.dir == "y" then
|
||||
_, h = base.fit_widget(self, context, self._private.third, width, size_remains)
|
||||
-- give the middle widget the rest of the space for "inside" mode
|
||||
if self._expand == "inside" then
|
||||
if self._private.expand == "inside" then
|
||||
size_remains = size_remains - h
|
||||
end
|
||||
else
|
||||
w, _ = base.fit_widget(self, context, self.third, size_remains, height)
|
||||
if self._expand == "inside" then
|
||||
w, _ = base.fit_widget(self, context, self._private.third, size_remains, height)
|
||||
if self._private.expand == "inside" then
|
||||
size_remains = size_remains - w
|
||||
end
|
||||
end
|
||||
else
|
||||
if self.dir == "y" then
|
||||
if self._private.dir == "y" then
|
||||
h = size_remains
|
||||
else
|
||||
w = size_remains
|
||||
end
|
||||
end
|
||||
local x, y = width - w, height - h
|
||||
table.insert(result, base.place_widget_at(self.third, x, y, w, h))
|
||||
table.insert(result, base.place_widget_at(self._private.third, x, y, w, h))
|
||||
end
|
||||
-- here we either draw the second widget in the space set aside for it
|
||||
-- in the beginning, or in the remaining space, if it is "inside"
|
||||
if self.second and size_remains > 0 then
|
||||
if self._private.second and size_remains > 0 then
|
||||
local x, y, w, h = 0, 0, width, height
|
||||
if self._expand == "inside" then
|
||||
if self.dir == "y" then
|
||||
if self._private.expand == "inside" then
|
||||
if self._private.dir == "y" then
|
||||
h = size_remains
|
||||
x, y = 0, size_first
|
||||
else
|
||||
|
@ -125,62 +127,76 @@ function align:layout(context, width, height)
|
|||
end
|
||||
else
|
||||
local _
|
||||
if self.dir == "y" then
|
||||
_, h = base.fit_widget(self, context, self.second, width, size_second)
|
||||
if self._private.dir == "y" then
|
||||
_, h = base.fit_widget(self, context, self._private.second, width, size_second)
|
||||
y = floor( (height - h)/2 )
|
||||
else
|
||||
w, _ = base.fit_widget(self, context, self.second, size_second, height)
|
||||
w, _ = base.fit_widget(self, context, self._private.second, size_second, height)
|
||||
x = floor( (width -w)/2 )
|
||||
end
|
||||
end
|
||||
table.insert(result, base.place_widget_at(self.second, x, y, w, h))
|
||||
table.insert(result, base.place_widget_at(self._private.second, x, y, w, h))
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
--- Set the layout's first widget. This is the widget that is at the left/top
|
||||
--- Set the layout's first widget.
|
||||
-- This is the widget that is at the left/top
|
||||
-- @property first
|
||||
|
||||
function align:set_first(widget)
|
||||
if self.first == widget then
|
||||
if self._private.first == widget then
|
||||
return
|
||||
end
|
||||
self.first = widget
|
||||
self._private.first = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Set the layout's second widget. This is the centered one.
|
||||
-- @property second
|
||||
|
||||
function align:set_second(widget)
|
||||
if self.second == widget then
|
||||
if self._private.second == widget then
|
||||
return
|
||||
end
|
||||
self.second = widget
|
||||
self._private.second = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Set the layout's third widget. This is the widget that is at the right/bottom
|
||||
--- Set the layout's third widget.
|
||||
-- This is the widget that is at the right/bottom
|
||||
-- @property third
|
||||
|
||||
function align:set_third(widget)
|
||||
if self.third == widget then
|
||||
if self._private.third == widget then
|
||||
return
|
||||
end
|
||||
self.third = widget
|
||||
self._private.third = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Get all children of this layout
|
||||
-- @treturn table a list of all widgets
|
||||
function align:get_children()
|
||||
return util.from_sparse {self.first, self.second, self.third}
|
||||
for _, prop in ipairs {"first", "second", "third", "expand" } do
|
||||
align["get_"..prop] = function(self)
|
||||
return self._private[prop]
|
||||
end
|
||||
end
|
||||
|
||||
--- All direct children of this layout.
|
||||
-- This can be used to replace all 3 widgets at once.
|
||||
-- @treturn table a list of all widgets
|
||||
-- @property children
|
||||
|
||||
function align:get_children()
|
||||
return util.from_sparse {self._private.first, self._private.second, self._private.third}
|
||||
end
|
||||
|
||||
--- Replace the layout children
|
||||
-- This layout only accept three children, all others will be ignored
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function align:set_children(children)
|
||||
self:set_first(children[1])
|
||||
self:set_second(children[2])
|
||||
self:set_third(children[3])
|
||||
end
|
||||
|
||||
--- Fit the align layout into the given space. The align layout will
|
||||
-- Fit the align layout into the given space. The align layout will
|
||||
-- ask for the sum of the sizes of its sub-widgets in its direction
|
||||
-- and the largest sized sub widget in the other direction.
|
||||
-- @param context The context in which we are fit.
|
||||
|
@ -190,18 +206,18 @@ function align:fit(context, orig_width, orig_height)
|
|||
local used_in_dir = 0
|
||||
local used_in_other = 0
|
||||
|
||||
for _, v in pairs{self.first, self.second, self.third} do
|
||||
for _, v in pairs{self._private.first, self._private.second, self._private.third} do
|
||||
local w, h = base.fit_widget(self, context, v, orig_width, orig_height)
|
||||
|
||||
local max = self.dir == "y" and w or h
|
||||
local max = self._private.dir == "y" and w or h
|
||||
if max > used_in_other then
|
||||
used_in_other = max
|
||||
end
|
||||
|
||||
used_in_dir = used_in_dir + (self.dir == "y" and h or w)
|
||||
used_in_dir = used_in_dir + (self._private.dir == "y" and h or w)
|
||||
end
|
||||
|
||||
if self.dir == "y" then
|
||||
if self._private.dir == "y" then
|
||||
return used_in_other, used_in_dir
|
||||
end
|
||||
return used_in_dir, used_in_other
|
||||
|
@ -221,11 +237,13 @@ end
|
|||
-- * "none" - All widgets are sized using their fit function, drawn to only the
|
||||
-- returned space, or remaining space, whichever is smaller. Center widget
|
||||
-- gets priority.
|
||||
-- @property expand
|
||||
|
||||
function align:set_expand(mode)
|
||||
if mode == "none" or mode == "outside" then
|
||||
self._expand = mode
|
||||
self._private.expand = mode
|
||||
else
|
||||
self._expand = "inside"
|
||||
self._private.expand = "inside"
|
||||
end
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
@ -238,12 +256,12 @@ function align:reset()
|
|||
end
|
||||
|
||||
local function get_layout(dir, first, second, third)
|
||||
local ret = base.make_widget()
|
||||
ret.dir = dir
|
||||
local ret = base.make_widget(nil, nil, {enable_properties = true})
|
||||
ret._private.dir = dir
|
||||
|
||||
for k, v in pairs(align) do
|
||||
if type(v) == "function" then
|
||||
ret[k] = v
|
||||
rawset(ret, k, v)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -268,9 +286,9 @@ end
|
|||
function align.horizontal(left, middle, right)
|
||||
local ret = get_layout("x", left, middle, right)
|
||||
|
||||
ret.set_left = ret.set_first
|
||||
ret.set_middle = ret.set_second
|
||||
ret.set_right = ret.set_third
|
||||
rawset(ret, "set_left" , ret.set_first )
|
||||
rawset(ret, "set_middle", ret.set_second )
|
||||
rawset(ret, "set_right" , ret.set_third )
|
||||
|
||||
return ret
|
||||
end
|
||||
|
@ -285,13 +303,17 @@ end
|
|||
function align.vertical(top, middle, bottom)
|
||||
local ret = get_layout("y", top, middle, bottom)
|
||||
|
||||
ret.set_top = ret.set_first
|
||||
ret.set_middle = ret.set_second
|
||||
ret.set_bottom = ret.set_third
|
||||
rawset(ret, "set_top" , ret.set_first )
|
||||
rawset(ret, "set_middle", ret.set_second )
|
||||
rawset(ret, "set_bottom", ret.set_third )
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
--@DOC_widget_COMMON@
|
||||
|
||||
--@DOC_object_COMMON@
|
||||
|
||||
return align
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -1,140 +1,18 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- This class has been moved to `wibox.container.`
|
||||
--
|
||||
-- @author Lukáš Hrázký
|
||||
-- @copyright 2012 Lukáš Hrázký
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.layout.constraint
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local pairs = pairs
|
||||
local type = type
|
||||
local setmetatable = setmetatable
|
||||
local base = require("wibox.widget.base")
|
||||
local math = math
|
||||
local util = require("awful.util")
|
||||
|
||||
local constraint = { mt = {} }
|
||||
|
||||
--- Layout a constraint layout
|
||||
function constraint:layout(_, width, height)
|
||||
if self.widget then
|
||||
return { base.place_widget_at(self.widget, 0, 0, width, height) }
|
||||
end
|
||||
end
|
||||
|
||||
--- Fit a constraint layout into the given space
|
||||
function constraint:fit(context, width, height)
|
||||
local w, h
|
||||
if self.widget then
|
||||
w = self._strategy(width, self._width)
|
||||
h = self._strategy(height, self._height)
|
||||
|
||||
w, h = base.fit_widget(self, context, self.widget, w, h)
|
||||
else
|
||||
w, h = 0, 0
|
||||
end
|
||||
|
||||
w = self._strategy(w, self._width)
|
||||
h = self._strategy(h, self._height)
|
||||
|
||||
return w, h
|
||||
end
|
||||
|
||||
--- Set the widget that this layout adds a constraint on.
|
||||
function constraint:set_widget(widget)
|
||||
self.widget = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Get the number of children element
|
||||
-- @treturn table The children
|
||||
function constraint:get_children()
|
||||
return {self.widget}
|
||||
end
|
||||
|
||||
--- Replace the layout children
|
||||
-- This layout only accept one children, all others will be ignored
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function constraint:set_children(children)
|
||||
self:set_widget(children[1])
|
||||
end
|
||||
|
||||
--- Set the strategy to use for the constraining. Valid values are 'max',
|
||||
-- 'min' or 'exact'. Throws an error on invalid values.
|
||||
function constraint:set_strategy(val)
|
||||
local func = {
|
||||
min = function(real_size, limit)
|
||||
return limit and math.max(limit, real_size) or real_size
|
||||
end,
|
||||
max = function(real_size, limit)
|
||||
return limit and math.min(limit, real_size) or real_size
|
||||
end,
|
||||
exact = function(real_size, limit)
|
||||
return limit or real_size
|
||||
end
|
||||
}
|
||||
|
||||
if not func[val] then
|
||||
error("Invalid strategy for constraint layout: " .. tostring(val))
|
||||
end
|
||||
|
||||
self._strategy = func[val]
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Set the maximum width to val. nil for no width limit.
|
||||
function constraint:set_width(val)
|
||||
self._width = val
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Set the maximum height to val. nil for no height limit.
|
||||
function constraint:set_height(val)
|
||||
self._height = val
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Reset this layout. The widget will be unreferenced, strategy set to "max"
|
||||
-- and the constraints set to nil.
|
||||
function constraint:reset()
|
||||
self._width = nil
|
||||
self._height = nil
|
||||
self:set_strategy("max")
|
||||
self:set_widget(nil)
|
||||
end
|
||||
|
||||
--- Returns a new constraint layout. This layout will constraint the size of a
|
||||
-- widget according to the strategy. Note that this will only work for layouts
|
||||
-- that respect the widget's size, eg. fixed layout. In layouts that don't
|
||||
-- (fully) respect widget's requested size, the inner widget still might get
|
||||
-- drawn with a size that does not fit the constraint, eg. in flex layout.
|
||||
-- @param[opt] widget A widget to use.
|
||||
-- @param[opt] strategy How to constraint the size. 'max' (default), 'min' or
|
||||
-- 'exact'.
|
||||
-- @param[opt] width The maximum width of the widget. nil for no limit.
|
||||
-- @param[opt] height The maximum height of the widget. nil for no limit.
|
||||
local function new(widget, strategy, width, height)
|
||||
local ret = base.make_widget()
|
||||
|
||||
for k, v in pairs(constraint) do
|
||||
if type(v) == "function" then
|
||||
ret[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
ret:set_strategy(strategy or "max")
|
||||
ret:set_width(width)
|
||||
ret:set_height(height)
|
||||
|
||||
if widget then
|
||||
ret:set_widget(widget)
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function constraint.mt:__call(...)
|
||||
return new(...)
|
||||
end
|
||||
|
||||
return setmetatable(constraint, constraint.mt)
|
||||
return util.deprecate_class(
|
||||
require("wibox.container.constraint"),
|
||||
"wibox.layout.constraint",
|
||||
"wibox.container.constraint"
|
||||
)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
---------------------------------------------------------------------------
|
||||
--
|
||||
--@DOC_wibox_layout_defaults_fixed_EXAMPLE@
|
||||
-- @author Uli Schlachter
|
||||
-- @copyright 2010 Uli Schlachter
|
||||
-- @release @AWESOME_VERSION@
|
||||
|
@ -21,28 +23,28 @@ local fixed = {}
|
|||
-- @param height The available height.
|
||||
function fixed:layout(context, width, height)
|
||||
local result = {}
|
||||
local pos,spacing = 0, self._spacing
|
||||
local pos,spacing = 0, self._private.spacing
|
||||
|
||||
for k, v in pairs(self.widgets) do
|
||||
for k, v in pairs(self._private.widgets) do
|
||||
local x, y, w, h, _
|
||||
if self.dir == "y" then
|
||||
if self._private.dir == "y" then
|
||||
x, y = 0, pos
|
||||
w, h = width, height - pos
|
||||
if k ~= #self.widgets or not self._fill_space then
|
||||
if k ~= #self._private.widgets or not self._private.fill_space then
|
||||
_, h = base.fit_widget(self, context, v, w, h);
|
||||
end
|
||||
pos = pos + h + spacing
|
||||
else
|
||||
x, y = pos, 0
|
||||
w, h = width - pos, height
|
||||
if k ~= #self.widgets or not self._fill_space then
|
||||
if k ~= #self._private.widgets or not self._private.fill_space then
|
||||
w, _ = base.fit_widget(self, context, v, w, h);
|
||||
end
|
||||
pos = pos + w + spacing
|
||||
end
|
||||
|
||||
if (self.dir == "y" and pos-spacing > height) or
|
||||
(self.dir ~= "y" and pos-spacing > width) then
|
||||
if (self._private.dir == "y" and pos-spacing > height) or
|
||||
(self._private.dir ~= "y" and pos-spacing > width) then
|
||||
break
|
||||
end
|
||||
table.insert(result, base.place_widget_at(v, x, y, w, h))
|
||||
|
@ -58,7 +60,7 @@ function fixed:add(...)
|
|||
assert(args.n > 0, "need at least one widget to add")
|
||||
for i=1, args.n do
|
||||
base.check_widget(args[i])
|
||||
table.insert(self.widgets, args[i])
|
||||
table.insert(self._private.widgets, args[i])
|
||||
end
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
@ -68,9 +70,9 @@ end
|
|||
-- @tparam number index The widget index to remove
|
||||
-- @treturn boolean index If the operation is successful
|
||||
function fixed:remove(index)
|
||||
if not index or index < 1 or index > #self.widgets then return false end
|
||||
if not index or index < 1 or index > #self._private.widgets then return false end
|
||||
|
||||
table.remove(self.widgets, index)
|
||||
table.remove(self._private.widgets, index)
|
||||
|
||||
self:emit_signal("widget::layout_changed")
|
||||
|
||||
|
@ -104,14 +106,10 @@ function fixed:remove_widgets(...)
|
|||
return #args > (recursive and 1 or 0) and ret
|
||||
end
|
||||
|
||||
--- Get all children of this layout
|
||||
-- @treturn table a list of all widgets
|
||||
function fixed:get_children()
|
||||
return self.widgets
|
||||
return self._private.widgets
|
||||
end
|
||||
|
||||
--- Replace the layout children
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function fixed:set_children(children)
|
||||
self:reset()
|
||||
if #children > 0 then
|
||||
|
@ -136,12 +134,12 @@ function fixed:replace_widget(widget, widget2, recursive)
|
|||
end
|
||||
|
||||
function fixed:swap(index1, index2)
|
||||
if not index1 or not index2 or index1 > #self.widgets
|
||||
or index2 > #self.widgets then
|
||||
if not index1 or not index2 or index1 > #self._private.widgets
|
||||
or index2 > #self._private.widgets then
|
||||
return false
|
||||
end
|
||||
|
||||
local widget1, widget2 = self.widgets[index1], self.widgets[index2]
|
||||
local widget1, widget2 = self._private.widgets[index1], self._private.widgets[index2]
|
||||
|
||||
self:set(index1, widget2)
|
||||
self:set(index2, widget1)
|
||||
|
@ -175,11 +173,11 @@ function fixed:swap_widgets(widget1, widget2, recursive)
|
|||
end
|
||||
|
||||
function fixed:set(index, widget2)
|
||||
if (not widget2) or (not self.widgets[index]) then return false end
|
||||
if (not widget2) or (not self._private.widgets[index]) then return false end
|
||||
|
||||
base.check_widget(widget2)
|
||||
|
||||
self.widgets[index] = widget2
|
||||
self._private.widgets[index] = widget2
|
||||
|
||||
self:emit_signal("widget::layout_changed")
|
||||
|
||||
|
@ -191,10 +189,10 @@ end
|
|||
-- @param widget The widget
|
||||
-- @treturn boolean If the operation is successful
|
||||
function fixed:insert(index, widget)
|
||||
if not index or index < 1 or index > #self.widgets + 1 then return false end
|
||||
if not index or index < 1 or index > #self._private.widgets + 1 then return false end
|
||||
|
||||
base.check_widget(widget)
|
||||
table.insert(self.widgets, index, widget)
|
||||
table.insert(self._private.widgets, index, widget)
|
||||
self:emit_signal("widget::layout_changed")
|
||||
|
||||
return true
|
||||
|
@ -208,10 +206,10 @@ function fixed:fit(context, orig_width, orig_height)
|
|||
local width, height = orig_width, orig_height
|
||||
local used_in_dir, used_max = 0, 0
|
||||
|
||||
for _, v in pairs(self.widgets) do
|
||||
for _, v in pairs(self._private.widgets) do
|
||||
local w, h = base.fit_widget(self, context, v, width, height)
|
||||
local in_dir, max
|
||||
if self.dir == "y" then
|
||||
if self._private.dir == "y" then
|
||||
max, in_dir = w, h
|
||||
height = height - in_dir
|
||||
else
|
||||
|
@ -224,7 +222,7 @@ function fixed:fit(context, orig_width, orig_height)
|
|||
used_in_dir = used_in_dir + in_dir
|
||||
|
||||
if width <= 0 or height <= 0 then
|
||||
if self.dir == "y" then
|
||||
if self._private.dir == "y" then
|
||||
used_in_dir = orig_height
|
||||
else
|
||||
used_in_dir = orig_width
|
||||
|
@ -233,36 +231,38 @@ function fixed:fit(context, orig_width, orig_height)
|
|||
end
|
||||
end
|
||||
|
||||
local spacing = self._spacing * (#self.widgets-1)
|
||||
local spacing = self._private.spacing * (#self._private.widgets-1)
|
||||
|
||||
if self.dir == "y" then
|
||||
if self._private.dir == "y" then
|
||||
return used_max, used_in_dir + spacing
|
||||
end
|
||||
return used_in_dir + spacing, used_max
|
||||
end
|
||||
|
||||
function fixed:reset()
|
||||
self.widgets = {}
|
||||
self._private.widgets = {}
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Set the layout's fill_space property. If this property is true, the last
|
||||
-- widget will get all the space that is left. If this is false, the last widget
|
||||
-- won't be handled specially and there can be space left unused.
|
||||
-- @property fill_space
|
||||
|
||||
function fixed:fill_space(val)
|
||||
if self._fill_space ~= val then
|
||||
self._fill_space = not not val
|
||||
if self._private.fill_space ~= val then
|
||||
self._private.fill_space = not not val
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
end
|
||||
|
||||
local function get_layout(dir, widget1, ...)
|
||||
local ret = base.make_widget()
|
||||
local ret = base.make_widget(nil, nil, {enable_properties = true})
|
||||
|
||||
util.table.crush(ret, fixed)
|
||||
util.table.crush(ret, fixed, true)
|
||||
|
||||
ret.dir = dir
|
||||
ret.widgets = {}
|
||||
ret._private.dir = dir
|
||||
ret._private.widgets = {}
|
||||
ret:set_spacing(0)
|
||||
ret:fill_space(false)
|
||||
|
||||
|
@ -292,14 +292,24 @@ function fixed.vertical(...)
|
|||
end
|
||||
|
||||
--- Add spacing between each layout widgets
|
||||
-- @param spacing Spacing between widgets.
|
||||
-- @property spacing
|
||||
-- @tparam number spacing Spacing between widgets.
|
||||
|
||||
function fixed:set_spacing(spacing)
|
||||
if self._spacing ~= spacing then
|
||||
self._spacing = spacing
|
||||
if self._private.spacing ~= spacing then
|
||||
self._private.spacing = spacing
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
end
|
||||
|
||||
function fixed:get_spacing()
|
||||
return self._private.spacing or 0
|
||||
end
|
||||
|
||||
--@DOC_widget_COMMON@
|
||||
|
||||
--@DOC_object_COMMON@
|
||||
|
||||
return fixed
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
---------------------------------------------------------------------------
|
||||
--
|
||||
--@DOC_wibox_layout_defaults_flex_EXAMPLE@
|
||||
-- @author Uli Schlachter
|
||||
-- @copyright 2010 Uli Schlachter
|
||||
-- @release @AWESOME_VERSION@
|
||||
|
@ -50,24 +52,24 @@ local flex = {}
|
|||
|
||||
function flex:layout(_, width, height)
|
||||
local result = {}
|
||||
local pos,spacing = 0, self._spacing
|
||||
local num = #self.widgets
|
||||
local pos,spacing = 0, self._private.spacing
|
||||
local num = #self._private.widgets
|
||||
local total_spacing = (spacing*(num-1))
|
||||
|
||||
local space_per_item
|
||||
if self.dir == "y" then
|
||||
if self._private.dir == "y" then
|
||||
space_per_item = height / num - total_spacing/num
|
||||
else
|
||||
space_per_item = width / num - total_spacing/num
|
||||
end
|
||||
|
||||
if self._max_widget_size then
|
||||
space_per_item = math.min(space_per_item, self._max_widget_size)
|
||||
if self._private.max_widget_size then
|
||||
space_per_item = math.min(space_per_item, self._private.max_widget_size)
|
||||
end
|
||||
|
||||
for _, v in pairs(self.widgets) do
|
||||
for _, v in pairs(self._private.widgets) do
|
||||
local x, y, w, h
|
||||
if self.dir == "y" then
|
||||
if self._private.dir == "y" then
|
||||
x, y = 0, util.round(pos)
|
||||
w, h = width, floor(space_per_item)
|
||||
else
|
||||
|
@ -79,8 +81,8 @@ function flex:layout(_, width, height)
|
|||
|
||||
pos = pos + space_per_item + spacing
|
||||
|
||||
if (self.dir == "y" and pos-spacing >= height) or
|
||||
(self.dir ~= "y" and pos-spacing >= width) then
|
||||
if (self._private.dir == "y" and pos-spacing >= height) or
|
||||
(self._private.dir ~= "y" and pos-spacing >= width) then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
@ -97,39 +99,41 @@ function flex:fit(context, orig_width, orig_height)
|
|||
local used_in_other = 0
|
||||
|
||||
-- Figure out the maximum size we can give out to sub-widgets
|
||||
local sub_height = self.dir == "x" and orig_height or orig_height / #self.widgets
|
||||
local sub_width = self.dir == "y" and orig_width or orig_width / #self.widgets
|
||||
local sub_height = self._private.dir == "x" and orig_height or orig_height / #self._private.widgets
|
||||
local sub_width = self._private.dir == "y" and orig_width or orig_width / #self._private.widgets
|
||||
|
||||
for _, v in pairs(self.widgets) do
|
||||
for _, v in pairs(self._private.widgets) do
|
||||
local w, h = base.fit_widget(self, context, v, sub_width, sub_height)
|
||||
|
||||
local max = self.dir == "y" and w or h
|
||||
local max = self._private.dir == "y" and w or h
|
||||
if max > used_in_other then
|
||||
used_in_other = max
|
||||
end
|
||||
|
||||
used_in_dir = used_in_dir + (self.dir == "y" and h or w)
|
||||
used_in_dir = used_in_dir + (self._private.dir == "y" and h or w)
|
||||
end
|
||||
|
||||
if self._max_widget_size then
|
||||
if self._private.max_widget_size then
|
||||
used_in_dir = math.min(used_in_dir,
|
||||
#self.widgets * self._max_widget_size)
|
||||
#self._private.widgets * self._private.max_widget_size)
|
||||
end
|
||||
|
||||
local spacing = self._spacing * (#self.widgets-1)
|
||||
local spacing = self._private.spacing * (#self._private.widgets-1)
|
||||
|
||||
if self.dir == "y" then
|
||||
if self._private.dir == "y" then
|
||||
return used_in_other, used_in_dir + spacing
|
||||
end
|
||||
return used_in_dir + spacing, used_in_other
|
||||
end
|
||||
|
||||
--- Set the maximum size the widgets in this layout will take (that is,
|
||||
-- maximum width for horizontal and maximum height for vertical).
|
||||
-- @param val The maximum size of the widget.
|
||||
--- Set the maximum size the widgets in this layout will take.
|
||||
--That is, maximum width for horizontal and maximum height for vertical.
|
||||
-- @property max_widget_size
|
||||
-- @param number
|
||||
|
||||
function flex:set_max_widget_size(val)
|
||||
if self._max_widget_size ~= val then
|
||||
self._max_widget_size = val
|
||||
if self._private.max_widget_size ~= val then
|
||||
self._private.max_widget_size = val
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
end
|
||||
|
@ -137,9 +141,9 @@ end
|
|||
local function get_layout(dir, widget1, ...)
|
||||
local ret = fixed[dir](widget1, ...)
|
||||
|
||||
util.table.crush(ret, flex)
|
||||
util.table.crush(ret, flex, true)
|
||||
|
||||
ret.fill_space = nil
|
||||
ret._private.fill_space = nil
|
||||
|
||||
return ret
|
||||
end
|
||||
|
@ -160,6 +164,10 @@ function flex.vertical(...)
|
|||
return get_layout("vertical", ...)
|
||||
end
|
||||
|
||||
--@DOC_widget_COMMON@
|
||||
|
||||
--@DOC_object_COMMON@
|
||||
|
||||
return flex
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -1,198 +1,18 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- This class has been moved to `wibox.container.margin`
|
||||
--
|
||||
-- @author Uli Schlachter
|
||||
-- @copyright 2010 Uli Schlachter
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.layout.margin
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local pairs = pairs
|
||||
local type = type
|
||||
local setmetatable = setmetatable
|
||||
local base = require("wibox.widget.base")
|
||||
local gcolor = require("gears.color")
|
||||
local cairo = require("lgi").cairo
|
||||
local util = require("awful.util")
|
||||
|
||||
local margin = { mt = {} }
|
||||
|
||||
-- Draw a margin layout
|
||||
function margin:draw(_, cr, width, height)
|
||||
local x = self.left
|
||||
local y = self.top
|
||||
local w = self.right
|
||||
local h = self.bottom
|
||||
local color = self.color
|
||||
|
||||
if not self.widget or width <= x + w or height <= y + h then
|
||||
return
|
||||
end
|
||||
|
||||
if color then
|
||||
cr:set_source(color)
|
||||
cr:rectangle(0, 0, width, height)
|
||||
cr:rectangle(x, y, width - x - w, height - y - h)
|
||||
cr:set_fill_rule(cairo.FillRule.EVEN_ODD)
|
||||
cr:fill()
|
||||
end
|
||||
end
|
||||
|
||||
-- Layout a margin layout
|
||||
function margin:layout(_, width, height)
|
||||
if self.widget then
|
||||
local x = self.left
|
||||
local y = self.top
|
||||
local w = self.right
|
||||
local h = self.bottom
|
||||
|
||||
return { base.place_widget_at(self.widget, x, y, width - x - w, height - y - h) }
|
||||
end
|
||||
end
|
||||
|
||||
-- Fit a margin layout into the given space
|
||||
function margin:fit(context, width, height)
|
||||
local extra_w = self.left + self.right
|
||||
local extra_h = self.top + self.bottom
|
||||
local w, h = 0, 0
|
||||
if self.widget then
|
||||
w, h = base.fit_widget(self, context, self.widget, width - extra_w, height - extra_h)
|
||||
end
|
||||
|
||||
if self._draw_empty == false and (w == 0 or h == 0) then
|
||||
return 0, 0
|
||||
end
|
||||
|
||||
return w + extra_w, h + extra_h
|
||||
end
|
||||
|
||||
--- Set the widget that this layout adds a margin on.
|
||||
function margin:set_widget(widget)
|
||||
if widget then
|
||||
base.check_widget(widget)
|
||||
end
|
||||
self.widget = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
-- Get the number of children element
|
||||
-- @treturn table The children
|
||||
function margin:get_children()
|
||||
return {self.widget}
|
||||
end
|
||||
|
||||
-- Replace the layout children
|
||||
-- This layout only accept one children, all others will be ignored
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function margin:set_children(children)
|
||||
self:set_widget(children[1])
|
||||
end
|
||||
|
||||
--- Set all the margins to val.
|
||||
-- @tparam number val The margin value
|
||||
function margin:set_margins(val)
|
||||
if self.left == val and
|
||||
self.right == val and
|
||||
self.top == val and
|
||||
self.bottom == val then
|
||||
return
|
||||
end
|
||||
|
||||
self.left = val
|
||||
self.right = val
|
||||
self.top = val
|
||||
self.bottom = val
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Set the margins color to create a border.
|
||||
-- @param color A color used to fill the margin.
|
||||
function margin:set_color(color)
|
||||
self.color = color and gcolor(color)
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Draw the margin even if the content size is 0x0 (default: true)
|
||||
-- @tparam boolean draw_empty Draw nothing is content is 0x0 or draw the margin anyway
|
||||
function margin:set_draw_empty(draw_empty)
|
||||
self._draw_empty = draw_empty
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Reset this layout. The widget will be unreferenced, the margins set to 0
|
||||
-- and the color erased
|
||||
function margin:reset()
|
||||
self:set_widget(nil)
|
||||
self:set_margins(0)
|
||||
self:set_color(nil)
|
||||
end
|
||||
|
||||
--- Set the left margin that this layout adds to its widget.
|
||||
-- @param layout The layout you are modifying.
|
||||
-- @param margin The new margin to use.
|
||||
-- @name set_left
|
||||
-- @class function
|
||||
|
||||
--- Set the right margin that this layout adds to its widget.
|
||||
-- @param layout The layout you are modifying.
|
||||
-- @param margin The new margin to use.
|
||||
-- @name set_right
|
||||
-- @class function
|
||||
|
||||
--- Set the top margin that this layout adds to its widget.
|
||||
-- @param layout The layout you are modifying.
|
||||
-- @param margin The new margin to use.
|
||||
-- @name set_top
|
||||
-- @class function
|
||||
|
||||
--- Set the bottom margin that this layout adds to its widget.
|
||||
-- @param layout The layout you are modifying.
|
||||
-- @param margin The new margin to use.
|
||||
-- @name set_bottom
|
||||
-- @class function
|
||||
|
||||
-- Create setters for each direction
|
||||
for _, v in pairs({ "left", "right", "top", "bottom" }) do
|
||||
margin["set_" .. v] = function(layout, val)
|
||||
if layout[v] == val then return end
|
||||
layout[v] = val
|
||||
layout:emit_signal("widget::layout_changed")
|
||||
end
|
||||
end
|
||||
|
||||
--- Returns a new margin layout.
|
||||
-- @param[opt] widget A widget to use.
|
||||
-- @param[opt] left A margin to use on the left side of the widget.
|
||||
-- @param[opt] right A margin to use on the right side of the widget.
|
||||
-- @param[opt] top A margin to use on the top side of the widget.
|
||||
-- @param[opt] bottom A margin to use on the bottom side of the widget.
|
||||
-- @param[opt] color A color for the margins.
|
||||
-- @param[opt] draw_empty whether or not to draw the margin when the content is empty
|
||||
local function new(widget, left, right, top, bottom, color, draw_empty)
|
||||
local ret = base.make_widget()
|
||||
|
||||
for k, v in pairs(margin) do
|
||||
if type(v) == "function" then
|
||||
ret[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
ret:set_left(left or 0)
|
||||
ret:set_right(right or 0)
|
||||
ret:set_top(top or 0)
|
||||
ret:set_bottom(bottom or 0)
|
||||
ret:set_draw_empty(draw_empty)
|
||||
|
||||
ret:set_color(color)
|
||||
|
||||
if widget then
|
||||
ret:set_widget(widget)
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function margin.mt:__call(...)
|
||||
return new(...)
|
||||
end
|
||||
|
||||
return setmetatable(margin, margin.mt)
|
||||
return util.deprecate_class(
|
||||
require("wibox.container.margin"),
|
||||
"wibox.layout.margin",
|
||||
"wibox.container.margin"
|
||||
)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -1,127 +1,18 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- This class has been moved to `wibox.container.mirror`
|
||||
--
|
||||
-- @author dodo
|
||||
-- @copyright 2012 dodo
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.layout.mirror
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local type = type
|
||||
local error = error
|
||||
local pairs = pairs
|
||||
local ipairs = ipairs
|
||||
local setmetatable = setmetatable
|
||||
local base = require("wibox.widget.base")
|
||||
local matrix = require("gears.matrix")
|
||||
local util = require("awful.util")
|
||||
|
||||
local mirror = { mt = {} }
|
||||
|
||||
--- Layout this layout
|
||||
function mirror:layout(_, width, height)
|
||||
if not self.widget then return end
|
||||
|
||||
local m = matrix.identity
|
||||
local t = { x = 0, y = 0 } -- translation
|
||||
local s = { x = 1, y = 1 } -- scale
|
||||
if self.horizontal then
|
||||
t.x = width
|
||||
s.x = -1
|
||||
end
|
||||
if self.vertical then
|
||||
t.y = height
|
||||
s.y = -1
|
||||
end
|
||||
m = m:translate(t.x, t.y)
|
||||
m = m:scale(s.x, s.y)
|
||||
|
||||
return { base.place_widget_via_matrix(self.widget, m, width, height) }
|
||||
end
|
||||
|
||||
--- Fit this layout into the given area
|
||||
function mirror:fit(context, ...)
|
||||
if not self.widget then
|
||||
return 0, 0
|
||||
end
|
||||
return base.fit_widget(self, context, self.widget, ...)
|
||||
end
|
||||
|
||||
--- Set the widget that this layout mirrors.
|
||||
-- @param widget The widget to mirror
|
||||
function mirror:set_widget(widget)
|
||||
if widget then
|
||||
base.check_widget(widget)
|
||||
end
|
||||
self.widget = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Get the number of children element
|
||||
-- @treturn table The children
|
||||
function mirror:get_children()
|
||||
return {self.widget}
|
||||
end
|
||||
|
||||
--- Replace the layout children
|
||||
-- This layout only accept one children, all others will be ignored
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function mirror:set_children(children)
|
||||
self:set_widget(children[1])
|
||||
end
|
||||
|
||||
--- Reset this layout. The widget will be removed and the axes reset.
|
||||
function mirror:reset()
|
||||
self.horizontal = false
|
||||
self.vertical = false
|
||||
self:set_widget(nil)
|
||||
end
|
||||
|
||||
--- Set the reflection of this mirror layout.
|
||||
-- @param reflection a table which contains new values for horizontal and/or vertical (booleans)
|
||||
function mirror:set_reflection(reflection)
|
||||
if type(reflection) ~= 'table' then
|
||||
error("Invalid type of reflection for mirror layout: " ..
|
||||
type(reflection) .. " (should be a table)")
|
||||
end
|
||||
for _, ref in ipairs({"horizontal", "vertical"}) do
|
||||
if reflection[ref] ~= nil then
|
||||
self[ref] = reflection[ref]
|
||||
end
|
||||
end
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Get the reflection of this mirror layout.
|
||||
-- @return a table of booleans with the keys "horizontal", "vertical".
|
||||
function mirror:get_reflection()
|
||||
return { horizontal = self.horizontal, vertical = self.vertical }
|
||||
end
|
||||
|
||||
--- Returns a new mirror layout. A mirror layout mirrors a given widget. Use
|
||||
-- :set_widget() to set the widget and
|
||||
-- :set_horizontal() and :set_vertical() for the direction.
|
||||
-- horizontal and vertical are by default false which doesn't change anything.
|
||||
-- @param[opt] widget The widget to display.
|
||||
-- @param[opt] reflection A table describing the reflection to apply.
|
||||
local function new(widget, reflection)
|
||||
local ret = base.make_widget()
|
||||
ret.horizontal = false
|
||||
ret.vertical = false
|
||||
|
||||
for k, v in pairs(mirror) do
|
||||
if type(v) == "function" then
|
||||
ret[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
ret:set_widget(widget)
|
||||
ret:set_reflection(reflection or {})
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function mirror.mt:__call(...)
|
||||
return new(...)
|
||||
end
|
||||
|
||||
return setmetatable(mirror, mirror.mt)
|
||||
return util.deprecate_class(
|
||||
require("wibox.container.mirror"),
|
||||
"wibox.layout.mirror",
|
||||
"wibox.container.mirror"
|
||||
)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
--- A layout filling all the available space. Each widget is assigned a
|
||||
-- ratio (percentage) of the total space. Multiple methods are available to
|
||||
-- ajust this ratio.
|
||||
--
|
||||
--@DOC_wibox_layout_defaults_ratio_EXAMPLE@
|
||||
-- @author Emmanuel Lepage Vallee
|
||||
-- @copyright 2016 Emmanuel Lepage Vallee
|
||||
-- @release @AWESOME_VERSION@
|
||||
|
@ -23,9 +25,9 @@ local ratio = {}
|
|||
local function gen_sum(self, i_s, i_e)
|
||||
local sum, new_w = 0,0
|
||||
|
||||
for i = i_s or 1, i_e or #self.widgets do
|
||||
if self._ratios[i] then
|
||||
sum = sum + self._ratios[i]
|
||||
for i = i_s or 1, i_e or #self._private.widgets do
|
||||
if self._private.ratios[i] then
|
||||
sum = sum + self._private.ratios[i]
|
||||
else
|
||||
new_w = new_w + 1
|
||||
end
|
||||
|
@ -40,24 +42,24 @@ end
|
|||
-- specific ratio must be enforced for a widget, it has to be done with the
|
||||
-- `ajust_ratio` method after each insertion or deletion
|
||||
local function normalize(self)
|
||||
local count = #self.widgets
|
||||
local count = #self._private.widgets
|
||||
if count == 0 then return end
|
||||
|
||||
-- Instead of adding "if" everywhere, just handle this common case
|
||||
if count == 1 then
|
||||
self._ratios = { 1 }
|
||||
self._private.ratios = { 1 }
|
||||
return
|
||||
end
|
||||
|
||||
local sum, new_w = gen_sum(self)
|
||||
local old_count = #self.widgets - new_w
|
||||
local old_count = #self._private.widgets - new_w
|
||||
|
||||
local to_add = (sum == 0) and 1 or (sum / old_count)
|
||||
|
||||
-- Make sure all widgets have a ratio
|
||||
for i=1, #self.widgets do
|
||||
if not self._ratios[i] then
|
||||
self._ratios[i] = to_add
|
||||
for i=1, #self._private.widgets do
|
||||
if not self._private.ratios[i] then
|
||||
self._private.ratios[i] = to_add
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -66,9 +68,9 @@ local function normalize(self)
|
|||
local delta, new_sum = (1 - sum) / count,0
|
||||
|
||||
-- Increase or decrease each ratio so it the sum become 1
|
||||
for i=1, #self.widgets do
|
||||
self._ratios[i] = self._ratios[i] + delta
|
||||
new_sum = new_sum + self._ratios[i]
|
||||
for i=1, #self._private.widgets do
|
||||
self._private.ratios[i] = self._private.ratios[i] + delta
|
||||
new_sum = new_sum + self._private.ratios[i]
|
||||
end
|
||||
|
||||
-- Floating points is not an exact science, but it should still be close
|
||||
|
@ -78,18 +80,18 @@ end
|
|||
|
||||
function ratio:layout(_, width, height)
|
||||
local result = {}
|
||||
local pos,spacing = 0, self._spacing
|
||||
local pos,spacing = 0, self._private.spacing
|
||||
|
||||
for k, v in ipairs(self.widgets) do
|
||||
for k, v in ipairs(self._private.widgets) do
|
||||
local space
|
||||
local x, y, w, h
|
||||
|
||||
if self.dir == "y" then
|
||||
space = height * self._ratios[k]
|
||||
if self._private.dir == "y" then
|
||||
space = height * self._private.ratios[k]
|
||||
x, y = 0, util.round(pos)
|
||||
w, h = width, floor(space)
|
||||
else
|
||||
space = width * self._ratios[k]
|
||||
space = width * self._private.ratios[k]
|
||||
x, y = util.round(pos), 0
|
||||
w, h = floor(space), height
|
||||
end
|
||||
|
@ -100,8 +102,8 @@ function ratio:layout(_, width, height)
|
|||
|
||||
-- Make sure all widgets fit in the layout, if they aren't, something
|
||||
-- went wrong
|
||||
if (self.dir == "y" and util.round(pos) >= height) or
|
||||
(self.dir ~= "y" and util.round(pos) >= width) then
|
||||
if (self._private.dir == "y" and util.round(pos) >= height) or
|
||||
(self._private.dir ~= "y" and util.round(pos) >= width) then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
@ -116,14 +118,14 @@ end
|
|||
-- @tparam number increment An floating point value between -1 and 1 where the
|
||||
-- end result is within 0 and 1
|
||||
function ratio:inc_ratio(index, increment)
|
||||
if #self.widgets == 1 or (not index) or (not self._ratios[index])
|
||||
if #self._private.widgets == 1 or (not index) or (not self._private.ratios[index])
|
||||
or increment < -1 or increment > 1 then
|
||||
return
|
||||
end
|
||||
|
||||
assert(self._ratios[index])
|
||||
assert(self._private.ratios[index])
|
||||
|
||||
self:set_ratio(index, self._ratios[index] + increment)
|
||||
self:set_ratio(index, self._private.ratios[index] + increment)
|
||||
end
|
||||
|
||||
--- Increment the ratio of the first instance of `widget`
|
||||
|
@ -144,22 +146,22 @@ end
|
|||
-- @tparam number index The index of the widget to change
|
||||
-- @tparam number percent An floating point value between 0 and 1
|
||||
function ratio:set_ratio(index, percent)
|
||||
if not percent or #self.widgets == 1 or not index or not self.widgets[index]
|
||||
if not percent or #self._private.widgets == 1 or not index or not self._private.widgets[index]
|
||||
or percent < 0 or percent > 1 then
|
||||
return
|
||||
end
|
||||
|
||||
local old = self._ratios[index]
|
||||
local old = self._private.ratios[index]
|
||||
|
||||
-- Remove what has to be cleared from all widget
|
||||
local delta = ( (percent-old) / (#self.widgets-1) )
|
||||
local delta = ( (percent-old) / (#self._private.widgets-1) )
|
||||
|
||||
for k in pairs(self.widgets) do
|
||||
self._ratios[k] = self._ratios[k] - delta
|
||||
for k in pairs(self._private.widgets) do
|
||||
self._private.ratios[k] = self._private.ratios[k] - delta
|
||||
end
|
||||
|
||||
-- Set the new ratio
|
||||
self._ratios[index] = percent
|
||||
self._private.ratios[index] = percent
|
||||
|
||||
-- As some widgets may now have a slightly negative ratio, normalize again
|
||||
normalize(self)
|
||||
|
@ -172,7 +174,7 @@ end
|
|||
-- @treturn number The index (between 0 and 1)
|
||||
function ratio:get_ratio(index)
|
||||
if not index then return end
|
||||
return self._ratios[index]
|
||||
return self._private.ratios[index]
|
||||
end
|
||||
|
||||
--- Set the ratio of `widget` to `percent`.
|
||||
|
@ -191,7 +193,7 @@ end
|
|||
-- @tparam number itself The ratio for "widget"
|
||||
-- @tparam number after The sum of the ratio after the widget
|
||||
function ratio:ajust_ratio(index, before, itself, after)
|
||||
if not self.widgets[index] or not before or not itself or not after then
|
||||
if not self._private.widgets[index] or not before or not itself or not after then
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -202,21 +204,21 @@ function ratio:ajust_ratio(index, before, itself, after)
|
|||
if sum > 1.01 or sum < -0.99 then return end
|
||||
|
||||
-- Compute the before and after offset to be applied to each widgets
|
||||
local before_count, after_count = index-1, #self.widgets - index
|
||||
local before_count, after_count = index-1, #self._private.widgets - index
|
||||
|
||||
local b, a = gen_sum(self, 1, index-1), gen_sum(self, index+1)
|
||||
|
||||
local db, da = (before - b)/before_count, (after - a)/after_count
|
||||
|
||||
-- Apply the new ratio
|
||||
self._ratios[index] = itself
|
||||
self._private.ratios[index] = itself
|
||||
|
||||
-- Equality split the delta among widgets before and after
|
||||
for i = 1, index -1 do
|
||||
self._ratios[i] = self._ratios[i] + db
|
||||
self._private.ratios[i] = self._private.ratios[i] + db
|
||||
end
|
||||
for i = index+1, #self.widgets do
|
||||
self._ratios[i] = self._ratios[i] + da
|
||||
for i = index+1, #self._private.widgets do
|
||||
self._private.ratios[i] = self._private.ratios[i] + da
|
||||
end
|
||||
|
||||
-- Remove potential negative ratio
|
||||
|
@ -243,7 +245,7 @@ function ratio:add(...)
|
|||
assert(args.n > 0, "need at least one widget to add")
|
||||
for i=1, args.n do
|
||||
base.check_widget(args[i])
|
||||
table.insert(self.widgets, args[i])
|
||||
table.insert(self._private.widgets, args[i])
|
||||
end
|
||||
|
||||
normalize(self)
|
||||
|
@ -254,10 +256,10 @@ end
|
|||
-- @tparam number index The widget index to remove
|
||||
-- @treturn boolean index If the operation is successful
|
||||
function ratio:remove(index)
|
||||
if not index or not self.widgets[index] then return false end
|
||||
if not index or not self._private.widgets[index] then return false end
|
||||
|
||||
table.remove(self._ratios, index)
|
||||
table.remove(self.widgets, index)
|
||||
table.remove(self._private.ratios, index)
|
||||
table.remove(self._private.widgets, index)
|
||||
|
||||
normalize(self)
|
||||
|
||||
|
@ -270,11 +272,11 @@ end
|
|||
-- @tparam number index The position
|
||||
-- @param widget The widget
|
||||
function ratio:insert(index, widget)
|
||||
if not index or index < 1 or index > #self.widgets + 1 then return false end
|
||||
if not index or index < 1 or index > #self._private.widgets + 1 then return false end
|
||||
|
||||
base.check_widget(widget)
|
||||
|
||||
table.insert(self.widgets, index, widget)
|
||||
table.insert(self._private.widgets, index, widget)
|
||||
|
||||
normalize(self)
|
||||
|
||||
|
@ -284,11 +286,11 @@ end
|
|||
local function get_layout(dir, widget1, ...)
|
||||
local ret = flex[dir](widget1, ...)
|
||||
|
||||
util.table.crush(ret, ratio)
|
||||
util.table.crush(ret, ratio, true)
|
||||
|
||||
ret.fill_space = nil
|
||||
ret._private.fill_space = nil
|
||||
|
||||
ret._ratios = {}
|
||||
ret._private.ratios = {}
|
||||
|
||||
return ret
|
||||
end
|
||||
|
@ -307,6 +309,10 @@ function ratio.vertical(...)
|
|||
return get_layout("vertical", ...)
|
||||
end
|
||||
|
||||
--@DOC_widget_COMMON@
|
||||
|
||||
--@DOC_object_COMMON@
|
||||
|
||||
return ratio
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -1,137 +1,18 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- This class has been moved to `wibox.container.rotate`
|
||||
--
|
||||
-- @author Uli Schlachter
|
||||
-- @copyright 2010 Uli Schlachter
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.layout.rotate
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local error = error
|
||||
local pairs = pairs
|
||||
local pi = math.pi
|
||||
local type = type
|
||||
local setmetatable = setmetatable
|
||||
local tostring = tostring
|
||||
local base = require("wibox.widget.base")
|
||||
local matrix = require("gears.matrix")
|
||||
local util = require("awful.util")
|
||||
|
||||
local rotate = { mt = {} }
|
||||
|
||||
local function transform(layout, width, height)
|
||||
local dir = layout:get_direction()
|
||||
if dir == "east" or dir == "west" then
|
||||
return height, width
|
||||
end
|
||||
return width, height
|
||||
end
|
||||
|
||||
--- Layout this layout
|
||||
function rotate:layout(_, width, height)
|
||||
if not self.widget or not self.widget.visible then
|
||||
return
|
||||
end
|
||||
|
||||
local dir = self:get_direction()
|
||||
|
||||
local m = matrix.identity
|
||||
if dir == "west" then
|
||||
m = m:rotate(pi / 2)
|
||||
m = m:translate(0, -width)
|
||||
elseif dir == "south" then
|
||||
m = m:rotate(pi)
|
||||
m = m:translate(-width, -height)
|
||||
elseif dir == "east" then
|
||||
m = m:rotate(3 * pi / 2)
|
||||
m = m:translate(-height, 0)
|
||||
end
|
||||
|
||||
-- Since we rotated, we might have to swap width and height.
|
||||
-- transform() does that for us.
|
||||
return { base.place_widget_via_matrix(self.widget, m, transform(self, width, height)) }
|
||||
end
|
||||
|
||||
--- Fit this layout into the given area
|
||||
function rotate:fit(context, width, height)
|
||||
if not self.widget then
|
||||
return 0, 0
|
||||
end
|
||||
return transform(self, base.fit_widget(self, context, self.widget, transform(self, width, height)))
|
||||
end
|
||||
|
||||
--- Set the widget that this layout rotates.
|
||||
function rotate:set_widget(widget)
|
||||
if widget then
|
||||
base.check_widget(widget)
|
||||
end
|
||||
self.widget = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Get the number of children element
|
||||
-- @treturn table The children
|
||||
function rotate:get_children()
|
||||
return {self.widget}
|
||||
end
|
||||
|
||||
--- Replace the layout children
|
||||
-- This layout only accept one children, all others will be ignored
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function rotate:set_children(children)
|
||||
self:set_widget(children[1])
|
||||
end
|
||||
|
||||
--- Reset this layout. The widget will be removed and the rotation reset.
|
||||
function rotate:reset()
|
||||
self.direction = nil
|
||||
self:set_widget(nil)
|
||||
end
|
||||
|
||||
--- Set the direction of this rotating layout. Valid values are "north", "east",
|
||||
-- "south" and "west". On an invalid value, this function will throw an error.
|
||||
function rotate:set_direction(dir)
|
||||
local allowed = {
|
||||
north = true,
|
||||
east = true,
|
||||
south = true,
|
||||
west = true
|
||||
}
|
||||
|
||||
if not allowed[dir] then
|
||||
error("Invalid direction for rotate layout: " .. tostring(dir))
|
||||
end
|
||||
|
||||
self.direction = dir
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Get the direction of this rotating layout
|
||||
function rotate:get_direction()
|
||||
return self.direction or "north"
|
||||
end
|
||||
|
||||
--- Returns a new rotate layout. A rotate layout rotates a given widget. Use
|
||||
-- :set_widget() to set the widget and :set_direction() for the direction.
|
||||
-- The default direction is "north" which doesn't change anything.
|
||||
-- @param[opt] widget The widget to display.
|
||||
-- @param[opt] dir The direction to rotate to.
|
||||
local function new(widget, dir)
|
||||
local ret = base.make_widget()
|
||||
|
||||
for k, v in pairs(rotate) do
|
||||
if type(v) == "function" then
|
||||
ret[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
ret:set_widget(widget)
|
||||
ret:set_direction(dir or "north")
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function rotate.mt:__call(...)
|
||||
return new(...)
|
||||
end
|
||||
|
||||
return setmetatable(rotate, rotate.mt)
|
||||
return util.deprecate_class(
|
||||
require("wibox.container.rotate"),
|
||||
"wibox.layout.rotate",
|
||||
"wibox.container.rotate"
|
||||
)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -1,509 +1,17 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- This class has been moved to `wibox.container.scroll`
|
||||
--
|
||||
-- @author Uli Schlachter (based on ideas from Saleur Geoffrey)
|
||||
-- @copyright 2015 Uli Schlachter
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.layout.scroll
|
||||
---------------------------------------------------------------------------
|
||||
local util = require("awful.util")
|
||||
|
||||
local cache = require("gears.cache")
|
||||
local timer = require("gears.timer")
|
||||
local hierarchy = require("wibox.hierarchy")
|
||||
local base = require("wibox.widget.base")
|
||||
local lgi = require("lgi")
|
||||
local GLib = lgi.GLib
|
||||
|
||||
local scroll = {}
|
||||
local scroll_mt = { __index = scroll }
|
||||
local _need_scroll_redraw
|
||||
|
||||
-- "Strip" a context so that we can use it for our own drawing
|
||||
local function cleanup_context(context)
|
||||
local skip = { wibox = true, drawable = true, client = true, position = true }
|
||||
local res = {}
|
||||
for k, v in pairs(context) do
|
||||
if not skip[k] then
|
||||
res[k] = v
|
||||
end
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
-- Create a hierarchy (and some more stuff) for drawing the given widget. This
|
||||
-- allows "some stuff" to be re-used instead of re-created all the time.
|
||||
local hierarchy_cache = cache.new(function(context, widget, width, height)
|
||||
context = cleanup_context(context)
|
||||
local layouts = setmetatable({}, { __mode = "k" })
|
||||
|
||||
-- Create a widget hierarchy and update when needed
|
||||
local hier
|
||||
local function do_pending_updates(layout)
|
||||
layouts[layout] = true
|
||||
hier:update(context, widget, width, height, nil)
|
||||
end
|
||||
local function emit(signal)
|
||||
-- Make the scroll layouts redraw
|
||||
for w in pairs(layouts) do
|
||||
w:emit_signal(signal)
|
||||
end
|
||||
end
|
||||
local function redraw_callback()
|
||||
emit("widget::redraw_needed")
|
||||
end
|
||||
local function layout_callback()
|
||||
emit("widget::redraw_needed")
|
||||
emit("widget::layout_changed")
|
||||
end
|
||||
hier = hierarchy.new(context, widget, width, height, redraw_callback, layout_callback, nil)
|
||||
|
||||
return hier, do_pending_updates, context
|
||||
end)
|
||||
|
||||
--- Calculate all the information needed for scrolling.
|
||||
-- @param self The instance of the scrolling layout.
|
||||
-- @param context A widget context under which we are fit/drawn.
|
||||
-- @param width The available width
|
||||
-- @param height The available height
|
||||
-- @return A table with the following entries
|
||||
-- @field fit_width The width that should be returned from :fit
|
||||
-- @field fit_height The height that should be returned from :fit
|
||||
-- @field surface_width The width for showing the child widget
|
||||
-- @field surface_height The height for showing the child widget
|
||||
-- @field first_x The x offset for drawing the child the first time
|
||||
-- @field first_y The y offset for drawing the child the first time
|
||||
-- @field[opt] second_x The x offset for drawing the child the second time
|
||||
-- @field[opt] second_y The y offset for drawing the child the second time
|
||||
-- @field hierarchy The wibox.hierarchy instance representing "everything"
|
||||
-- @field context The widget context for drawing the hierarchy
|
||||
local function calculate_info(self, context, width, height)
|
||||
local result = {}
|
||||
assert(self.widget)
|
||||
|
||||
-- First, get the size of the widget (and the size of extra space)
|
||||
local surface_width, surface_height = width, height
|
||||
local extra_width, extra_height, extra = 0, 0, self.expand and self.extra_space or 0
|
||||
local w, h
|
||||
if self.dir == "h" then
|
||||
w, h = base.fit_widget(self, context, self.widget, self.space_for_scrolling, height)
|
||||
surface_width = w
|
||||
extra_width = extra
|
||||
else
|
||||
w, h = base.fit_widget(self, context, self.widget, width, self.space_for_scrolling)
|
||||
surface_height = h
|
||||
extra_height = extra
|
||||
end
|
||||
result.fit_width, result.fit_height = w, h
|
||||
if self.dir == "h" then
|
||||
if self.max_size then
|
||||
result.fit_width = math.min(w, self.max_size)
|
||||
end
|
||||
else
|
||||
if self.max_size then
|
||||
result.fit_height = math.min(h, self.max_size)
|
||||
end
|
||||
end
|
||||
if w > width or h > height then
|
||||
-- There is less space available than we need, we have to scroll
|
||||
_need_scroll_redraw(self)
|
||||
|
||||
surface_width, surface_height = surface_width + extra_width, surface_height + extra_height
|
||||
|
||||
local x, y = 0, 0
|
||||
local function get_scroll_offset(size, visible_size)
|
||||
return self.step_function(self.timer:elapsed(), size, visible_size, self.speed, self.extra_space)
|
||||
end
|
||||
if self.dir == "h" then
|
||||
x = -get_scroll_offset(surface_width - extra, width)
|
||||
else
|
||||
y = -get_scroll_offset(surface_height - extra, height)
|
||||
end
|
||||
result.first_x, result.first_y = x, y
|
||||
-- Was the extra space already included elsewhere?
|
||||
local extra_spacer = self.expand and 0 or self.extra_space
|
||||
if self.dir == "h" then
|
||||
x = x + surface_width + extra_spacer
|
||||
else
|
||||
y = y + surface_height + extra_spacer
|
||||
end
|
||||
result.second_x, result.second_y = x, y
|
||||
else
|
||||
result.first_x, result.first_y = 0, 0
|
||||
end
|
||||
result.surface_width, result.surface_height = surface_width, surface_height
|
||||
|
||||
-- Get the hierarchy and subscribe ourselves to updates
|
||||
local hier, do_pending_updates, ctx = hierarchy_cache:get(context,
|
||||
self.widget, surface_width, surface_height)
|
||||
result.hierarchy = hier
|
||||
result.context = ctx
|
||||
do_pending_updates(self)
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
--- Draw this scrolling layout.
|
||||
-- @param context The context in which we are drawn.
|
||||
-- @param cr The cairo context to draw to.
|
||||
-- @param width The available width.
|
||||
-- @param height The available height.
|
||||
function scroll:draw(context, cr, width, height)
|
||||
if not self.widget then
|
||||
return
|
||||
end
|
||||
|
||||
local info = calculate_info(self, context, width, height)
|
||||
|
||||
-- Draw the first instance of the child
|
||||
cr:save()
|
||||
cr:translate(info.first_x, info.first_y)
|
||||
cr:rectangle(0, 0, info.surface_width, info.surface_height)
|
||||
cr:clip()
|
||||
info.hierarchy:draw(info.context, cr)
|
||||
cr:restore()
|
||||
|
||||
-- If there is one, draw the second instance (same code as above, minus the
|
||||
-- clip)
|
||||
if info.second_x and info.second_y then
|
||||
cr:translate(info.second_x, info.second_y)
|
||||
cr:rectangle(0, 0, info.surface_width, info.surface_height)
|
||||
cr:clip()
|
||||
info.hierarchy:draw(info.context, cr)
|
||||
end
|
||||
end
|
||||
|
||||
--- Fit the scroll layout into the given space.
|
||||
-- @param context The context in which we are fit.
|
||||
-- @param width The available width.
|
||||
-- @param height The available height.
|
||||
function scroll:fit(context, width, height)
|
||||
if not self.widget then
|
||||
return 0, 0
|
||||
end
|
||||
local info = calculate_info(self, context, width, height)
|
||||
return info.fit_width, info.fit_height
|
||||
end
|
||||
|
||||
-- Internal function used for triggering redraws for scrolling.
|
||||
-- The purpose is to start a timer for redrawing the widget for scrolling.
|
||||
-- Redrawing works by simply emitting the `widget::redraw_needed` signal.
|
||||
-- Pausing is implemented in this function: We just don't start a timer.
|
||||
-- This function must be idempotent (calling it multiple times right after
|
||||
-- another does not make a difference).
|
||||
_need_scroll_redraw = function(self)
|
||||
if not self.paused and not self.scroll_timer then
|
||||
self.scroll_timer = timer.start_new(1 / self.fps, function()
|
||||
self.scroll_timer = nil
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
--- Pause the scrolling animation.
|
||||
-- @see continue
|
||||
function scroll:pause()
|
||||
if self.paused then
|
||||
return
|
||||
end
|
||||
self.paused = true
|
||||
self.timer:stop()
|
||||
end
|
||||
|
||||
--- Continue the scrolling animation.
|
||||
-- @see pause
|
||||
function scroll:continue()
|
||||
if not self.paused then
|
||||
return
|
||||
end
|
||||
self.paused = false
|
||||
self.timer:continue()
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Reset the scrolling state to its initial condition.
|
||||
-- For must scroll step functions, the effect of this function should be to
|
||||
-- display the widget without any scrolling applied.
|
||||
-- This function does not undo the effect of @{pause}.
|
||||
function scroll:reset_scrolling()
|
||||
self.timer:start()
|
||||
if self.paused then
|
||||
self.timer:stop()
|
||||
end
|
||||
end
|
||||
|
||||
--- Set the direction in which this widget scroll.
|
||||
-- @param dir Either "h" for horizontal scrolling or "v" for vertical scrolling
|
||||
function scroll:set_direction(dir)
|
||||
if dir == self.dir then
|
||||
return
|
||||
end
|
||||
if dir ~= "h" and dir ~= "v" then
|
||||
error("Invalid direction, can only be 'h' or 'v'")
|
||||
end
|
||||
self.dir = dir
|
||||
self:emit_signal("widget::layout_changed")
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set the widget which we scroll.
|
||||
-- @tparam widget widget The widget that we should display
|
||||
function scroll:set_widget(widget)
|
||||
if widget == self.widget then
|
||||
return
|
||||
end
|
||||
if widget then
|
||||
base.check_widget(widget)
|
||||
end
|
||||
self.widget = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Get the number of children element
|
||||
-- @treturn table The children
|
||||
function scroll:get_children()
|
||||
return {self.widget}
|
||||
end
|
||||
|
||||
--- Replace the layout children
|
||||
-- This layout only accept one children, all others will be ignored
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function scroll:set_children(children)
|
||||
self:set_widget(children[1])
|
||||
end
|
||||
|
||||
--- Specify the expand mode that is used for extra space.
|
||||
-- @tparam boolean expand If true, the widget is expanded to include the extra
|
||||
-- space. If false, the extra space is simply left empty.
|
||||
-- @see set_extra_space
|
||||
function scroll:set_expand(expand)
|
||||
if expand == self.expand then
|
||||
return
|
||||
end
|
||||
self.expand = expand
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set the number of frames per second that this widget should draw.
|
||||
-- @tparam number fps The number of frames per second
|
||||
function scroll:set_fps(fps)
|
||||
if fps == self.fps then
|
||||
return
|
||||
end
|
||||
self.fps = fps
|
||||
-- No signal needed: If we are scrolling, the next redraw will apply the new
|
||||
-- FPS, else it obviously doesn't make a difference.
|
||||
end
|
||||
|
||||
--- Set the amount of extra space that should be included in the scrolling. This
|
||||
-- extra space will likely be left empty between repetitions of the widgets.
|
||||
-- @tparam number extra_space The amount of extra space
|
||||
-- @see set_expand
|
||||
function scroll:set_extra_space(extra_space)
|
||||
if extra_space == self.extra_space then
|
||||
return
|
||||
end
|
||||
self.extra_space = extra_space
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set the speed of the scrolling animation. The exact meaning depends on the
|
||||
-- step function that is used, but for the simplest step functions, this will be
|
||||
-- in pixels per second.
|
||||
-- @tparam number speed The speed for the animation
|
||||
function scroll:set_speed(speed)
|
||||
if speed == self.speed then
|
||||
return
|
||||
end
|
||||
self.speed = speed
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set the maximum size of this widget in the direction set by
|
||||
-- @{set_direction}. If the child widget is smaller than this size, no scrolling
|
||||
-- is done. If the child widget is larger, then only this size will be visible
|
||||
-- and the rest is made visible via scrolling.
|
||||
-- @tparam number max_size The maximum size of this widget or nil for unlimited.
|
||||
function scroll:set_max_size(max_size)
|
||||
if max_size == self.max_size then
|
||||
return
|
||||
end
|
||||
self.max_size = max_size
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Set the step function that determines the exact behaviour of the scrolling
|
||||
-- animation.
|
||||
-- The step function is called with five arguments:
|
||||
--
|
||||
-- * The time in seconds since the state of the animation
|
||||
-- * The size of the child widget
|
||||
-- * The size of the visible part of the widget
|
||||
-- * The speed of the animation. This should have a linear effect on this
|
||||
-- function's behaviour.
|
||||
-- * The extra space configured by @{set_extra_space}. This was not yet added to
|
||||
-- the size of the child widget, but should likely be added to it in most
|
||||
-- cases.
|
||||
--
|
||||
-- The step function should return a single number. This number is the offset at
|
||||
-- which the widget is drawn and should be between 0 and `size+extra_space`.
|
||||
-- @tparam function step_function A step function.
|
||||
-- @see step_functions
|
||||
function scroll:set_step_function(step_function)
|
||||
-- Call the step functions once to see if it works
|
||||
step_function(0, 42, 10, 10, 5)
|
||||
if step_function == self.step_function then
|
||||
return
|
||||
end
|
||||
self.step_function = step_function
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set an upper limit for the space for scrolling.
|
||||
-- This restricts the child widget's maximal size.
|
||||
-- @tparam number space_for_scrolling The space for scrolling
|
||||
function scroll:set_space_for_scrolling(space_for_scrolling)
|
||||
if space_for_scrolling == self.space_for_scrolling then
|
||||
return
|
||||
end
|
||||
self.space_for_scrolling = space_for_scrolling
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
local function get_layout(dir, widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling)
|
||||
local ret = base.make_widget()
|
||||
|
||||
ret.paused = false
|
||||
ret.timer = GLib.Timer()
|
||||
ret.scroll_timer = nil
|
||||
|
||||
setmetatable(ret, scroll_mt)
|
||||
|
||||
ret:set_direction(dir)
|
||||
ret:set_widget(widget)
|
||||
ret:set_fps(fps or 20)
|
||||
ret:set_speed(speed or 10)
|
||||
ret:set_extra_space(extra_space or 0)
|
||||
ret:set_expand(expand)
|
||||
ret:set_max_size(max_size)
|
||||
ret:set_step_function(step_function or scroll.step_functions.linear_increase)
|
||||
ret:set_space_for_scrolling(space_for_scrolling or 2^1024)
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
--- Get a new horizontal scrolling layout.
|
||||
-- @param[opt] widget The widget that should be scrolled
|
||||
-- @param[opt=20] fps The number of frames per second
|
||||
-- @param[opt=10] speed The speed of the animation
|
||||
-- @param[opt=0] extra_space The amount of extra space to include
|
||||
-- @tparam[opt=false] boolean expand Should the widget be expanded to include the
|
||||
-- extra space?
|
||||
-- @param[opt] max_size The maximum size of the child widget
|
||||
-- @param[opt=step_functions.linear_increase] step_function The step function to be used
|
||||
-- @param[opt=2^1024] space_for_scrolling The space for scrolling
|
||||
function scroll.horizontal(widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling)
|
||||
return get_layout("h", widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling)
|
||||
end
|
||||
|
||||
--- Get a new vertical scrolling layout.
|
||||
-- @param[opt] widget The widget that should be scrolled
|
||||
-- @param[opt=20] fps The number of frames per second
|
||||
-- @param[opt=10] speed The speed of the animation
|
||||
-- @param[opt=0] extra_space The amount of extra space to include
|
||||
-- @tparam[opt=false] boolean expand Should the widget be expanded to include the
|
||||
-- extra space?
|
||||
-- @param[opt] max_size The maximum size of the child widget
|
||||
-- @param[opt=step_functions.linear_increase] step_function The step function to be used
|
||||
-- @param[opt=2^1024] space_for_scrolling The space for scrolling
|
||||
function scroll.vertical(widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling)
|
||||
return get_layout("v", widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling)
|
||||
end
|
||||
|
||||
--- A selection of step functions
|
||||
-- @see set_step_function
|
||||
scroll.step_functions = {}
|
||||
|
||||
--- A step function that scrolls the widget in an increasing direction with
|
||||
-- constant speed.
|
||||
function scroll.step_functions.linear_increase(elapsed, size, _, speed, extra_space)
|
||||
return (elapsed * speed) % (size + extra_space)
|
||||
end
|
||||
|
||||
--- A step function that scrolls the widget in an decreasing direction with
|
||||
-- constant speed.
|
||||
function scroll.step_functions.linear_decrease(elapsed, size, _, speed, extra_space)
|
||||
return (-elapsed * speed) % (size + extra_space)
|
||||
end
|
||||
|
||||
--- A step function that scrolls the widget to its end and back to its
|
||||
-- beginning, then back to its end, etc. The speed is constant.
|
||||
function scroll.step_functions.linear_back_and_forth(elapsed, size, visible_size, speed)
|
||||
local state = ((elapsed * speed) % (2 * size)) / size
|
||||
state = state <= 1 and state or 2 - state
|
||||
return (size - visible_size) * state
|
||||
end
|
||||
|
||||
--- A step function that scrolls the widget to its end and back to its
|
||||
-- beginning, then back to its end, etc. The speed is null at the ends and
|
||||
-- maximal in the middle.
|
||||
function scroll.step_functions.nonlinear_back_and_forth(elapsed, size, visible_size, speed)
|
||||
local state = ((elapsed * speed) % (2 * size)) / size
|
||||
local negate = false
|
||||
if state > 1 then
|
||||
negate = true
|
||||
state = state - 1
|
||||
end
|
||||
if state < 1/3 then
|
||||
-- In the first 1/3rd of time, do a quadratic increase in speed
|
||||
state = 2 * state * state
|
||||
elseif state < 2/3 then
|
||||
-- In the center, do a linear increase. That means we need:
|
||||
-- If state is 1/3, result is 2/9 = 2 * 1/3 * 1/3
|
||||
-- If state is 2/3, result is 7/9 = 1 - 2 * (1 - 2/3) * (1 - 2/3)
|
||||
state = 5/3*state - 3/9
|
||||
else
|
||||
-- In the last 1/3rd of time, do a quadratic decrease in speed
|
||||
state = 1 - 2 * (1 - state) * (1 - state)
|
||||
end
|
||||
if negate then
|
||||
state = 1 - state
|
||||
end
|
||||
return (size - visible_size) * state
|
||||
end
|
||||
|
||||
--- A step function that scrolls the widget to its end and back to its
|
||||
-- beginning, then back to its end, etc. The speed is null at the ends and
|
||||
-- maximal in the middle. At both ends the widget stands still for a moment.
|
||||
function scroll.step_functions.waiting_nonlinear_back_and_forth(elapsed, size, visible_size, speed)
|
||||
local state = ((elapsed * speed) % (2 * size)) / size
|
||||
local negate = false
|
||||
if state > 1 then
|
||||
negate = true
|
||||
state = state - 1
|
||||
end
|
||||
if state < 1/5 or state > 4/5 then
|
||||
-- One fifth of time, nothing moves
|
||||
state = state < 1/5 and 0 or 1
|
||||
else
|
||||
state = (state - 1/5) * 5/3
|
||||
if state < 1/3 then
|
||||
-- In the first 1/3rd of time, do a quadratic increase in speed
|
||||
state = 2 * state * state
|
||||
elseif state < 2/3 then
|
||||
-- In the center, do a linear increase. That means we need:
|
||||
-- If state is 1/3, result is 2/9 = 2 * 1/3 * 1/3
|
||||
-- If state is 2/3, result is 7/9 = 1 - 2 * (1 - 2/3) * (1 - 2/3)
|
||||
state = 5/3*state - 3/9
|
||||
else
|
||||
-- In the last 1/3rd of time, do a quadratic decrease in speed
|
||||
state = 1 - 2 * (1 - state) * (1 - state)
|
||||
end
|
||||
end
|
||||
if negate then
|
||||
state = 1 - state
|
||||
end
|
||||
return (size - visible_size) * state
|
||||
end
|
||||
|
||||
return scroll
|
||||
return util.deprecate_class(
|
||||
require("wibox.container.scroll"),
|
||||
"wibox.layout.scroll",
|
||||
"wibox.container.scroll"
|
||||
)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
-- The indices are going from 1 (the bottom of the stack) up to the top of
|
||||
-- the stack. The order can be changed either using `:swap` or `:raise`.
|
||||
--
|
||||
--@DOC_wibox_layout_defaults_stack_EXAMPLE@
|
||||
-- @author Emmanuel Lepage Vallee
|
||||
-- @copyright 2016 Emmanuel Lepage Vallee
|
||||
-- @release @AWESOME_VERSION@
|
||||
|
@ -52,17 +53,16 @@ local stack = {mt={}}
|
|||
-- @class function
|
||||
|
||||
--- Add spacing between each layout widgets
|
||||
-- @param spacing Spacing between widgets.
|
||||
-- @name set_spacing
|
||||
-- @class function
|
||||
-- @property spacing
|
||||
-- @tparam number spacing Spacing between widgets.
|
||||
|
||||
function stack:layout(_, width, height)
|
||||
local result = {}
|
||||
local spacing = self._spacing
|
||||
local spacing = self._private.spacing
|
||||
|
||||
for _, v in pairs(self.widgets) do
|
||||
for _, v in pairs(self._private.widgets) do
|
||||
table.insert(result, base.place_widget_at(v, spacing, spacing, width - 2*spacing, height - 2*spacing))
|
||||
if self._top_only then break end
|
||||
if self._private.top_only then break end
|
||||
end
|
||||
|
||||
return result
|
||||
|
@ -70,9 +70,9 @@ end
|
|||
|
||||
function stack:fit(context, orig_width, orig_height)
|
||||
local max_w, max_h = 0,0
|
||||
local spacing = self._spacing
|
||||
local spacing = self._private.spacing
|
||||
|
||||
for _, v in pairs(self.widgets) do
|
||||
for _, v in pairs(self._private.widgets) do
|
||||
local w, h = base.fit_widget(self, context, v, orig_width, orig_height)
|
||||
max_w, max_h = math.max(max_w, w+2*spacing), math.max(max_h, h+2*spacing)
|
||||
end
|
||||
|
@ -80,26 +80,25 @@ function stack:fit(context, orig_width, orig_height)
|
|||
return math.min(max_w, orig_width), math.min(max_h, orig_height)
|
||||
end
|
||||
|
||||
--- Get if only the first stack widget is drawn
|
||||
-- @return If the only the first stack widget is drawn
|
||||
function stack:get_display_top_only()
|
||||
return self._top_only
|
||||
--- If only the first stack widget is drawn
|
||||
-- @property top_only
|
||||
|
||||
function stack:get_top_only()
|
||||
return self._private.top_only
|
||||
end
|
||||
|
||||
--- Only draw the first widget of the stack, ignore others
|
||||
-- @tparam boolean top_only Only draw the top stack widget
|
||||
function stack:set_display_top_only(top_only)
|
||||
self._top_only = top_only
|
||||
function stack:set_top_only(top_only)
|
||||
self._private.top_only = top_only
|
||||
end
|
||||
|
||||
--- Raise a widget at `index` to the top of the stack
|
||||
-- @tparam number index the widget index to raise
|
||||
function stack:raise(index)
|
||||
if (not index) or self.widgets[index] then return end
|
||||
if (not index) or self._private.widgets[index] then return end
|
||||
|
||||
local w = self.widgets[index]
|
||||
table.remove(self.widgets, index)
|
||||
table.insert(self.widgets, w)
|
||||
local w = self._private.widgets[index]
|
||||
table.remove(self._private.widgets, index)
|
||||
table.insert(self._private.widgets, w)
|
||||
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
@ -130,7 +129,7 @@ end
|
|||
local function new(...)
|
||||
local ret = fixed.horizontal(...)
|
||||
|
||||
util.table.crush(ret, stack)
|
||||
util.table.crush(ret, stack, true)
|
||||
|
||||
return ret
|
||||
end
|
||||
|
@ -139,5 +138,9 @@ function stack.mt:__call(_, ...)
|
|||
return new(...)
|
||||
end
|
||||
|
||||
--@DOC_widget_COMMON@
|
||||
|
||||
--@DOC_object_COMMON@
|
||||
|
||||
return setmetatable(stack, stack.mt)
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -1,224 +1,17 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- A container capable of changing the background color, foreground color
|
||||
-- widget shape.
|
||||
-- This class has been moved to `wibox.container.background`
|
||||
--
|
||||
-- @author Uli Schlachter
|
||||
-- @copyright 2010 Uli Schlachter
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.widget.background
|
||||
---------------------------------------------------------------------------
|
||||
local util = require("awful.util")
|
||||
|
||||
local base = require("wibox.widget.base")
|
||||
local color = require("gears.color")
|
||||
local surface = require("gears.surface")
|
||||
local beautiful = require("beautiful")
|
||||
local cairo = require("lgi").cairo
|
||||
local setmetatable = setmetatable
|
||||
local pairs = pairs
|
||||
local type = type
|
||||
local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
|
||||
|
||||
local background = { mt = {} }
|
||||
|
||||
-- Draw this widget
|
||||
function background:draw(context, cr, width, height)
|
||||
if not self.widget or not self.widget.visible then
|
||||
return
|
||||
end
|
||||
|
||||
-- Keep the shape path in case there is a border
|
||||
self._path = nil
|
||||
|
||||
if self._shape then
|
||||
-- Only add the offset if there is something to draw
|
||||
local offset = ((self._shape_border_width and self._shape_border_color)
|
||||
and self._shape_border_width or 0) / 2
|
||||
|
||||
cr:translate(offset, offset)
|
||||
self._shape(cr, width - 2*offset, height - 2*offset, unpack(self._shape_args or {}))
|
||||
cr:translate(-offset, -offset)
|
||||
self._path = cr:copy_path()
|
||||
cr:clip()
|
||||
end
|
||||
|
||||
if self.background then
|
||||
cr:set_source(self.background)
|
||||
cr:paint()
|
||||
end
|
||||
if self.bgimage then
|
||||
if type(self.bgimage) == "function" then
|
||||
self.bgimage(context, cr, width, height,unpack(self.bgimage_args))
|
||||
else
|
||||
local pattern = cairo.Pattern.create_for_surface(self.bgimage)
|
||||
cr:set_source(pattern)
|
||||
cr:paint()
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Draw the border
|
||||
function background:after_draw_children(_, cr)
|
||||
-- Draw the border
|
||||
if self._path and self._shape_border_width and self._shape_border_width > 0 then
|
||||
cr:append_path(self._path)
|
||||
cr:set_source(color(self._shape_border_color or self.foreground or beautiful.fg_normal))
|
||||
|
||||
cr:set_line_width(self._shape_border_width)
|
||||
cr:stroke()
|
||||
self._path = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Prepare drawing the children of this widget
|
||||
function background:before_draw_children(_, cr)
|
||||
if self.foreground then
|
||||
cr:set_source(self.foreground)
|
||||
end
|
||||
|
||||
-- Clip the shape
|
||||
if self._path and self._shape_clip then
|
||||
cr:append_path(self._path)
|
||||
cr:clip()
|
||||
end
|
||||
end
|
||||
|
||||
-- Layout this widget
|
||||
function background:layout(_, width, height)
|
||||
if self.widget then
|
||||
return { base.place_widget_at(self.widget, 0, 0, width, height) }
|
||||
end
|
||||
end
|
||||
|
||||
-- Fit this widget into the given area
|
||||
function background:fit(context, width, height)
|
||||
if not self.widget then
|
||||
return 0, 0
|
||||
end
|
||||
|
||||
return base.fit_widget(self, context, self.widget, width, height)
|
||||
end
|
||||
|
||||
--- Set the widget that is drawn on top of the background
|
||||
-- @tparam widget widget The widget to be disaplayed inside of the background
|
||||
-- area
|
||||
function background:set_widget(widget)
|
||||
if widget then
|
||||
base.check_widget(widget)
|
||||
end
|
||||
self.widget = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
-- Get children element
|
||||
-- @treturn table The children
|
||||
function background:get_children()
|
||||
return {self.widget}
|
||||
end
|
||||
|
||||
-- Replace the layout children
|
||||
-- This layout only accept one children, all others will be ignored
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function background:set_children(children)
|
||||
self:set_widget(children[1])
|
||||
end
|
||||
|
||||
--- Set the background to use.
|
||||
--@DOC_wibox_widget_background_bg_EXAMPLE@
|
||||
-- @param bg A color string, pattern or gradient (see `gears.color`)
|
||||
function background:set_bg(bg)
|
||||
if bg then
|
||||
self.background = color(bg)
|
||||
else
|
||||
self.background = nil
|
||||
end
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set the foreground to use.
|
||||
--@DOC_wibox_widget_background_fg_EXAMPLE@
|
||||
-- @param fg A color string, pattern or gradient (see `gears.color`)
|
||||
function background:set_fg(fg)
|
||||
if fg then
|
||||
self.foreground = color(fg)
|
||||
else
|
||||
self.foreground = nil
|
||||
end
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set the background shape.
|
||||
--
|
||||
-- Any other arguments will be passed to the shape function
|
||||
--@DOC_wibox_widget_background_shape_EXAMPLE@
|
||||
-- @param shape A function taking a context, width and height as arguments
|
||||
function background:set_shape(shape, ...)
|
||||
self._shape = shape
|
||||
self._shape_args = {...}
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- When a `shape` is set, also draw a border.
|
||||
--
|
||||
-- See `wibox.widget.background.set_shape` for an usage example.
|
||||
-- @tparam number width The border width
|
||||
function background:set_shape_border_width(width)
|
||||
self._shape_border_width = width
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- When a `shape` is set, also draw a border.
|
||||
--
|
||||
-- See `wibox.widget.background.set_shape` for an usage example.
|
||||
-- @param[opt=self.foreground] fg The border color, pattern or gradient
|
||||
function background:set_shape_border_color(fg)
|
||||
self._shape_border_color = fg
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- When a `shape` is set, make sure nothing is drawn outside of it.
|
||||
--@DOC_wibox_widget_background_clip_EXAMPLE@
|
||||
-- @tparam boolean value If the shape clip is enable
|
||||
function background:set_shape_clip(value)
|
||||
self._shape_clip = value
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set the background image to use
|
||||
-- If `image` is a function, it will be called with `(context, cr, width, height)`
|
||||
-- as arguments. Any other arguments passed to this method will be appended.
|
||||
-- @param image A background image or a function
|
||||
function background:set_bgimage(image, ...)
|
||||
self.bgimage = type(image) == "function" and image or surface.load(image)
|
||||
self.bgimage_args = {...}
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Returns a new background layout. A background layout applies a background
|
||||
-- and foreground color to another widget.
|
||||
-- @param[opt] widget The widget to display.
|
||||
-- @param[opt] bg The background to use for that widget.
|
||||
-- @param[opt] shape A `gears.shape` compatible shape function
|
||||
local function new(widget, bg, shape)
|
||||
local ret = base.make_widget()
|
||||
|
||||
for k, v in pairs(background) do
|
||||
if type(v) == "function" then
|
||||
ret[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
ret._shape = shape
|
||||
|
||||
ret:set_widget(widget)
|
||||
ret:set_bg(bg)
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function background.mt:__call(...)
|
||||
return new(...)
|
||||
end
|
||||
|
||||
return setmetatable(background, background.mt)
|
||||
return util.deprecate_class(
|
||||
require("wibox.container.background"),
|
||||
"wibox.widget.background",
|
||||
"wibox.container.background"
|
||||
)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
-- @author Uli Schlachter
|
||||
-- @copyright 2010 Uli Schlachter
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @module wibox.widget.base
|
||||
-- @classmod wibox.widget.base
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local object = require("gears.object")
|
||||
|
@ -24,60 +24,102 @@ base.widget = {}
|
|||
|
||||
--- Set/get a widget's buttons.
|
||||
-- @param _buttons The table of buttons that should bind to the widget.
|
||||
-- @function buttons
|
||||
function base.widget:buttons(_buttons)
|
||||
if _buttons then
|
||||
self.widget_buttons = _buttons
|
||||
self._private.widget_buttons = _buttons
|
||||
end
|
||||
|
||||
return self.widget_buttons
|
||||
return self._private.widget_buttons
|
||||
end
|
||||
|
||||
--- Set a widget's visible property
|
||||
-- @tparam boolean b Wether the widget is visible at all
|
||||
-- @function set_visible
|
||||
function base.widget:set_visible(b)
|
||||
if b ~= self.visible then
|
||||
self.visible = b
|
||||
if b ~= self._private.visible then
|
||||
self._private.visible = b
|
||||
self:emit_signal("widget::layout_changed")
|
||||
-- In case something ignored fit and drew the widget anyway
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
end
|
||||
|
||||
--- Get if the widget is visible.
|
||||
-- @treturn boolean If the widget is visible
|
||||
-- @function get_visible
|
||||
function base.widget:get_visible()
|
||||
return self._private.visible or false
|
||||
end
|
||||
|
||||
--- Set a widget's opacity
|
||||
-- @tparam number o The opacity to use (a number from 0 to 1). 0 is fully
|
||||
-- transparent while 1 is fully opaque.
|
||||
-- @function set_opacity
|
||||
function base.widget:set_opacity(o)
|
||||
if o ~= self.opacity then
|
||||
self.opacity = o
|
||||
if o ~= self._private.opacity then
|
||||
self._private.opacity = o
|
||||
self:emit_signal("widget::redraw")
|
||||
end
|
||||
end
|
||||
|
||||
--- Get the widget opacity.
|
||||
-- @treturn number The opacity (between 0 and 1)
|
||||
-- @function get_opacity
|
||||
function base.widget:get_opacity()
|
||||
return self._private.opacity
|
||||
end
|
||||
|
||||
--- Set the widget's width
|
||||
-- @tparam number|nil s The width that the widget has. `nil` means to apply the
|
||||
-- default mechanism of calling the `:fit` method. A number overrides the result
|
||||
-- from `:fit`.
|
||||
function base.widget:set_width(s)
|
||||
if s ~= self._forced_width then
|
||||
self._forced_width = s
|
||||
-- @function set_width
|
||||
function base.widget:set_forced_width(s)
|
||||
if s ~= self._private.forced_width then
|
||||
self._private.forced_width = s
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
end
|
||||
|
||||
--- Get the widget forced width.
|
||||
-- Note that widgets instances can be placed at different places simultaneously,
|
||||
-- therefore, they can have multiple width and width simultaneously. If there
|
||||
-- is no forced size, then the only way to get the widget actual size is when
|
||||
-- there is a `mouse::enter`, `mouse::leave` or button events.
|
||||
-- @treturn nil|number The forced width (nil if automatic)
|
||||
-- @function get_forced_widget
|
||||
function base.widget:get_forced_width()
|
||||
return self._private.forced_width
|
||||
end
|
||||
|
||||
--- Set the widget's height
|
||||
-- @tparam number|nil s The height that the widget has. `nil` means to apply the
|
||||
-- default mechanism of calling the `:fit` method. A number overrides the result
|
||||
-- from `:fit`.
|
||||
function base.widget:set_height(s)
|
||||
if s ~= self._forced_height then
|
||||
self._forced_height = s
|
||||
-- @function set_height
|
||||
function base.widget:set_forced_height(s)
|
||||
if s ~= self._private.forced_height then
|
||||
self._private.forced_height = s
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
end
|
||||
|
||||
--- Get the widget forced height.
|
||||
-- Note that widgets instances can be placed at different places simultaneously,
|
||||
-- therefore, they can have multiple width and height simultaneously. If there
|
||||
-- is no forced size, then the only way to get the widget actual size is when
|
||||
-- there is a `mouse::enter`, `mouse::leave` or button events.
|
||||
-- @treturn nil|number The forced height (nil if automatic)
|
||||
-- @function get_forced_height
|
||||
function base.widget:get_forced_height()
|
||||
return self._private.forced_height
|
||||
end
|
||||
|
||||
--- Get all direct children widgets
|
||||
-- This method should be re-implemented by the relevant widgets
|
||||
-- @treturn table The children
|
||||
-- @function get_children
|
||||
function base.widget:get_children()
|
||||
return {}
|
||||
end
|
||||
|
@ -86,6 +128,7 @@ end
|
|||
-- The default implementation does nothing, this must be re-implemented by
|
||||
-- all layout and container widgets.
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
-- @function set_children
|
||||
function base.widget:set_children(children) -- luacheck: no unused
|
||||
-- Nothing on purpose
|
||||
end
|
||||
|
@ -98,24 +141,26 @@ local function digg_children(ret, tlw)
|
|||
end
|
||||
end
|
||||
|
||||
--- Get all direct and indirect children widgets
|
||||
--- Get all direct and indirect children widgets.
|
||||
-- This will scan all containers recursively to find widgets
|
||||
-- Warning: This method it prone to stack overflow id the widget, or any of its
|
||||
-- children, contain (directly or indirectly) itself.
|
||||
-- @treturn table The children
|
||||
-- @function get_all_children
|
||||
function base.widget:get_all_children()
|
||||
local ret = {}
|
||||
digg_children(ret, self)
|
||||
return ret
|
||||
end
|
||||
|
||||
--- Get a widex index
|
||||
--- Get a widex index.
|
||||
-- @param widget The widget to look for
|
||||
-- @param[opt] recursive Also check sub-widgets
|
||||
-- @param[opt] ... Aditional widgets to add at the end of the "path"
|
||||
-- @return The index
|
||||
-- @return The parent layout
|
||||
-- @return The path between "self" and "widget"
|
||||
-- @function index
|
||||
function base.widget:index(widget, recursive, ...)
|
||||
local widgets = self:get_children()
|
||||
|
||||
|
@ -143,12 +188,12 @@ local widget_dependencies = setmetatable({}, { __mode = "kv" })
|
|||
-- Get the cache of the given kind for this widget. This returns a gears.cache
|
||||
-- that calls the callback of kind `kind` on the widget.
|
||||
local function get_cache(widget, kind)
|
||||
if not widget._widget_caches[kind] then
|
||||
widget._widget_caches[kind] = cache.new(function(...)
|
||||
if not widget._private.widget_caches[kind] then
|
||||
widget._private.widget_caches[kind] = cache.new(function(...)
|
||||
return protected_call(widget[kind], widget, ...)
|
||||
end)
|
||||
end
|
||||
return widget._widget_caches[kind]
|
||||
return widget._private.widget_caches[kind]
|
||||
end
|
||||
|
||||
-- Special value to skip the dependency recording that is normally done by
|
||||
|
@ -177,7 +222,7 @@ local clear_caches
|
|||
function clear_caches(widget)
|
||||
local deps = widget_dependencies[widget] or {}
|
||||
widget_dependencies[widget] = {}
|
||||
widget._widget_caches = {}
|
||||
widget._private.widget_caches = {}
|
||||
for w in pairs(deps) do
|
||||
clear_caches(w)
|
||||
end
|
||||
|
@ -187,6 +232,7 @@ end
|
|||
|
||||
--- Figure out the geometry in device coordinate space. This gives only tight
|
||||
-- bounds if no rotations by non-multiples of 90° are used.
|
||||
-- @function wibox.widget.base.rect_to_device_geometry
|
||||
function base.rect_to_device_geometry(cr, x, y, width, height)
|
||||
return matrix.transform_rectangle(cr.matrix, x, y, width, height)
|
||||
end
|
||||
|
@ -200,10 +246,11 @@ end
|
|||
-- @param width The available width for the widget
|
||||
-- @param height The available height for the widget
|
||||
-- @return The width and height that the widget wants to use
|
||||
-- @function wibox.widget.base.fit_widget
|
||||
function base.fit_widget(parent, context, widget, width, height)
|
||||
record_dependency(parent, widget)
|
||||
|
||||
if not widget.visible then
|
||||
if not widget._private.visible then
|
||||
return 0, 0
|
||||
end
|
||||
|
||||
|
@ -225,8 +272,8 @@ function base.fit_widget(parent, context, widget, width, height)
|
|||
end
|
||||
|
||||
-- Apply forced size and handle nil's
|
||||
w = widget._forced_width or w or 0
|
||||
h = widget._forced_height or h or 0
|
||||
w = widget._private.forced_width or w or 0
|
||||
h = widget._private.forced_height or h or 0
|
||||
|
||||
-- Also sanitize the output.
|
||||
w = math.max(0, math.min(w, width))
|
||||
|
@ -244,10 +291,11 @@ end
|
|||
-- @param width The available width for the widget
|
||||
-- @param height The available height for the widget
|
||||
-- @return The result from the widget's `:layout` callback.
|
||||
-- @function wibox.widget.base.layout_widget
|
||||
function base.layout_widget(parent, context, widget, width, height)
|
||||
record_dependency(parent, widget)
|
||||
|
||||
if not widget.visible then
|
||||
if not widget._private.visible then
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -262,6 +310,7 @@ end
|
|||
|
||||
-- Handle a button event on a widget. This is used internally and should not be
|
||||
-- called directly.
|
||||
-- @function wibox.widget.base.handle_button
|
||||
function base.handle_button(event, widget, x, y, button, modifiers, geometry)
|
||||
x = x or y -- luacheck: no unused
|
||||
local function is_any(mod)
|
||||
|
@ -282,7 +331,7 @@ function base.handle_button(event, widget, x, y, button, modifiers, geometry)
|
|||
|
||||
-- Find all matching button objects
|
||||
local matches = {}
|
||||
for _, v in pairs(widget.widget_buttons) do
|
||||
for _, v in pairs(widget._private.widget_buttons) do
|
||||
local match = true
|
||||
-- Is it the right button?
|
||||
if v.button ~= 0 and v.button ~= button then match = false end
|
||||
|
@ -310,6 +359,7 @@ end
|
|||
-- @param height The height of the widget in its own coordinate system. That is,
|
||||
-- after applying the transformation matrix.
|
||||
-- @return An opaque object that can be returned from :layout()
|
||||
-- @function wibox.widget.base.place_widget_via_matrix
|
||||
function base.place_widget_via_matrix(widget, mat, width, height)
|
||||
return {
|
||||
_widget = widget,
|
||||
|
@ -329,6 +379,7 @@ end
|
|||
-- @param height The height of the widget in its own coordinate system. That is,
|
||||
-- after applying the transformation matrix.
|
||||
-- @return An opaque object that can be returned from :layout()
|
||||
-- @function wibox.widget.base.place_widget_at
|
||||
function base.place_widget_at(widget, x, y, width, height)
|
||||
return base.place_widget_via_matrix(widget, matrix.create_translate(x, y), width, height)
|
||||
end
|
||||
|
@ -424,12 +475,17 @@ end
|
|||
|
||||
-- Only available when the declarative system is used
|
||||
local function get_children_by_id(self, name)
|
||||
return self._by_id[name] or {}
|
||||
if rawget(self, "_private") then
|
||||
return self._private.by_id[name] or {}
|
||||
else
|
||||
return rawget(self, "_by_id")[name] or {}
|
||||
end
|
||||
end
|
||||
|
||||
--- Set a declarative widget hierarchy description.
|
||||
-- See [The declarative layout system](../documentation/03-declarative-layout.md.html)
|
||||
-- @param args An array containing the widgets disposition
|
||||
-- @function setup
|
||||
function base.widget:setup(args)
|
||||
local f,ids = self.set_widget or self.add or self.set_first,{}
|
||||
local w, id = drill(ids, args)
|
||||
|
@ -438,13 +494,20 @@ function base.widget:setup(args)
|
|||
-- Avoid being dropped by wibox metatable -> drawin
|
||||
rawset(self, id, w)
|
||||
end
|
||||
rawset(self, "_by_id", ids)
|
||||
|
||||
if rawget(self, "_private") then
|
||||
self._private.by_id = ids
|
||||
else
|
||||
rawset(self, "_by_id", ids)
|
||||
end
|
||||
|
||||
rawset(self, "get_children_by_id", get_children_by_id)
|
||||
end
|
||||
|
||||
--- Create a widget from a declarative description
|
||||
-- See [The declarative layout system](../documentation/03-declarative-layout.md.html)
|
||||
-- @param args An array containing the widgets disposition
|
||||
-- @function wibox.widget.base.make_widget_declarative
|
||||
function base.make_widget_declarative(args)
|
||||
local ids = {}
|
||||
|
||||
|
@ -454,10 +517,16 @@ function base.make_widget_declarative(args)
|
|||
|
||||
local w, id = drill(ids, args)
|
||||
|
||||
local mt = {}
|
||||
local mt = getmetatable(w) or {}
|
||||
local orig_string = tostring(w)
|
||||
|
||||
rawset(w, "_by_id", ids)
|
||||
|
||||
if rawget(w, "_private") then
|
||||
w._private.by_id = ids
|
||||
else
|
||||
rawset(w, "_by_id", ids)
|
||||
end
|
||||
|
||||
rawset(w, "get_children_by_id", get_children_by_id)
|
||||
|
||||
mt.__tostring = function()
|
||||
|
@ -474,9 +543,18 @@ end
|
|||
-- 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`.
|
||||
-- @tparam[opt={}] table args Widget settings
|
||||
-- @tparam[opt=false] boolean args.enable_properties Enable automatic getters and
|
||||
-- setters calls.
|
||||
-- @tparam[opt=nil] table args.class The widget class
|
||||
-- @see fit_widget
|
||||
function base.make_widget(proxy, widget_name)
|
||||
local ret = object()
|
||||
-- @function wibox.widget.base.make_widget
|
||||
function base.make_widget(proxy, widget_name, args)
|
||||
args = args or {}
|
||||
local ret = object {
|
||||
enable_properties = args.enable_properties,
|
||||
class = args.class,
|
||||
}
|
||||
|
||||
-- This signal is used by layouts to find out when they have to update.
|
||||
ret:add_signal("widget::layout_changed")
|
||||
|
@ -495,21 +573,24 @@ function base.make_widget(proxy, widget_name)
|
|||
ret:emit_signal("widget::redraw_needed")
|
||||
end)
|
||||
|
||||
-- Create a table used to store the widgets internal data
|
||||
rawset(ret, "_private", {})
|
||||
|
||||
-- No buttons yet
|
||||
ret.widget_buttons = {}
|
||||
ret._private.widget_buttons = {}
|
||||
|
||||
-- Widget is visible
|
||||
ret.visible = true
|
||||
ret._private.visible = true
|
||||
|
||||
-- Widget is fully opaque
|
||||
ret.opacity = 1
|
||||
ret._private.opacity = 1
|
||||
|
||||
-- Differentiate tables from widgets
|
||||
ret.is_widget = true
|
||||
rawset(ret, "is_widget", true)
|
||||
|
||||
-- Size is not restricted/forced
|
||||
ret._forced_width = nil
|
||||
ret._forced_height = nil
|
||||
ret._private.forced_width = nil
|
||||
ret._private.forced_height = nil
|
||||
|
||||
-- Make buttons work
|
||||
ret:connect_signal("button::press", function(...)
|
||||
|
@ -520,12 +601,12 @@ function base.make_widget(proxy, widget_name)
|
|||
end)
|
||||
|
||||
if proxy then
|
||||
ret.fit = function(_, context, width, height)
|
||||
rawset(ret, "fit", function(_, context, width, height)
|
||||
return base.fit_widget(ret, context, proxy, width, height)
|
||||
end
|
||||
ret.layout = function(_, _, width, height)
|
||||
end)
|
||||
rawset(ret, "layout", function(_, _, width, height)
|
||||
return { base.place_widget_at(proxy, 0, 0, width, height) }
|
||||
end
|
||||
end)
|
||||
proxy:connect_signal("widget::layout_changed", function()
|
||||
ret:emit_signal("widget::layout_changed")
|
||||
end)
|
||||
|
@ -542,12 +623,12 @@ function base.make_widget(proxy, widget_name)
|
|||
|
||||
-- Add functions
|
||||
for k, v in pairs(base.widget) do
|
||||
ret[k] = v
|
||||
rawset(ret, k, v)
|
||||
end
|
||||
|
||||
-- Add __tostring method to metatable.
|
||||
ret.widget_name = widget_name or object.modulename(3)
|
||||
local mt = {}
|
||||
rawset(ret, "widget_name", widget_name or object.modulename(3))
|
||||
local mt = getmetatable(ret) or {}
|
||||
local orig_string = tostring(ret)
|
||||
mt.__tostring = function()
|
||||
return string.format("%s (%s)", ret.widget_name, orig_string)
|
||||
|
@ -556,12 +637,14 @@ function base.make_widget(proxy, widget_name)
|
|||
end
|
||||
|
||||
--- Generate an empty widget which takes no space and displays nothing
|
||||
-- @function wibox.widget.base.empty_widget
|
||||
function base.empty_widget()
|
||||
return base.make_widget()
|
||||
end
|
||||
|
||||
--- Do some sanity checking on widget. This function raises a lua error if
|
||||
-- widget is not a valid widget.
|
||||
-- @function wibox.widget.base.check_widget
|
||||
function base.check_widget(widget)
|
||||
assert(type(widget) == "table", "Type should be table, but is " .. tostring(type(widget)))
|
||||
assert(widget.is_widget, "Argument is not a widget!")
|
||||
|
|
|
@ -0,0 +1,291 @@
|
|||
---------------------------------------------------------------------------
|
||||
--- A graph widget.
|
||||
--
|
||||
--@DOC_wibox_widget_defaults_graph_EXAMPLE@
|
||||
-- @author Julien Danjou <julien@danjou.info>
|
||||
-- @copyright 2009 Julien Danjou
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.widget.graph
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local setmetatable = setmetatable
|
||||
local ipairs = ipairs
|
||||
local math = math
|
||||
local table = table
|
||||
local type = type
|
||||
local color = require("gears.color")
|
||||
local base = require("wibox.widget.base")
|
||||
local beautiful = require("beautiful")
|
||||
|
||||
local graph = { mt = {} }
|
||||
|
||||
--- Set the graph border color.
|
||||
-- If the value is nil, no border will be drawn.
|
||||
--
|
||||
-- @property border_color
|
||||
-- @tparam geats.color border_color The border color to set.
|
||||
|
||||
--- Set the graph foreground color.
|
||||
--
|
||||
-- @property color
|
||||
-- @tparam color color The graph color.
|
||||
-- @see gears.color.create_pattern
|
||||
|
||||
--- Set the graph background color.
|
||||
--
|
||||
-- @property background_color
|
||||
-- @tparam gears.color background_color The graph background color.
|
||||
|
||||
--- Set the maximum value the graph should handle.
|
||||
-- If "scale" is also set, the graph never scales up below this value, but it
|
||||
-- automatically scales down to make all data fit.
|
||||
--
|
||||
-- @property max_value
|
||||
-- @param number
|
||||
|
||||
--- Set the graph to automatically scale its values. Default is false.
|
||||
--
|
||||
-- @property scale
|
||||
-- @param boolean
|
||||
|
||||
--- Set the graph to draw stacks. Default is false.
|
||||
--
|
||||
-- @property stack
|
||||
-- @param boolean
|
||||
|
||||
--- Set the graph stacking colors. Order matters.
|
||||
--
|
||||
-- @property stack_colors
|
||||
-- @param stack_colors A table with stacking colors.
|
||||
|
||||
--- The graph background color.
|
||||
-- @beautiful beautiful.graph_bg
|
||||
|
||||
--- The graph foreground color.
|
||||
-- @beautiful beautiful.graph_fg
|
||||
|
||||
--- The graph border color.
|
||||
-- @beautiful beautiful.graph_border_color
|
||||
|
||||
local properties = { "width", "height", "border_color", "stack",
|
||||
"stack_colors", "color", "background_color",
|
||||
"max_value", "scale" }
|
||||
|
||||
function graph.draw(_graph, _, cr, width, height)
|
||||
local max_value = _graph._private.max_value
|
||||
local values = _graph._private.values
|
||||
|
||||
cr:set_line_width(1)
|
||||
|
||||
-- Draw the background first
|
||||
cr:set_source(color(_graph._private.background_color or beautiful.graph_bg or "#000000aa"))
|
||||
cr:paint()
|
||||
|
||||
-- Account for the border width
|
||||
cr:save()
|
||||
if _graph._private.border_color then
|
||||
cr:translate(1, 1)
|
||||
width, height = width - 2, height - 2
|
||||
end
|
||||
|
||||
-- Draw a stacked graph
|
||||
if _graph._private.stack then
|
||||
|
||||
if _graph._private.scale then
|
||||
for _, v in ipairs(values) do
|
||||
for _, sv in ipairs(v) do
|
||||
if sv > max_value then
|
||||
max_value = sv
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for i = 0, width do
|
||||
local rel_i = 0
|
||||
local rel_x = i + 0.5
|
||||
|
||||
if _graph._private.stack_colors then
|
||||
for idx, col in ipairs(_graph._private.stack_colors) do
|
||||
local stack_values = values[idx]
|
||||
if stack_values and i < #stack_values then
|
||||
local value = stack_values[#stack_values - i] + rel_i
|
||||
cr:move_to(rel_x, height * (1 - (rel_i / max_value)))
|
||||
cr:line_to(rel_x, height * (1 - (value / max_value)))
|
||||
cr:set_source(color(col or beautiful.graph_fg or "#ff0000"))
|
||||
cr:stroke()
|
||||
rel_i = value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
if _graph._private.scale then
|
||||
for _, v in ipairs(values) do
|
||||
if v > max_value then
|
||||
max_value = v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Draw the background on no value
|
||||
if #values ~= 0 then
|
||||
-- Draw reverse
|
||||
for i = 0, #values - 1 do
|
||||
local value = values[#values - i]
|
||||
if value >= 0 then
|
||||
value = value / max_value
|
||||
cr:move_to(i + 0.5, height * (1 - value))
|
||||
cr:line_to(i + 0.5, height)
|
||||
end
|
||||
end
|
||||
cr:set_source(color(_graph._private.color or beautiful.graph_fg or "#ff0000"))
|
||||
cr:stroke()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Undo the cr:translate() for the border
|
||||
cr:restore()
|
||||
|
||||
-- Draw the border last so that it overlaps already drawn values
|
||||
if _graph._private.border_color then
|
||||
-- We decremented these by two above
|
||||
width, height = width + 2, height + 2
|
||||
|
||||
-- Draw the border
|
||||
cr:rectangle(0.5, 0.5, width - 1, height - 1)
|
||||
cr:set_source(color(_graph._private.border_color or beautiful.graph_border_color or "#ffffff"))
|
||||
cr:stroke()
|
||||
end
|
||||
end
|
||||
|
||||
function graph.fit(_graph)
|
||||
return _graph._private.width, _graph._private.height
|
||||
end
|
||||
|
||||
--- Add a value to the graph
|
||||
--
|
||||
-- @param value The value to be added to the graph
|
||||
-- @param group The stack color group index.
|
||||
function graph:add_value(value, group)
|
||||
value = value or 0
|
||||
local values = self._private.values
|
||||
local max_value = self._private.max_value
|
||||
value = math.max(0, value)
|
||||
if not self._private.scale then
|
||||
value = math.min(max_value, value)
|
||||
end
|
||||
|
||||
if self._private.stack and group then
|
||||
if not self._private.values[group]
|
||||
or type(self._private.values[group]) ~= "table"
|
||||
then
|
||||
self._private.values[group] = {}
|
||||
end
|
||||
values = self._private.values[group]
|
||||
end
|
||||
table.insert(values, value)
|
||||
|
||||
local border_width = 0
|
||||
if self._private.border_color then border_width = 2 end
|
||||
|
||||
-- Ensure we never have more data than we can draw
|
||||
while #values > self._private.width - border_width do
|
||||
table.remove(values, 1)
|
||||
end
|
||||
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
return self
|
||||
end
|
||||
|
||||
--- Clear the graph.
|
||||
function graph:clear()
|
||||
self._private.values = {}
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set the graph height.
|
||||
-- @param height The height to set.
|
||||
function graph:set_height(height)
|
||||
if height >= 5 then
|
||||
self._private.height = height
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set the graph width.
|
||||
-- @param width The width to set.
|
||||
function graph:set_width(width)
|
||||
if width >= 5 then
|
||||
self._private.width = width
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
-- Build properties function
|
||||
for _, prop in ipairs(properties) do
|
||||
if not graph["set_" .. prop] then
|
||||
graph["set_" .. prop] = function(_graph, value)
|
||||
if _graph._private[prop] ~= value then
|
||||
_graph._private[prop] = value
|
||||
_graph:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
return _graph
|
||||
end
|
||||
end
|
||||
if not graph["get_" .. prop] then
|
||||
graph["get_" .. prop] = function(_graph)
|
||||
return _graph._private[prop]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Create a graph widget.
|
||||
-- @param args Standard widget() arguments. You should add width and height
|
||||
-- key to set graph geometry.
|
||||
-- @return A new graph widget.
|
||||
-- @function wibox.widget.graph
|
||||
function graph.new(args)
|
||||
args = args or {}
|
||||
|
||||
local width = args.width or 100
|
||||
local height = args.height or 20
|
||||
|
||||
if width < 5 or height < 5 then return end
|
||||
|
||||
local _graph = base.make_widget(nil, nil, {enable_properties = true})
|
||||
|
||||
_graph._private.width = width
|
||||
_graph._private.height = height
|
||||
_graph._private.values = {}
|
||||
_graph._private.max_value = 1
|
||||
|
||||
-- Set methods
|
||||
_graph.add_value = graph["add_value"]
|
||||
_graph.clear = graph["clear"]
|
||||
_graph.draw = graph.draw
|
||||
_graph.fit = graph.fit
|
||||
|
||||
for _, prop in ipairs(properties) do
|
||||
_graph["set_" .. prop] = graph["set_" .. prop]
|
||||
_graph["get_" .. prop] = graph["get_" .. prop]
|
||||
end
|
||||
|
||||
return _graph
|
||||
end
|
||||
|
||||
function graph.mt:__call(...)
|
||||
return graph.new(...)
|
||||
end
|
||||
|
||||
--@DOC_widget_COMMON@
|
||||
|
||||
--@DOC_object_COMMON@
|
||||
|
||||
return setmetatable(graph, graph.mt)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -1,4 +1,6 @@
|
|||
---------------------------------------------------------------------------
|
||||
--
|
||||
--@DOC_wibox_widget_defaults_imagebox_EXAMPLE@
|
||||
-- @author Uli Schlachter
|
||||
-- @copyright 2010 Uli Schlachter
|
||||
-- @release @AWESOME_VERSION@
|
||||
|
@ -7,23 +9,23 @@
|
|||
|
||||
local base = require("wibox.widget.base")
|
||||
local surface = require("gears.surface")
|
||||
local util = require("awful.util")
|
||||
local setmetatable = setmetatable
|
||||
local pairs = pairs
|
||||
local type = type
|
||||
local print = print
|
||||
local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
|
||||
|
||||
local imagebox = { mt = {} }
|
||||
|
||||
--- Draw an imagebox with the given cairo context in the given geometry.
|
||||
-- Draw an imagebox with the given cairo context in the given geometry.
|
||||
function imagebox:draw(_, cr, width, height)
|
||||
if not self._image then return end
|
||||
if not self._private.image then return end
|
||||
if width == 0 or height == 0 then return end
|
||||
|
||||
if not self.resize_forbidden then
|
||||
if not self._private.resize_forbidden then
|
||||
-- Let's scale the image so that it fits into (width, height)
|
||||
local w = self._image:get_width()
|
||||
local h = self._image:get_height()
|
||||
local w = self._private.image:get_width()
|
||||
local h = self._private.image:get_height()
|
||||
local aspect = width / w
|
||||
local aspect_h = height / h
|
||||
if aspect > aspect_h then aspect = aspect_h end
|
||||
|
@ -32,22 +34,22 @@ function imagebox:draw(_, cr, width, height)
|
|||
end
|
||||
|
||||
-- Set the clip
|
||||
if self._clip_shape then
|
||||
cr:clip(self._clip_shape(cr, width, height, unpack(self._clip_args)))
|
||||
if self._private.clip_shape then
|
||||
cr:clip(self._private.clip_shape(cr, width, height, unpack(self._private.clip_args)))
|
||||
end
|
||||
|
||||
cr:set_source_surface(self._image, 0, 0)
|
||||
cr:set_source_surface(self._private.image, 0, 0)
|
||||
cr:paint()
|
||||
end
|
||||
|
||||
--- Fit the imagebox into the given geometry
|
||||
-- Fit the imagebox into the given geometry
|
||||
function imagebox:fit(_, width, height)
|
||||
if not self._image then
|
||||
if not self._private.image then
|
||||
return 0, 0
|
||||
end
|
||||
|
||||
local w = self._image:get_width()
|
||||
local h = self._image:get_height()
|
||||
local w = self._private.image:get_width()
|
||||
local h = self._private.image:get_height()
|
||||
|
||||
if w > width then
|
||||
h = h * width / w
|
||||
|
@ -62,7 +64,7 @@ function imagebox:fit(_, width, height)
|
|||
return 0, 0
|
||||
end
|
||||
|
||||
if not self.resize_forbidden then
|
||||
if not self._private.resize_forbidden then
|
||||
local aspect = width / w
|
||||
local aspect_h = height / h
|
||||
|
||||
|
@ -76,9 +78,11 @@ function imagebox:fit(_, width, height)
|
|||
end
|
||||
|
||||
--- Set an imagebox' image
|
||||
-- @property image
|
||||
-- @param image Either a string or a cairo image surface. A string is
|
||||
-- interpreted as the path to a png image file.
|
||||
-- @return true on success, false if the image cannot be used
|
||||
|
||||
function imagebox:set_image(image)
|
||||
if type(image) == "string" then
|
||||
image = surface.load(image)
|
||||
|
@ -98,19 +102,28 @@ function imagebox:set_image(image)
|
|||
end
|
||||
end
|
||||
|
||||
if self._image == image then
|
||||
if self._private.image == image then
|
||||
-- The image could have been modified, so better redraw
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
return
|
||||
end
|
||||
|
||||
self._image = image
|
||||
self._private.image = image
|
||||
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("widget::layout_changed")
|
||||
return true
|
||||
end
|
||||
|
||||
--- Set a clip shape for this imagebox
|
||||
-- A clip shape define an area where the content is displayed and one where it
|
||||
-- is trimmed.
|
||||
--
|
||||
-- @property clip_shape
|
||||
-- @param clip_shape A `gears_shape` compatible shape function
|
||||
-- @see gears.shape
|
||||
-- @see set_clip_shape
|
||||
|
||||
--- Set a clip shape for this imagebox
|
||||
-- A clip shape define an area where the content is displayed and one where it
|
||||
-- is trimmed.
|
||||
|
@ -118,35 +131,37 @@ end
|
|||
-- Any other parameters will be passed to the clip shape function
|
||||
--
|
||||
-- @param clip_shape A `gears_shape` compatible shape function
|
||||
-- @see gears.shape
|
||||
-- @see clip_shape
|
||||
function imagebox:set_clip_shape(clip_shape, ...)
|
||||
self._clip_shape = clip_shape
|
||||
self._clip_args = {...}
|
||||
self._private.clip_shape = clip_shape
|
||||
self._private.clip_args = {...}
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Should the image be resized to fit into the available space?
|
||||
-- @property resize
|
||||
-- @param allowed If false, the image will be clipped, else it will be resized
|
||||
-- to fit into the available space.
|
||||
|
||||
function imagebox:set_resize(allowed)
|
||||
self.resize_forbidden = not allowed
|
||||
self._private.resize_forbidden = not allowed
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Returns a new imagebox
|
||||
--- Returns a new imagebox.
|
||||
-- Any other arguments will be passed to the clip shape function
|
||||
-- @param image the image to display, may be nil
|
||||
-- @param resize_allowed If false, the image will be clipped, else it will be resized
|
||||
-- to fit into the available space.
|
||||
-- @param clip_shape A `gears.shape` compatible function
|
||||
-- @treturn table A new `imagebox`
|
||||
-- @function wibox.widget.imagebox
|
||||
local function new(image, resize_allowed, clip_shape)
|
||||
local ret = base.make_widget()
|
||||
local ret = base.make_widget(nil, nil, {enable_properties = true})
|
||||
|
||||
for k, v in pairs(imagebox) do
|
||||
if type(v) == "function" then
|
||||
ret[k] = v
|
||||
end
|
||||
end
|
||||
util.table.crush(ret, imagebox, true)
|
||||
|
||||
if image then
|
||||
ret:set_image(image)
|
||||
|
@ -155,8 +170,8 @@ local function new(image, resize_allowed, clip_shape)
|
|||
ret:set_resize(resize_allowed)
|
||||
end
|
||||
|
||||
ret._clip_shape = clip_shape
|
||||
ret._clip_args = {}
|
||||
ret._private.clip_shape = clip_shape
|
||||
ret._private.clip_args = {}
|
||||
|
||||
return ret
|
||||
end
|
||||
|
@ -165,6 +180,10 @@ function imagebox.mt:__call(...)
|
|||
return new(...)
|
||||
end
|
||||
|
||||
--@DOC_widget_COMMON@
|
||||
|
||||
--@DOC_object_COMMON@
|
||||
|
||||
return setmetatable(imagebox, imagebox.mt)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -12,6 +12,9 @@ return setmetatable({
|
|||
imagebox = require("wibox.widget.imagebox");
|
||||
background = require("wibox.widget.background");
|
||||
systray = require("wibox.widget.systray");
|
||||
textclock = require("wibox.widget.textclock");
|
||||
progressbar = require("wibox.widget.progressbar");
|
||||
graph = require("wibox.widget.graph");
|
||||
}, {__call = function(_, args) return base.make_widget_declarative(args) end})
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -0,0 +1,243 @@
|
|||
---------------------------------------------------------------------------
|
||||
--- A progressbar widget.
|
||||
--
|
||||
--@DOC_wibox_widget_defaults_progressbar_EXAMPLE@
|
||||
-- @author Julien Danjou <julien@danjou.info>
|
||||
-- @copyright 2009 Julien Danjou
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.widget.progressbar
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local setmetatable = setmetatable
|
||||
local ipairs = ipairs
|
||||
local math = math
|
||||
local base = require("wibox.widget.base")
|
||||
local color = require("gears.color")
|
||||
local beautiful = require("beautiful")
|
||||
|
||||
local progressbar = { mt = {} }
|
||||
|
||||
local data = setmetatable({}, { __mode = "k" })
|
||||
|
||||
--- Set the progressbar border color.
|
||||
-- If the value is nil, no border will be drawn.
|
||||
--
|
||||
-- @function set_border_color
|
||||
-- @param progressbar The progressbar.
|
||||
-- @param color The border color to set.
|
||||
|
||||
--- Set the progressbar foreground color.
|
||||
--
|
||||
-- @function set_color
|
||||
-- @param progressbar The progressbar.
|
||||
-- @param color The progressbar color.
|
||||
|
||||
--- Set the progressbar background color.
|
||||
--
|
||||
-- @function set_background_color
|
||||
-- @param progressbar The progressbar.
|
||||
-- @param color The progressbar background color.
|
||||
|
||||
--- Set the progressbar to draw vertically. Default is false.
|
||||
--
|
||||
-- @function set_vertical
|
||||
-- @param progressbar The progressbar.
|
||||
-- @param vertical A boolean value.
|
||||
|
||||
--- Set the progressbar to draw ticks. Default is false.
|
||||
--
|
||||
-- @function set_ticks
|
||||
-- @param progressbar The progressbar.
|
||||
-- @param ticks A boolean value.
|
||||
|
||||
--- Set the progressbar ticks gap.
|
||||
--
|
||||
-- @function set_ticks_gap
|
||||
-- @param progressbar The progressbar.
|
||||
-- @param value The value.
|
||||
|
||||
--- Set the progressbar ticks size.
|
||||
--
|
||||
-- @function set_ticks_size
|
||||
-- @param progressbar The progressbar.
|
||||
-- @param value The value.
|
||||
|
||||
--- Set the maximum value the progressbar should handle.
|
||||
--
|
||||
-- @function set_max_value
|
||||
-- @param progressbar The progressbar.
|
||||
-- @param value The value.
|
||||
|
||||
--- The progressbar background color.
|
||||
-- @beautiful beautiful.graph_bg
|
||||
|
||||
--- The progressbar foreground color.
|
||||
-- @beautiful beautiful.graph_fg
|
||||
|
||||
--- The progressbar border color.
|
||||
-- @beautiful beautiful.graph_border_color
|
||||
|
||||
local properties = { "width", "height", "border_color",
|
||||
"color", "background_color",
|
||||
"vertical", "value", "max_value",
|
||||
"ticks", "ticks_gap", "ticks_size" }
|
||||
|
||||
function progressbar.draw(pbar, _, cr, width, height)
|
||||
local ticks_gap = data[pbar].ticks_gap or 1
|
||||
local ticks_size = data[pbar].ticks_size or 4
|
||||
|
||||
-- We want one pixel wide lines
|
||||
cr:set_line_width(1)
|
||||
|
||||
local value = data[pbar].value
|
||||
local max_value = data[pbar].max_value
|
||||
if value >= 0 then
|
||||
value = value / max_value
|
||||
end
|
||||
|
||||
local over_drawn_width = width
|
||||
local over_drawn_height = height
|
||||
local border_width = 0
|
||||
local col = data[pbar].border_color or beautiful.progressbar_border_color
|
||||
if col then
|
||||
-- Draw border
|
||||
cr:rectangle(0.5, 0.5, width - 1, height - 1)
|
||||
cr:set_source(color(col))
|
||||
cr:stroke()
|
||||
|
||||
over_drawn_width = width - 2 -- remove 2 for borders
|
||||
over_drawn_height = height - 2 -- remove 2 for borders
|
||||
border_width = 1
|
||||
end
|
||||
|
||||
cr:rectangle(border_width, border_width,
|
||||
over_drawn_width, over_drawn_height)
|
||||
cr:set_source(color(data[pbar].color or beautiful.progressbar_fg or "#ff0000"))
|
||||
cr:fill()
|
||||
|
||||
-- Cover the part that is not set with a rectangle
|
||||
if data[pbar].vertical then
|
||||
local rel_height = over_drawn_height * (1 - value)
|
||||
cr:rectangle(border_width,
|
||||
border_width,
|
||||
over_drawn_width,
|
||||
rel_height)
|
||||
cr:set_source(color(data[pbar].background_color or beautiful.progressbar_bg or "#000000aa"))
|
||||
cr:fill()
|
||||
|
||||
-- Place smaller pieces over the gradient if ticks are enabled
|
||||
if data[pbar].ticks then
|
||||
for i=0, height / (ticks_size+ticks_gap)-border_width do
|
||||
local rel_offset = over_drawn_height / 1 - (ticks_size+ticks_gap) * i
|
||||
|
||||
if rel_offset >= rel_height then
|
||||
cr:rectangle(border_width,
|
||||
rel_offset,
|
||||
over_drawn_width,
|
||||
ticks_gap)
|
||||
end
|
||||
end
|
||||
cr:set_source(color(data[pbar].background_color or beautiful.progressbar_bg or "#000000aa"))
|
||||
cr:fill()
|
||||
end
|
||||
else
|
||||
local rel_x = over_drawn_width * value
|
||||
cr:rectangle(border_width + rel_x,
|
||||
border_width,
|
||||
over_drawn_width - rel_x,
|
||||
over_drawn_height)
|
||||
cr:set_source(color(data[pbar].background_color or "#000000aa"))
|
||||
cr:fill()
|
||||
|
||||
if data[pbar].ticks then
|
||||
for i=0, width / (ticks_size+ticks_gap)-border_width do
|
||||
local rel_offset = over_drawn_width / 1 - (ticks_size+ticks_gap) * i
|
||||
|
||||
if rel_offset <= rel_x then
|
||||
cr:rectangle(rel_offset,
|
||||
border_width,
|
||||
ticks_gap,
|
||||
over_drawn_height)
|
||||
end
|
||||
end
|
||||
cr:set_source(color(data[pbar].background_color or "#000000aa"))
|
||||
cr:fill()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function progressbar.fit(pbar)
|
||||
return data[pbar].width, data[pbar].height
|
||||
end
|
||||
|
||||
--- Set the progressbar value.
|
||||
-- @param value The progress bar value between 0 and 1.
|
||||
function progressbar:set_value(value)
|
||||
value = value or 0
|
||||
local max_value = data[self].max_value
|
||||
data[self].value = math.min(max_value, math.max(0, value))
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set the progressbar height.
|
||||
-- @param height The height to set.
|
||||
function progressbar:set_height(height)
|
||||
data[self].height = height
|
||||
self:emit_signal("widget::layout_changed")
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set the progressbar width.
|
||||
-- @param width The width to set.
|
||||
function progressbar:set_width(width)
|
||||
data[self].width = width
|
||||
self:emit_signal("widget::layout_changed")
|
||||
return self
|
||||
end
|
||||
|
||||
-- Build properties function
|
||||
for _, prop in ipairs(properties) do
|
||||
if not progressbar["set_" .. prop] then
|
||||
progressbar["set_" .. prop] = function(pbar, value)
|
||||
data[pbar][prop] = value
|
||||
pbar:emit_signal("widget::redraw_needed")
|
||||
return pbar
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Create a progressbar widget.
|
||||
-- @param args Standard widget() arguments. You should add width and height
|
||||
-- key to set progressbar geometry.
|
||||
-- @return A progressbar widget.
|
||||
-- @function wibox.widget.progressbar
|
||||
function progressbar.new(args)
|
||||
args = args or {}
|
||||
local width = args.width or 100
|
||||
local height = args.height or 20
|
||||
|
||||
args.type = "imagebox"
|
||||
|
||||
local pbar = base.make_widget()
|
||||
|
||||
data[pbar] = { width = width, height = height, value = 0, max_value = 1 }
|
||||
|
||||
-- Set methods
|
||||
for _, prop in ipairs(properties) do
|
||||
pbar["set_" .. prop] = progressbar["set_" .. prop]
|
||||
end
|
||||
|
||||
pbar.draw = progressbar.draw
|
||||
pbar.fit = progressbar.fit
|
||||
|
||||
return pbar
|
||||
end
|
||||
|
||||
function progressbar.mt:__call(...)
|
||||
return progressbar.new(...)
|
||||
end
|
||||
|
||||
return setmetatable(progressbar, progressbar.mt)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
local wbase = require("wibox.widget.base")
|
||||
local beautiful = require("beautiful")
|
||||
local util = require("awful.util")
|
||||
local capi = {
|
||||
awesome = awesome,
|
||||
screen = screen
|
||||
|
@ -23,6 +24,14 @@ local base_size = nil
|
|||
local reverse = false
|
||||
local display_on_screen = "primary"
|
||||
|
||||
--- The systray background color.
|
||||
-- @beautiful beautiful.bg_systray
|
||||
-- @param string The color (string like "#ff0000" only)
|
||||
|
||||
--- The systray icon spacing.
|
||||
-- @beautiful beautiful.systray_icon_spacing
|
||||
-- @tparam[opt=0] integer The icon spacing
|
||||
|
||||
local function should_display_on(s)
|
||||
if display_on_screen == "primary" then
|
||||
return s == capi.screen.primary
|
||||
|
@ -138,12 +147,16 @@ function systray:set_screen(s)
|
|||
end
|
||||
end
|
||||
|
||||
--- Create the systray widget.
|
||||
-- Note that this widget can only exist once.
|
||||
-- @tparam boolean revers Show in the opposite direction
|
||||
-- @treturn table The new `systray` widget
|
||||
-- @function wibox.widget.systray
|
||||
|
||||
local function new(revers)
|
||||
local ret = wbase.make_widget()
|
||||
|
||||
for k, v in pairs(systray) do
|
||||
ret[k] = v
|
||||
end
|
||||
util.table.crush(ret, systray, true)
|
||||
|
||||
if revers then
|
||||
ret:set_reverse(true)
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
---------------------------------------------------------------------------
|
||||
--
|
||||
--@DOC_wibox_widget_defaults_textbox_EXAMPLE@
|
||||
-- @author Uli Schlachter
|
||||
-- @author dodo
|
||||
-- @copyright 2010, 2011 Uli Schlachter, dodo
|
||||
|
@ -10,54 +12,56 @@ local base = require("wibox.widget.base")
|
|||
local gdebug = require("gears.debug")
|
||||
local beautiful = require("beautiful")
|
||||
local lgi = require("lgi")
|
||||
local util = require("awful.util")
|
||||
local Pango = lgi.Pango
|
||||
local PangoCairo = lgi.PangoCairo
|
||||
local type = type
|
||||
local setmetatable = setmetatable
|
||||
local pairs = pairs
|
||||
|
||||
local textbox = { mt = {} }
|
||||
|
||||
--- The textbox font.
|
||||
-- @beautiful beautiful.font
|
||||
|
||||
--- Set the DPI of a Pango layout
|
||||
local function setup_dpi(box, dpi)
|
||||
if box.dpi ~= dpi then
|
||||
box.dpi = dpi
|
||||
box._ctx:set_resolution(dpi)
|
||||
box._layout:context_changed()
|
||||
if box._private.dpi ~= dpi then
|
||||
box._private.dpi = dpi
|
||||
box._private.ctx:set_resolution(dpi)
|
||||
box._private.layout:context_changed()
|
||||
end
|
||||
end
|
||||
|
||||
--- Setup a pango layout for the given textbox and dpi
|
||||
local function setup_layout(box, width, height, dpi)
|
||||
box._layout.width = Pango.units_from_double(width)
|
||||
box._layout.height = Pango.units_from_double(height)
|
||||
box._private.layout.width = Pango.units_from_double(width)
|
||||
box._private.layout.height = Pango.units_from_double(height)
|
||||
setup_dpi(box, dpi)
|
||||
end
|
||||
|
||||
--- Draw the given textbox on the given cairo context in the given geometry
|
||||
-- Draw the given textbox on the given cairo context in the given geometry
|
||||
function textbox:draw(context, cr, width, height)
|
||||
setup_layout(self, width, height, context.dpi)
|
||||
cr:update_layout(self._layout)
|
||||
local _, logical = self._layout:get_pixel_extents()
|
||||
cr:update_layout(self._private.layout)
|
||||
local _, logical = self._private.layout:get_pixel_extents()
|
||||
local offset = 0
|
||||
if self._valign == "center" then
|
||||
if self._private.valign == "center" then
|
||||
offset = (height - logical.height) / 2
|
||||
elseif self._valign == "bottom" then
|
||||
elseif self._private.valign == "bottom" then
|
||||
offset = height - logical.height
|
||||
end
|
||||
cr:move_to(0, offset)
|
||||
cr:show_layout(self._layout)
|
||||
cr:show_layout(self._private.layout)
|
||||
end
|
||||
|
||||
local function do_fit_return(self)
|
||||
local _, logical = self._layout:get_pixel_extents()
|
||||
local _, logical = self._private.layout:get_pixel_extents()
|
||||
if logical.width == 0 or logical.height == 0 then
|
||||
return 0, 0
|
||||
end
|
||||
return logical.width, logical.height
|
||||
end
|
||||
|
||||
--- Fit the given textbox
|
||||
-- Fit the given textbox
|
||||
function textbox:fit(context, width, height)
|
||||
setup_layout(self, width, height, context.dpi)
|
||||
return do_fit_return(self)
|
||||
|
@ -92,8 +96,8 @@ end
|
|||
function textbox:get_preferred_size_at_dpi(dpi)
|
||||
local max_lines = 2^20
|
||||
setup_dpi(self, dpi)
|
||||
self._layout.width = -1 -- no width set
|
||||
self._layout.height = -max_lines -- show this many lines per paragraph
|
||||
self._private.layout.width = -1 -- no width set
|
||||
self._private.layout.height = -max_lines -- show this many lines per paragraph
|
||||
return do_fit_return(self)
|
||||
end
|
||||
|
||||
|
@ -106,8 +110,8 @@ end
|
|||
function textbox:get_height_for_width_at_dpi(width, dpi)
|
||||
local max_lines = 2^20
|
||||
setup_dpi(self, dpi)
|
||||
self._layout.width = Pango.units_from_double(width)
|
||||
self._layout.height = -max_lines -- show this many lines per paragraph
|
||||
self._private.layout.width = Pango.units_from_double(width)
|
||||
self._private.layout.height = -max_lines -- show this many lines per paragraph
|
||||
local _, h = do_fit_return(self)
|
||||
return h
|
||||
end
|
||||
|
@ -121,7 +125,7 @@ end
|
|||
-- @treturn[2] boolean false
|
||||
-- @treturn[2] string Error message explaining why the markup was invalid.
|
||||
function textbox:set_markup_silently(text)
|
||||
if self._markup == text then
|
||||
if self._private.markup == text then
|
||||
return true
|
||||
end
|
||||
|
||||
|
@ -131,9 +135,9 @@ function textbox:set_markup_silently(text)
|
|||
return false, parsed.message or tostring(parsed)
|
||||
end
|
||||
|
||||
self._markup = text
|
||||
self._layout.text = parsed
|
||||
self._layout.attributes = attr
|
||||
self._private.markup = text
|
||||
self._private.layout.text = parsed
|
||||
self._private.layout.attributes = attr
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("widget::layout_changed")
|
||||
return true
|
||||
|
@ -141,9 +145,12 @@ end
|
|||
|
||||
--- Set the text of the textbox (with
|
||||
-- [Pango markup](https://developer.gnome.org/pango/stable/PangoMarkupFormat.html)).
|
||||
-- @property markup
|
||||
-- @tparam string text The text to set. This can contain pango markup (e.g.
|
||||
-- `<b>bold</b>`). You can use `awful.util.escape` to escape
|
||||
-- parts of it.
|
||||
-- @see text
|
||||
|
||||
function textbox:set_markup(text)
|
||||
local success, message = self:set_markup_silently(text)
|
||||
if not success then
|
||||
|
@ -151,96 +158,117 @@ function textbox:set_markup(text)
|
|||
end
|
||||
end
|
||||
|
||||
function textbox:get_markup()
|
||||
return self._private.markup
|
||||
end
|
||||
|
||||
--- Set a textbox' text.
|
||||
-- @property text
|
||||
-- @param text The text to display. Pango markup is ignored and shown as-is.
|
||||
-- @see markup
|
||||
|
||||
function textbox:set_text(text)
|
||||
if self._layout.text == text and self._layout.attributes == nil then
|
||||
if self._private.layout.text == text and self._private.layout.attributes == nil then
|
||||
return
|
||||
end
|
||||
self._markup = nil
|
||||
self._layout.text = text
|
||||
self._layout.attributes = nil
|
||||
self._private.markup = nil
|
||||
self._private.layout.text = text
|
||||
self._private.layout.attributes = nil
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
function textbox:get_text()
|
||||
return self._private.layout.text
|
||||
end
|
||||
|
||||
--- Set a textbox' ellipsize mode.
|
||||
-- @property ellipsize
|
||||
-- @param mode Where should long lines be shortened? "start", "middle" or "end"
|
||||
|
||||
function textbox:set_ellipsize(mode)
|
||||
local allowed = { none = "NONE", start = "START", middle = "MIDDLE", ["end"] = "END" }
|
||||
if allowed[mode] then
|
||||
if self._layout:get_ellipsize() == allowed[mode] then
|
||||
if self._private.layout:get_ellipsize() == allowed[mode] then
|
||||
return
|
||||
end
|
||||
self._layout:set_ellipsize(allowed[mode])
|
||||
self._private.layout:set_ellipsize(allowed[mode])
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
end
|
||||
|
||||
--- Set a textbox' wrap mode.
|
||||
-- @property wrap
|
||||
-- @param mode Where to wrap? After "word", "char" or "word_char"
|
||||
|
||||
function textbox:set_wrap(mode)
|
||||
local allowed = { word = "WORD", char = "CHAR", word_char = "WORD_CHAR" }
|
||||
if allowed[mode] then
|
||||
if self._layout:get_wrap() == allowed[mode] then
|
||||
if self._private.layout:get_wrap() == allowed[mode] then
|
||||
return
|
||||
end
|
||||
self._layout:set_wrap(allowed[mode])
|
||||
self._private.layout:set_wrap(allowed[mode])
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
end
|
||||
|
||||
--- Set a textbox' vertical alignment
|
||||
--- The textbox' vertical alignment
|
||||
-- @property valign
|
||||
-- @param mode Where should the textbox be drawn? "top", "center" or "bottom"
|
||||
|
||||
function textbox:set_valign(mode)
|
||||
local allowed = { top = true, center = true, bottom = true }
|
||||
if allowed[mode] then
|
||||
if self._valign == mode then
|
||||
if self._private.valign == mode then
|
||||
return
|
||||
end
|
||||
self._valign = mode
|
||||
self._private.valign = mode
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
end
|
||||
|
||||
--- Set a textbox' horizontal alignment
|
||||
--- Set a textbox' horizontal alignment.
|
||||
-- @property align
|
||||
-- @param mode Where should the textbox be drawn? "left", "center" or "right"
|
||||
|
||||
function textbox:set_align(mode)
|
||||
local allowed = { left = "LEFT", center = "CENTER", right = "RIGHT" }
|
||||
if allowed[mode] then
|
||||
if self._layout:get_alignment() == allowed[mode] then
|
||||
if self._private.layout:get_alignment() == allowed[mode] then
|
||||
return
|
||||
end
|
||||
self._layout:set_alignment(allowed[mode])
|
||||
self._private.layout:set_alignment(allowed[mode])
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
end
|
||||
|
||||
--- Set a textbox' font
|
||||
-- @property font
|
||||
-- @param font The font description as string
|
||||
|
||||
function textbox:set_font(font)
|
||||
self._layout:set_font_description(beautiful.get_font(font))
|
||||
self._private.layout:set_font_description(beautiful.get_font(font))
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
-- Returns a new textbox
|
||||
--- Create a new textbox.
|
||||
-- @tparam[opt=""] string text The textbox content
|
||||
-- @tparam[opt=false] boolean ignore_markup Ignore the pango/HTML markup
|
||||
-- @treturn table A new textbox widget
|
||||
-- @function wibox.widget.textbox
|
||||
local function new(text, ignore_markup)
|
||||
local ret = base.make_widget()
|
||||
local ret = base.make_widget(nil, nil, {enable_properties = true})
|
||||
|
||||
for k, v in pairs(textbox) do
|
||||
if type(v) == "function" then
|
||||
ret[k] = v
|
||||
end
|
||||
end
|
||||
util.table.crush(ret, textbox, true)
|
||||
|
||||
ret._dpi = -1
|
||||
ret._ctx = PangoCairo.font_map_get_default():create_context()
|
||||
ret._layout = Pango.Layout.new(ret._ctx)
|
||||
ret._private.dpi = -1
|
||||
ret._private.ctx = PangoCairo.font_map_get_default():create_context()
|
||||
ret._private.layout = Pango.Layout.new(ret._private.ctx)
|
||||
|
||||
ret:set_ellipsize("end")
|
||||
ret:set_wrap("word_char")
|
||||
|
@ -263,6 +291,10 @@ function textbox.mt.__call(_, ...)
|
|||
return new(...)
|
||||
end
|
||||
|
||||
--@DOC_widget_COMMON@
|
||||
|
||||
--@DOC_object_COMMON@
|
||||
|
||||
return setmetatable(textbox, textbox.mt)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
---------------------------------------------------------------------------
|
||||
--- Text clock widget.
|
||||
--
|
||||
-- @author Julien Danjou <julien@danjou.info>
|
||||
-- @copyright 2009 Julien Danjou
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.widget.textclock
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local setmetatable = setmetatable
|
||||
local os = os
|
||||
local textbox = require("wibox.widget.textbox")
|
||||
local timer = require("gears.timer")
|
||||
local DateTime = require("lgi").GLib.DateTime
|
||||
|
||||
local textclock = { mt = {} }
|
||||
|
||||
--- This lowers the timeout so that it occurs "correctly". For example, a timeout
|
||||
-- of 60 is rounded so that it occurs the next time the clock reads ":00 seconds".
|
||||
local function calc_timeout(real_timeout)
|
||||
return real_timeout - os.time() % real_timeout
|
||||
end
|
||||
|
||||
--- Create a textclock widget. It draws the time it is in a textbox.
|
||||
--
|
||||
-- @tparam[opt=" %a %b %d, %H:%M "] string format The time format.
|
||||
-- @tparam[opt=60] number timeout How often update the time (in seconds).
|
||||
-- @treturn table A textbox widget.
|
||||
-- @function wibox.widget.textclock
|
||||
function textclock.new(format, timeout)
|
||||
format = format or " %a %b %d, %H:%M "
|
||||
timeout = timeout or 60
|
||||
|
||||
local w = textbox()
|
||||
local t
|
||||
function w._private.textclock_update_cb()
|
||||
w:set_markup(DateTime.new_now_local():format(format))
|
||||
t.timeout = calc_timeout(timeout)
|
||||
t:again()
|
||||
return true -- Continue the timer
|
||||
end
|
||||
t = timer.weak_start_new(timeout, w._private.textclock_update_cb)
|
||||
t:emit_signal("timeout")
|
||||
return w
|
||||
end
|
||||
|
||||
function textclock.mt:__call(...)
|
||||
return textclock.new(...)
|
||||
end
|
||||
|
||||
--@DOC_widget_COMMON@
|
||||
|
||||
--@DOC_object_COMMON@
|
||||
|
||||
return setmetatable(textclock, textclock.mt)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -82,17 +82,18 @@ assert:register("assertion", "widget_layout", widget_layout, "assertion.widget_l
|
|||
return {
|
||||
widget_stub = function(width, height)
|
||||
local w = object()
|
||||
w._private = {}
|
||||
w:add_signal("widget::redraw_needed")
|
||||
w:add_signal("widget::layout_changed")
|
||||
w.is_widget = true
|
||||
w.visible = true
|
||||
w.opacity = 1
|
||||
w._private.visible = true
|
||||
w._private.opacity = 1
|
||||
if width or height then
|
||||
w.fit = function()
|
||||
return width or 10, height or 10
|
||||
end
|
||||
end
|
||||
w._widget_caches = {}
|
||||
w._private.widget_caches = {}
|
||||
|
||||
return w
|
||||
end,
|
||||
|
|
|
@ -13,7 +13,7 @@ return { create_wibox = function()
|
|||
|
||||
-- Widgets that are aligned to the right
|
||||
local right_layout = wibox.layout.fixed.horizontal()
|
||||
local textclock = awful.widget.textclock()
|
||||
local textclock = wibox.widget.textclock()
|
||||
right_layout:add(textclock)
|
||||
right_layout:add(awful.widget.layoutbox(1))
|
||||
|
||||
|
|
|
@ -144,11 +144,16 @@ function(run_test test_path namespace template escaped_content)
|
|||
get_filename_component(${test_path} TEST_FILE_NAME NAME)
|
||||
set(IMAGE_PATH "${IMAGE_DIR}/AUTOGEN${namespace}_${TEST_FILE_NAME}")
|
||||
|
||||
# Use the example testing as coverage source
|
||||
if (USE_LCOV)
|
||||
set(LCOV_PATH ${SOURCE_DIR}/.luacov)
|
||||
endif()
|
||||
|
||||
# Execute the script, leave the image extension decision to the test
|
||||
# SVG is preferred, but PNG is better suited for some tests, like bitmap
|
||||
# patterns.
|
||||
execute_process(
|
||||
COMMAND lua ${template} ${test_path} ${IMAGE_PATH} ${SOURCE_DIR}/.luacov
|
||||
COMMAND lua ${template} ${test_path} ${IMAGE_PATH} ${LCOV_PATH}
|
||||
OUTPUT_VARIABLE TEST_OUTPUT
|
||||
ERROR_VARIABLE TEST_ERROR
|
||||
)
|
||||
|
|
|
@ -30,7 +30,7 @@ local function show(cr, skip_fill)
|
|||
cr:clip()
|
||||
end
|
||||
|
||||
local cr = get_surface(svgpath)
|
||||
local cr = get_surface(svgpath..".svg")
|
||||
cr:translate(3,3)
|
||||
|
||||
loadfile(filepath)(shape, cr, show)
|
|
@ -1,5 +1,29 @@
|
|||
local lgi = require("lgi")
|
||||
local Pango = lgi.Pango
|
||||
local cairo = lgi.cairo
|
||||
|
||||
-- A simple Awesome logo
|
||||
local function logo()
|
||||
local img = cairo.ImageSurface.create(cairo.Format.ARGB32, 22, 22)
|
||||
local cr = cairo.Context(img)
|
||||
|
||||
-- Awesome default #555555
|
||||
cr:set_source_rgb(0.21568627451, 0.21568627451, 0.21568627451)
|
||||
cr:paint()
|
||||
|
||||
cr:set_source_rgb(1,1,1)
|
||||
|
||||
cr:rectangle(0, 7, 15, 1)
|
||||
cr:fill()
|
||||
|
||||
cr:rectangle(15, 15, 1, 7)
|
||||
cr:fill()
|
||||
|
||||
cr:rectangle(8, 15, 7, 1)
|
||||
cr:fill()
|
||||
|
||||
return img
|
||||
end
|
||||
|
||||
-- Default theme for the documentation examples
|
||||
local module = {
|
||||
|
@ -10,9 +34,17 @@ local module = {
|
|||
border_width = 1.5 ,
|
||||
|
||||
-- Fake resources handling
|
||||
xresources = require("beautiful.xresources")
|
||||
xresources = require("beautiful.xresources"),
|
||||
|
||||
awesome_icon = logo()
|
||||
}
|
||||
|
||||
module.graph_bg = module.bg_normal
|
||||
module.graph_fg = module.bg_highlight
|
||||
|
||||
module.progressbar_bg = module.bg_normal
|
||||
module.progressbar_fg = module.bg_highlight
|
||||
|
||||
local f = Pango.FontDescription.from_string("sans 8")
|
||||
|
||||
function module.get_font()
|
||||
|
|
|
@ -10,17 +10,17 @@ parent : setup {
|
|||
{
|
||||
text_widget,
|
||||
bg = '#ff0000',
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
{
|
||||
text_widget,
|
||||
bg = '#00ff00',
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
{
|
||||
text_widget,
|
||||
bg = '#0000ff',
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
spacing = 10,
|
||||
layout = wibox.layout.fixed.vertical
|
|
@ -13,7 +13,7 @@ parent : setup {
|
|||
shape = gears.shape.circle,
|
||||
bg = beautiful.bg_normal,
|
||||
shape_border_color = beautiful.border_color,
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
{
|
||||
-- To solve this, clip the content
|
||||
|
@ -25,7 +25,7 @@ parent : setup {
|
|||
shape = gears.shape.circle,
|
||||
bg = beautiful.bg_normal,
|
||||
shape_border_color = beautiful.border_color,
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
spacing = 10,
|
||||
layout = wibox.layout.fixed.vertical
|
|
@ -10,17 +10,17 @@ parent : setup {
|
|||
{
|
||||
text_widget,
|
||||
fg = '#ff0000',
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
{
|
||||
text_widget,
|
||||
fg = '#00ff00',
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
{
|
||||
text_widget,
|
||||
fg = '#0000ff',
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
spacing = 10,
|
||||
layout = wibox.layout.fixed.vertical
|
|
@ -14,7 +14,7 @@ parent : setup {
|
|||
bg = beautiful.bg_normal,
|
||||
shape_border_color = beautiful.border_color,
|
||||
shape_border_width = beautiful.border_width,
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
{
|
||||
-- To solve this, use a margin
|
||||
|
@ -27,13 +27,13 @@ parent : setup {
|
|||
right = 10,
|
||||
top = 3,
|
||||
bottom = 3,
|
||||
widget = wibox.layout.margin
|
||||
widget = wibox.container.margin
|
||||
},
|
||||
shape = gears.shape.hexagon,
|
||||
bg = beautiful.bg_normal,
|
||||
shape_border_color = beautiful.border_color,
|
||||
shape_border_width = beautiful.border_width,
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
spacing = 10,
|
||||
layout = wibox.layout.fixed.vertical
|
|
@ -0,0 +1,24 @@
|
|||
--DOC_HIDE_ALL
|
||||
local wibox = require("wibox")
|
||||
local gears = {shape = require("gears.shape")}
|
||||
local beautiful = require("beautiful")
|
||||
|
||||
return {
|
||||
text = "Before",
|
||||
align = "center",
|
||||
valign = "center",
|
||||
widget = wibox.widget.textbox,
|
||||
},
|
||||
{
|
||||
{
|
||||
text = "After",
|
||||
align = "center",
|
||||
valign = "center",
|
||||
widget = wibox.widget.textbox,
|
||||
},
|
||||
shape = gears.shape.circle,
|
||||
shape_border_width = 5,
|
||||
shape_border_color = "#ff0000",
|
||||
bg = beautiful.bg_highlight,
|
||||
widget = wibox.container.background
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
--DOC_HIDE_ALL
|
||||
local wibox = require("wibox")
|
||||
|
||||
return {
|
||||
text = "Some long text",
|
||||
align = "center",
|
||||
valign = "center",
|
||||
widget = wibox.widget.textbox,
|
||||
},
|
||||
{
|
||||
{
|
||||
{
|
||||
{
|
||||
text = "Some long text",
|
||||
align = "center",
|
||||
valign = "center",
|
||||
widget = wibox.widget.textbox,
|
||||
},
|
||||
strategy = "max",
|
||||
height = 8,
|
||||
width = 50,
|
||||
widget = wibox.container.constraint
|
||||
},
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
},
|
||||
layout = wibox.layout.fixed.vertical,
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
--DOC_HIDE_ALL
|
||||
local wibox = require("wibox")
|
||||
local beautiful = require("beautiful")
|
||||
|
||||
return {
|
||||
nil,
|
||||
{
|
||||
nil,
|
||||
{
|
||||
{
|
||||
text = "Before",
|
||||
align = "center",
|
||||
valign = "center",
|
||||
widget = wibox.widget.textbox,
|
||||
},
|
||||
bg = beautiful.bg_highlight,
|
||||
widget = wibox.container.background
|
||||
},
|
||||
nil,
|
||||
expand = "none",
|
||||
layout = wibox.layout.align.horizontal,
|
||||
},
|
||||
nil,
|
||||
expand = "none",
|
||||
layout = wibox.layout.align.vertical,
|
||||
},
|
||||
{
|
||||
nil,
|
||||
{
|
||||
nil,
|
||||
{
|
||||
{
|
||||
{
|
||||
text = "After",
|
||||
align = "center",
|
||||
valign = "center",
|
||||
widget = wibox.widget.textbox,
|
||||
},
|
||||
bg = beautiful.bg_highlight,
|
||||
widget = wibox.container.background
|
||||
},
|
||||
top = 5,
|
||||
left = 20,
|
||||
color = "#ff0000",
|
||||
widget = wibox.container.margin,
|
||||
},
|
||||
nil,
|
||||
expand = "none",
|
||||
layout = wibox.layout.align.horizontal,
|
||||
},
|
||||
nil,
|
||||
expand = "none",
|
||||
layout = wibox.layout.align.vertical,
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
--DOC_HIDE_ALL
|
||||
local wibox = require("wibox")
|
||||
|
||||
return {
|
||||
text = "Before",
|
||||
align = "center",
|
||||
valign = "center",
|
||||
widget = wibox.widget.textbox,
|
||||
},
|
||||
{
|
||||
{
|
||||
text = "After",
|
||||
align = "center",
|
||||
valign = "center",
|
||||
widget = wibox.widget.textbox,
|
||||
},
|
||||
reflection = {horizontal = true},
|
||||
widget = wibox.container.mirror
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
--DOC_HIDE_ALL
|
||||
local wibox = require("wibox")
|
||||
|
||||
return {
|
||||
text = "Before",
|
||||
align = "center",
|
||||
valign = "center",
|
||||
widget = wibox.widget.textbox,
|
||||
},
|
||||
{
|
||||
{
|
||||
text = "After",
|
||||
align = "center",
|
||||
valign = "center",
|
||||
widget = wibox.widget.textbox,
|
||||
},
|
||||
direction = "east",
|
||||
widget = wibox.container.rotate
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
local file_path, image_path, luacovpath = ...
|
||||
|
||||
-- Set the global shims
|
||||
-- luacheck: globals awesome client tag drawin screen
|
||||
awesome = require( "awesome" )
|
||||
client = require( "client" )
|
||||
tag = require( "tag" )
|
||||
drawin = require( "drawin" )
|
||||
screen = require( "screen" )
|
||||
|
||||
-- Force luacheck to be silent about setting those as unused globals
|
||||
assert(awesome and client and tag)
|
||||
|
||||
local beautiful = require( "beautiful" )
|
||||
local wibox = require( "wibox" )
|
||||
local surface = require( "gears.surface" )
|
||||
local shape = require( "gears.shape" )
|
||||
|
||||
-- If luacov is available, use it. Else, do nothing.
|
||||
pcall(function()
|
||||
require("luacov.runner")(luacovpath)
|
||||
end)
|
||||
|
||||
-- Let the test request a size and file format
|
||||
local before, after = loadfile(file_path)()
|
||||
|
||||
local container = wibox.widget {
|
||||
{
|
||||
{
|
||||
{
|
||||
before,
|
||||
shape_border_color = beautiful.border_color,
|
||||
shape_border_width = beautiful.border_width,
|
||||
shape = shape.rounded_rect,
|
||||
widget = wibox.container.background,
|
||||
},
|
||||
strategy = 'exact',
|
||||
width = 70,
|
||||
height = 40,
|
||||
widget = wibox.container.constraint
|
||||
},
|
||||
{
|
||||
{
|
||||
{
|
||||
text = " ",
|
||||
widget = wibox.widget.textbox,
|
||||
},
|
||||
bg = beautiful.bg_normal,
|
||||
shape_border_color = beautiful.border_color,
|
||||
shape_border_width = beautiful.border_width,
|
||||
widget = wibox.container.background,
|
||||
shape = shape.transform(shape.arrow)
|
||||
: rotate_at(15,15,math.pi/2)
|
||||
: translate(0,-8)
|
||||
: scale(0.9, 0.9),
|
||||
},
|
||||
strategy = 'exact',
|
||||
width = 42,
|
||||
height = 40,
|
||||
widget = wibox.container.constraint
|
||||
},
|
||||
{
|
||||
{
|
||||
after,
|
||||
shape_border_color = beautiful.border_color,
|
||||
shape_border_width = beautiful.border_width,
|
||||
shape = shape.rounded_rect,
|
||||
widget = wibox.container.background,
|
||||
},
|
||||
strategy = 'exact',
|
||||
width = 70,
|
||||
height = 40,
|
||||
widget = wibox.container.constraint
|
||||
},
|
||||
layout = wibox.layout.align.horizontal
|
||||
},
|
||||
margins = 10,
|
||||
widget = wibox.container.margin,
|
||||
}
|
||||
|
||||
-- Emulate the event loop for 10 iterations
|
||||
for _ = 1, 10 do
|
||||
awesome:emit_signal("refresh")
|
||||
end
|
||||
|
||||
-- Get the example fallback size (the tests can return a size if the want)
|
||||
local f_w, f_h = container:fit({dpi=96}, 9999, 9999)
|
||||
|
||||
-- Save to the output file
|
||||
local img = surface.widget_to_svg(container, image_path..".svg", f_w, f_h)
|
||||
img:finish()
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
local parent = ... --DOC_HIDE
|
||||
local wibox = require("wibox") --DOC_HIDE
|
||||
local gears = {shape = require("gears.shape")} --DOC_HIDE
|
||||
local beautiful = require("beautiful") --DOC_HIDE
|
||||
|
||||
local function create_arrow(text) --DOC_HIDE
|
||||
return { --DOC_HIDE
|
||||
{ --DOC_HIDE
|
||||
{ --DOC_HIDE
|
||||
text = text, --DOC_HIDE
|
||||
align = "center", --DOC_HIDE
|
||||
valign = "center", --DOC_HIDE
|
||||
widget = wibox.widget.textbox, --DOC_HIDE
|
||||
}, --DOC_HIDE
|
||||
shape = gears.shape.arrow, --DOC_HIDE
|
||||
bg = beautiful.bg_normal, --DOC_HIDE
|
||||
shape_border_color = beautiful.border_color, --DOC_HIDE
|
||||
shape_border_width = beautiful.border_width, --DOC_HIDE
|
||||
widget = wibox.container.background --DOC_HIDE
|
||||
}, --DOC_HIDE
|
||||
strategy = 'exact', --DOC_HIDE
|
||||
width = 70, --DOC_HIDE
|
||||
height = 70, --DOC_HIDE
|
||||
widget = wibox.container.constraint --DOC_HIDE
|
||||
} --DOC_HIDE
|
||||
end --DOC_HIDE
|
||||
|
||||
local normal = create_arrow("Normal")
|
||||
|
||||
local north = wibox.container {
|
||||
create_arrow("North"),
|
||||
|
||||
direction = "north",
|
||||
widget = wibox.container.rotate
|
||||
}
|
||||
|
||||
local south = wibox.container {
|
||||
create_arrow("South"),
|
||||
|
||||
direction = "south",
|
||||
widget = wibox.container.rotate
|
||||
}
|
||||
|
||||
local east = wibox.container {
|
||||
create_arrow("East"),
|
||||
|
||||
direction = "east",
|
||||
widget = wibox.container.rotate
|
||||
}
|
||||
|
||||
local west = wibox.container {
|
||||
create_arrow("West"),
|
||||
|
||||
direction = "west",
|
||||
widget = wibox.container.rotate
|
||||
}
|
||||
|
||||
parent : setup { --DOC_HIDE
|
||||
normal, --DOC_HIDE
|
||||
north, --DOC_HIDE
|
||||
south, --DOC_HIDE
|
||||
east, --DOC_HIDE
|
||||
west, --DOC_HIDE
|
||||
spacing = 10, --DOC_HIDE
|
||||
layout = wibox.layout.fixed.horizontal --DOC_HIDE
|
||||
} --DOC_HIDE
|
|
@ -0,0 +1,10 @@
|
|||
local generic_widget = ... --DOC_HIDE
|
||||
local wibox = require("wibox") --DOC_HIDE
|
||||
|
||||
return --DOC_HIDE
|
||||
wibox.widget {
|
||||
generic_widget( "first" ),
|
||||
generic_widget( "second" ),
|
||||
generic_widget( "third" ),
|
||||
layout = wibox.layout.align.horizontal
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
local generic_widget = ... --DOC_HIDE
|
||||
local wibox = require("wibox") --DOC_HIDE
|
||||
|
||||
return --DOC_HIDE
|
||||
wibox.widget {
|
||||
generic_widget( "first" ),
|
||||
generic_widget( "second" ),
|
||||
generic_widget( "third" ),
|
||||
layout = wibox.layout.fixed.horizontal
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
local generic_widget = ... --DOC_HIDE
|
||||
local wibox = require("wibox") --DOC_HIDE
|
||||
|
||||
return --DOC_HIDE
|
||||
wibox.widget {
|
||||
generic_widget( "first" ),
|
||||
generic_widget( "second" ),
|
||||
generic_widget( "third" ),
|
||||
layout = wibox.layout.flex.horizontal
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
local generic_widget = ... --DOC_HIDE
|
||||
local wibox = require("wibox") --DOC_HIDE
|
||||
|
||||
local w = wibox.widget {
|
||||
generic_widget( "first" ),
|
||||
generic_widget( "second" ),
|
||||
generic_widget( "third" ),
|
||||
layout = wibox.layout.ratio.horizontal
|
||||
}
|
||||
|
||||
w:ajust_ratio(2, 0.44, 0.33, 0.22)
|
||||
|
||||
return w --DOC_HIDE
|
|
@ -0,0 +1,10 @@
|
|||
local generic_widget = ... --DOC_HIDE
|
||||
local wibox = require("wibox") --DOC_HIDE
|
||||
|
||||
return --DOC_HIDE
|
||||
wibox.widget {
|
||||
generic_widget( "first" ),
|
||||
generic_widget( "second" ),
|
||||
generic_widget( "third" ),
|
||||
layout = wibox.layout.stack
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
local file_path, image_path, luacovpath = ...
|
||||
|
||||
-- Set the global shims
|
||||
-- luacheck: globals awesome client tag drawin screen
|
||||
awesome = require( "awesome" )
|
||||
client = require( "client" )
|
||||
tag = require( "tag" )
|
||||
drawin = require( "drawin" )
|
||||
screen = require( "screen" )
|
||||
|
||||
-- Force luacheck to be silent about setting those as unused globals
|
||||
assert(awesome and client and tag)
|
||||
|
||||
local wibox = require( "wibox" )
|
||||
local surface = require( "gears.surface" )
|
||||
local color = require( "gears.color" )
|
||||
local beautiful = require( "beautiful" )
|
||||
|
||||
-- If luacov is available, use it. Else, do nothing.
|
||||
pcall(function()
|
||||
require("luacov.runner")(luacovpath)
|
||||
end)
|
||||
|
||||
-- Create a generic rectangle widget to show layout disposition
|
||||
local function generic_widget(text)
|
||||
return {
|
||||
{
|
||||
{
|
||||
draw = function(_, _, cr, width, height)
|
||||
cr:set_source(color(beautiful.bg_normal))
|
||||
cr:set_line_width(3)
|
||||
cr:rectangle(0, 0, width, height)
|
||||
cr:fill_preserve()
|
||||
cr:set_source(color(beautiful.border_color))
|
||||
cr:stroke()
|
||||
end,
|
||||
widget = wibox.widget.base.make_widget
|
||||
},
|
||||
text and {
|
||||
align = "center",
|
||||
valign = "center",
|
||||
text = text,
|
||||
widget = wibox.widget.textbox
|
||||
} or nil,
|
||||
widget = wibox.layout.stack
|
||||
},
|
||||
margins = 5,
|
||||
widget = wibox.container.margin,
|
||||
}
|
||||
end
|
||||
|
||||
-- Let the test request a size and file format
|
||||
local widget, w, h = loadfile(file_path)(generic_widget)
|
||||
|
||||
-- Emulate the event loop for 10 iterations
|
||||
for _ = 1, 10 do
|
||||
awesome:emit_signal("refresh")
|
||||
end
|
||||
|
||||
-- Save to the output file
|
||||
local img = surface["widget_to_svg"](widget, image_path..".svg", w or 200, h or 30)
|
||||
img:finish()
|
|
@ -0,0 +1,22 @@
|
|||
local parent = ... --DOC_HIDE
|
||||
local wibox = require("wibox") --DOC_HIDE
|
||||
|
||||
local data = { --DOC_HIDE
|
||||
3, 5, 6,4, 11,15,19,29,17,17,14,0,0,3,1,0,0, 22, 17,7, 1,0,0,5, --DOC_HIDE
|
||||
3, 5, 6,4, 11,15,19,29,17,17,14,0,0,3,1,0,0, 22, 17,7, 1,0,0,5, --DOC_HIDE
|
||||
3, 5, 6,4, 11,15,19,29,17,17,14,0,0,3,1,0,0, 22, 17,7, 1,0,0,5, --DOC_HIDE
|
||||
3, 5, 6,4, 11,15,19,29,17,17,14,0,0,3,1,0,0, 22, 17,7, 1,0,0,5, --DOC_HIDE
|
||||
3, 5, 6,4, 11,15,19,29,17,17,14,0,0,3,1,0,0, 22, 17,7, 1,0,0,5, --DOC_HIDE
|
||||
} --DOC_HIDE
|
||||
|
||||
local w = --DOC_HIDE
|
||||
wibox.widget {
|
||||
max_value = 29,
|
||||
widget = wibox.widget.graph
|
||||
}
|
||||
|
||||
parent:add( w ) --DOC_HIDE
|
||||
|
||||
for _, v in ipairs(data) do --DOC_HIDE
|
||||
w:add_value(v) --DOC_HIDE
|
||||
end --DOC_HIDE
|
|
@ -0,0 +1,13 @@
|
|||
local parent = ... --DOC_HIDE
|
||||
local wibox = require( "wibox" ) --DOC_HIDE
|
||||
local beautiful = require( "beautiful" ) --DOC_HIDE
|
||||
|
||||
parent:add( --DOC_HIDE
|
||||
|
||||
wibox.widget {
|
||||
image = beautiful.awesome_icon,
|
||||
resize = false,
|
||||
widget = wibox.widget.imagebox
|
||||
}
|
||||
|
||||
) --DOC_HIDE
|
|
@ -0,0 +1,12 @@
|
|||
local parent = ... --DOC_HIDE
|
||||
local wibox = require("wibox") --DOC_HIDE
|
||||
|
||||
parent:add( --DOC_HIDE
|
||||
|
||||
wibox.widget {
|
||||
max_value = 1,
|
||||
value = 0.33,
|
||||
widget = wibox.widget.progressbar
|
||||
}
|
||||
|
||||
) --DOC_HIDE
|
|
@ -0,0 +1,13 @@
|
|||
local parent = ... --DOC_HIDE
|
||||
local wibox = require("wibox") --DOC_HIDE
|
||||
|
||||
parent:add( --DOC_HIDE
|
||||
|
||||
wibox.widget{
|
||||
markup = "This <i>is</i> a <b>textbox</b>!!!",
|
||||
align = "center",
|
||||
valign = "center",
|
||||
widget = wibox.widget.textbox
|
||||
}
|
||||
|
||||
) --DOC_HIDE
|
|
@ -30,14 +30,14 @@ table.insert(steps, function()
|
|||
widget = wibox.widget.textbox,
|
||||
},
|
||||
bg = "#ff0000",
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
{
|
||||
{
|
||||
widget = button,
|
||||
},
|
||||
bg = "#ff00ff",
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
{
|
||||
{
|
||||
|
@ -45,14 +45,14 @@ table.insert(steps, function()
|
|||
widget = wibox.widget.textbox,
|
||||
},
|
||||
bg = "#0000ff",
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
layout = wibox.layout.flex.vertical
|
||||
}
|
||||
|
||||
awful.placement.centered(w)
|
||||
|
||||
img = button._image
|
||||
img = button._private.image
|
||||
assert(img)
|
||||
|
||||
return true
|
||||
|
@ -68,7 +68,7 @@ table.insert(steps, function()
|
|||
end)
|
||||
|
||||
table.insert(steps, function()
|
||||
assert(button._image ~= img)
|
||||
assert(button._private.image ~= img)
|
||||
|
||||
return true
|
||||
end)
|
||||
|
@ -77,14 +77,14 @@ end)
|
|||
table.insert(steps, function()
|
||||
root.fake_input("button_release", 1)
|
||||
|
||||
assert(button._image ~= img)
|
||||
assert(button._private.image ~= img)
|
||||
|
||||
return true
|
||||
end)
|
||||
|
||||
-- Test a button press/release outside of the widget
|
||||
table.insert(steps, function()
|
||||
assert(button._image == img)
|
||||
assert(button._private.image == img)
|
||||
|
||||
root.fake_input("button_press", 1)
|
||||
|
||||
|
@ -92,14 +92,14 @@ table.insert(steps, function()
|
|||
end)
|
||||
|
||||
table.insert(steps, function()
|
||||
assert(button._image ~= img)
|
||||
assert(button._private.image ~= img)
|
||||
|
||||
return true
|
||||
end)
|
||||
|
||||
table.insert(steps, function()
|
||||
-- just make sure the button is not released for nothing
|
||||
assert(button._image ~= img)
|
||||
assert(button._private.image ~= img)
|
||||
|
||||
-- test if the button is released when the mouse move out
|
||||
awful.placement.right(mouse--[[, {parent = w}]])
|
||||
|
@ -109,7 +109,7 @@ table.insert(steps, function()
|
|||
end)
|
||||
|
||||
table.insert(steps, function()
|
||||
assert(button._image == img)
|
||||
assert(button._private.image == img)
|
||||
|
||||
return true
|
||||
end)
|
||||
|
|
|
@ -63,7 +63,7 @@ collectable(wibox.layout.align.horizontal())
|
|||
-- Then some random widgets from awful
|
||||
collectable(awful.widget.launcher({ image = cairo.ImageSurface(cairo.Format.ARGB32, 20, 20), command = "bash" }))
|
||||
collectable(awful.widget.prompt())
|
||||
collectable(awful.widget.textclock())
|
||||
collectable(wibox.widget.textclock())
|
||||
collectable(awful.widget.layoutbox(1))
|
||||
|
||||
-- Some widgets do things via timer.delayed_call
|
||||
|
|
Loading…
Reference in New Issue