10 KiB
layout |
---|
page |
Lists
This type of UI element is also called menu (for example in GTK). As an example let's create a bookmarks widget - a widget will show a static list of sites. If item in the list is clicked - the site will be opened in the browser. You can find the created widget here
Prerequisite
Create a bookmark-widget.lua file under ~/.config/awesome/tutorials folder. Then include it in your rc.lua and add widget to the wibox:
local bookmark_widget = require("tutorials.bookmark-widget.bookmark-widget")
...
s.mytasklist, -- Middle widget
{ -- Right widgets
...
bookmark_widget
To have a list popup, first we need to have an "anchor" widget, clicking on which should toggle the visibility of the list, so let's create it, it will be an icon:
local awful = require("awful")
local wibox = require("wibox")
local gears = require("gears")
local beautiful = require("beautiful")
local HOME = os.getenv('HOME')
local ICON_DIR = HOME .. '/home-dev/awesome-wm-widget-tutorial/awesome-wm-widgets/bookmark-widget/icons/'
local bookmark_widget = wibox.widget {
{
image = ICON_DIR .. 'bookmark.svg',
resize = true,
widget = wibox.widget.imagebox,
},
margins = 4,
widget = wibox.container.margin
}
-- code mentioned below goes here
return bookmark_widget
Now restart awesome and boom! - you have a widget:
![1]({{ "/assets/img/tips/lists/1.png" | relative_url }}){:.center-image}
Widget structure
We are going to use an awful.popup as it's quite easy to show/hide it and also to place it on the screen. On the popup we'll add text and image widgets, arranged in a vertical list using layout.fixed layout plus container.margin and container.background to make it look nice and to change the background color on mouse hover:
![widget structure]({{ "/assets/img/tips/lists/bookmark_structure.png" | relative_url }}){:.center-image}
Let's start
Each item in the list will have three components: an icon, a text and an url to open when the item is clicked. Let's represent it in lua:
local menu_items = {
{ name = 'Reddit', icon_name = 'reddit.svg', url = 'https://www.reddit.com/' },
{ name = 'StackOverflow', icon_name = 'stackoverflow.svg', url = 'http://github.com/' },
{ name = 'GitHub', icon_name = 'github.svg', url = 'https://stackoverflow.com/' },
}
Then let's define a popup and rows (which will hold the vertical layout), to which we will add items later on:
local popup = awful.popup {
ontop = true,
visible = false, -- should be hidden when created
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, 4)
end,
border_width = 1,
border_color = beautiful.bg_focus,
maximum_width = 400,
offset = { y = 5 },
widget = {}
}
local rows = { layout = wibox.layout.fixed.vertical }
Now we'll just traverse over the menu_items
, create a row (let's start with a simple textbox widget), add it to rows and then add rows to the popup:
for _, item in ipairs(menu_items) do
local row = wibox.widget {
text = item.name,
widget = wibox.widget.textbox
}
table.insert(rows, row)
end
popup:setup(rows)
The last thing left is to toggle popup visibility on mouse click on the bookmark_widget
:
bookmark_widget:buttons(
awful.util.table.join(
awful.button({}, 1, function()
if popup.visible then
popup.visible = not popup.visible
else
popup:move_next_to(mouse.current_widget_geometry)
end
end))
)
Restart awesome and click on the widget:
![1]({{ "/assets/img/tips/lists/1_1.png" | relative_url }}){:.center-image}
Make it pretty
To add an icon let's wrap textbox in a fixed.horizontal layout and add an imagebox with an icon in front of it. Note that it's important to set the maximum height and width of the image, otherwise it will take up all available space:
Looks ok, but icon and text are too close to each other. One way to fix it is to use a spacing property of the fixed layout, which sets the distance between widgets:
Now let's add margins around each item:
One more step is to wrap margins in a background. Visually it won't change anything (unless you want to change the default color, which is bg_normal
from your theme), but it will be useful later, when we will add mouse hover effect to the menu item
Looks good now! Let's add some interactivity, like changing background on mouse hover, note that c
in the callback function's parameter is a row
, defined above, which is a background widget, so we can set the background color with set_bg
method:
Let's also change a cursor:
Make it work
The last bit is to open the link, when mouse is clicked. We'll use the buttons method which accepts a table of buttons. First parameter is a table with modifiers (we use none), second is a button number (1 is a left mouse button), third parameter is a callback function which is called on press action. When mouse button is clicked we want to hide the popup and open the link in the default browser. xdg-open is used exactly for that:
row:buttons(
awful.util.table.join(
awful.button({}, 1, function()
popup.visible = not popup.visible
awful.spawn.with_shell('xdg-open ' .. item.url)
end)
)
)
Future improvements
The menu or list widget, created above, looks pretty standard, as it has icon and text. However, playing with different layouts you can add more items to it, for example you may follow material design guidance and create lists with many components, like three-lines lists with visuals and controls. As an example here is a list from gitlab widget:
And another one from github-activity-widget:
![1]({{ "/assets/img/tips/lists/github.png" | relative_url }}){:.center-image}
And one more from docker widget:
![1]({{ "/assets/img/tips/lists/docker.png" | relative_url }}){:.center-image}
Widget described above can be found here