cleanup: Remove overlay/underlay hacks, re-implement as widgets container

There is a new widget called `infoshapes`. It support all the features
from the underlay system, but is a lot less intrusive. This allow to
make some code simpler.

This is another step in getting rid of all the hacks.
This commit is contained in:
Emmanuel Lepage Vallee 2016-02-28 02:04:51 -05:00
parent 0719485f49
commit 18c9071baf
18 changed files with 500 additions and 587 deletions

View File

@ -146,13 +146,6 @@ mytextbox:set_tooltip("foo bar")
``` ```
### "Underlay"
The "underlay" is the opposite of an overlay. Think of it as a background label.
Radical add this option to all Awesome widget by calling the `set_underlay`
method. The first argument is the text (or table of string) and the second is
an array with the `style`, `color` and `alpha` keys.
## Options ## Options
Radical offer a (very, very) wide range of options to allow the creation of rich Radical offer a (very, very) wide range of options to allow the creation of rich
@ -189,14 +182,6 @@ Multiple items can have multiple sets of options.
| show_filter | Show a filter widget at the bottom | boolean | | show_filter | Show a filter widget at the bottom | boolean |
| filter_string | Default filter string | string | | filter_string | Default filter string | string |
| fkeys_prefix | Display F1-F12 indicators for easy navigation | boolean | | fkeys_prefix | Display F1-F12 indicators for easy navigation | boolean |
| underlay_alpha | Underlay (see item options) opacity | 0-1 |
| underlay_style | Underlay (see item options) opacity | |
| underlay_align | Underlay alignment | "left" or "center" |
| underlay_bg | Fallback background color for missing states | color/gradient/pattern |
| overlay_alpha | Overlay (see item options) opacity | 0-1 |
| overlay_style | Overlay (see item options) opacity | |
| overlay_align | Overlay alignment | "left" or "center" |
| overlay_bg | Fallback background color for missing states | color/gradient/pattern |
| filter_prefix | Text to be shown at begenning of the filter string | string | | filter_prefix | Text to be shown at begenning of the filter string | string |
| max_items | Maximum number of items before showing scrollbar | number | | max_items | Maximum number of items before showing scrollbar | number |
| enable_keyboard | Enable or disable keyboard navigation / hooks | boolean | | enable_keyboard | Enable or disable keyboard navigation / hooks | boolean |
@ -226,7 +211,6 @@ Multiple items can have multiple sets of options.
| selected | Select this item | boolean | | selected | Select this item | boolean |
| checkable | Is the item dual state (a checkbox) | boolean | | checkable | Is the item dual state (a checkbox) | boolean |
| checked | Is the item checked or not | boolean | | checked | Is the item checked or not | boolean |
| underlay | Text to render at the far-right of the item | [array of] string |
| prefix_widget | Widget to append at the begenning of the item| widget | | prefix_widget | Widget to append at the begenning of the item| widget |
| suffix_widget | Widget to append at the end of the item | widget | | suffix_widget | Widget to append at the end of the item | widget |
| style | Custom item_style for this item | item_style | | style | Custom item_style for this item | item_style |
@ -239,12 +223,7 @@ Multiple items can have multiple sets of options.
| button5 | Scroll down action | function | | button5 | Scroll down action | function |
| overlay | See menu.overlay | function | | overlay | See menu.overlay | function |
| margins | Read/Write table (left,right,top and bottom) | dynamic table | | margins | Read/Write table (left,right,top and bottom) | dynamic table |
| underlay_alpha | Underlay (see item options) opacity | 0-1 | | infoshapes | See the infoshapes widget documentation | array of infoshapes|
| underlay_style | Underlay (see item options) opacity | |
| underlay_align | Underlay alignment | "left" or "center" |
| overlay_alpha | Overlay (see item options) opacity | 0-1 |
| overlay_style | Overlay (see item options) opacity | |
| overlay_align | Overlay alignment | "left" or "center" |
| overlay_draw | Draw a custom painter on top of the item | draw function | | overlay_draw | Draw a custom painter on top of the item | draw function |
###Colors options ###Colors options
@ -371,7 +350,6 @@ Radical also use the some of the same theme options as awful.menu, plus some:
| menu_opacity | Use your favorite compositor | Number (0=0%, 1=100%) | | menu_opacity | Use your favorite compositor | Number (0=0%, 1=100%) |
| menu_draw_underlay | Function returning the underlay pixmap | function(array,width) | | menu_draw_underlay | Function returning the underlay pixmap | function(array,width) |
| menu_icon_transformation | The function used to draw the icon | function(image,data,item) | | menu_icon_transformation | The function used to draw the icon | function(image,data,item) |
| underlay_alpha | Alpha for underlays | Number (0 to 1) |
| menu_corner_radius | Arrow based menu corner radius | Number (default = 10) | | menu_corner_radius | Arrow based menu corner radius | Number (default = 10) |
| dock_corner_radius | The dock menu type corner radius | Number (default 10) | | dock_corner_radius | The dock menu type corner radius | Number (default 10) |
| menu_outline_color | Arrow menu outer border color | String/Gradient/Pattern | | menu_outline_color | Arrow menu outer border color | String/Gradient/Pattern |
@ -383,11 +361,9 @@ allow masks such as desaturation, tinting, invert or some matrix to be applied
on the pixmap before it is being drawn. This function take the path/surface as on the pixmap before it is being drawn. This function take the path/surface as
only parameter and return the transformed surface. only parameter and return the transformed surface.
Other elements can be added to items such as prefix, underlay and siffixes. Other elements can be added to items such as prefix and siffixes.
Those elements sometime need extra color groups. The `add_color_group` method Those elements sometime need extra color groups. The `add_color_group` method
allow to register such new category. For a common example, the underlay, it allow to register such new category.
will be possible to pass `underlay_bg_focus` or `underlay_fg_disabled` colors
or any other registered states.
Some generic menu can also register beautiful namespaces using the Some generic menu can also register beautiful namespaces using the
`add_colors_namespace` method. For example, the tasklist namespace can be used `add_colors_namespace` method. For example, the tasklist namespace can be used

View File

@ -357,15 +357,7 @@ local function new(args)
suffix_widget = args.suffix_widget or nil, suffix_widget = args.suffix_widget or nil,
prefix_widget = args.prefix_widget or nil, prefix_widget = args.prefix_widget or nil,
fkeys_prefix = args.fkeys_prefix or false, fkeys_prefix = args.fkeys_prefix or false,
underlay_alpha = args.underlay_alpha or beautiful.underlay_alpha or 0.7,
underlay_style = args.underlay_style or nil,
underlay_align = args.underlay_align or nil,
underlay_bg = args.underlay_bg or nil,
overlay_alpha = args.overlay_alpha or beautiful.overlay_alpha or 0.7,
overlay_style = args.overlay_style or nil,
overlay_align = args.overlay_align or nil,
overlay_draw = args.overlay_draw or nil, overlay_draw = args.overlay_draw or nil,
overlay_bg = args.overlay_bg or nil,
filter_underlay = args.filter_underlay or nil, filter_underlay = args.filter_underlay or nil,
filter_prefix = args.filter_prefix or "Filter:", filter_prefix = args.filter_prefix or "Filter:",
enable_keyboard = (args.enable_keyboard ~= false), enable_keyboard = (args.enable_keyboard ~= false),
@ -375,8 +367,6 @@ local function new(args)
y = args.y or 0, y = args.y or 0,
sub_menu_on = args.sub_menu_on or module.event.SELECTED, sub_menu_on = args.sub_menu_on or module.event.SELECTED,
select_on = args.select_on or module.event.HOVER, select_on = args.select_on or module.event.HOVER,
overlay = args.overlay or nil,
overlay_draw = args.overlay_draw or nil,
opacity = args.opacity or beautiful.menu_opacity or 1, opacity = args.opacity or beautiful.menu_opacity or 1,
spacing = args.spacing or nil, spacing = args.spacing or nil,
default_margins = args.default_margins or beautiful.menu_default_margins or {}, default_margins = args.default_margins or beautiful.menu_default_margins or {},

View File

@ -213,7 +213,13 @@ function module.setup_item(data,item,args)
data._internal.scroll_w["down"]:emit_signal("widget::updated") data._internal.scroll_w["down"]:emit_signal("widget::updated")
end end
-- Setup the infoshapes
if item._internal.infoshapes then
item.infoshapes = item._internal.infoshapes
end
item.widget:emit_signal("widget::updated") item.widget:emit_signal("widget::updated")
end end
return module return module
-- kate: space-indent on; indent-width 4; replace-tabs on;

View File

@ -153,7 +153,7 @@ local function new(args)
args.internal.layout_func = orientation == "vertical" and vertical or horizontal args.internal.layout_func = orientation == "vertical" and vertical or horizontal
args.layout = args.layout or args.internal.layout_func args.layout = args.layout or args.internal.layout_func
args.item_style = args.item_style or item.style args.item_style = args.item_style or item.style
-- args.item_layout = args.item_layout or item_layout args.item_layout = args.item_layout or item_layout
args[length_inv] = args[length_inv] or 40 args[length_inv] = args[length_inv] or 40
-- Create the dock -- Create the dock

View File

@ -81,15 +81,15 @@ local function is_in_tag(t,c)
return false return false
end end
local function reload_underlay(client,item) local function reload_infoshapes(client,item)
local underlays = {} local infoshapes = {}
for k,v in ipairs(client:tags()) do for k,v in ipairs(client:tags()) do
underlays[#underlays+1] = v.name infoshapes[#infoshapes+1] = {text = v.name}
end end
if item then if item then
item.underlay = underlays item.infoshapes = infoshapes
end end
return underlays return infoshapes
end end
local function reload_highlight(i) local function reload_highlight(i)
@ -155,7 +155,7 @@ local function new(args)
local c = item.client local c = item.client
if c.screen ~= scr then return end if c.screen ~= scr then return end
client2.toggletag (t, c) client2.toggletag (t, c)
reload_underlay(c,item) reload_infoshapes(c,item)
if not auto_release then if not auto_release then
reload_highlight(item) reload_highlight(item)
end end
@ -170,7 +170,7 @@ local function new(args)
local c = item.client local c = item.client
if c.screen ~= scr then return end if c.screen ~= scr then return end
client2.movetotag(t, c) client2.movetotag(t, c)
reload_underlay(c,item) reload_infoshapes(c,item)
if not auto_release then if not auto_release then
reload_highlight(item) reload_highlight(item)
end end
@ -185,18 +185,18 @@ local function new(args)
l:add( button_group({client = v, field = "maximized", focus = false, checked = function() return v.maximized end, onclick = function() v.maximized = not v.maximized end })) l:add( button_group({client = v, field = "maximized", focus = false, checked = function() return v.maximized end, onclick = function() v.maximized = not v.maximized end }))
l:add( button_group({client = v, field = "sticky" , focus = false, checked = function() return v.sticky end, onclick = function() v.sticky = not v.sticky end })) l:add( button_group({client = v, field = "sticky" , focus = false, checked = function() return v.sticky end, onclick = function() v.sticky = not v.sticky end }))
l:add( button_group({client = v, field = "ontop" , focus = false, checked = function() return v.ontop end, onclick = function() v.ontop = not v.ontop end })) l:add( button_group({client = v, field = "ontop" , focus = false, checked = function() return v.ontop end, onclick = function() v.ontop = not v.ontop end }))
l:add( button_group({client = v, field = "close" , focus = false, checked = function() return false end, onclick = function() v:kill() end })) l:add( button_group({client = v, field = "close" , focus = false, checked = function() return false end, onclick = function() v:kill(); currentMenu.visible = false; end }))
l.fit = function (s,c,w,h) return 5*h,h end l.fit = function (s,c,w,h) return 5*h,h end
end end
local underlays = reload_underlay(v) local underlays = reload_infoshapes(v)
local i = currentMenu:add_item({ local i = currentMenu:add_item({
text = v.name, text = v.name,
icon = v.icon or module.default_icon, icon = v.icon or module.default_icon,
suffix_widget = not auto_release and l or nil, suffix_widget = not auto_release and l or nil,
selected = capi.client.focus and capi.client.focus == v, selected = capi.client.focus and capi.client.focus == v,
underlay = underlays, infoshapes = underlays,
checkable = (not auto_release) and v.screen == scr, checkable = (not auto_release) and v.screen == scr,
checked = v.screen == scr and (not auto_release and is_in_tag(t,v)) or nil, checked = v.screen == scr and (not auto_release and is_in_tag(t,v)) or nil,
button1 = function(a,b,c,d,no_hide) button1 = function(a,b,c,d,no_hide)

View File

@ -22,40 +22,40 @@ function module.signals()
return sigMenu return sigMenu
end end
sigMenu = radical.context{max_items=10} sigMenu = radical.context{max_items=10}
sigterm = sigMenu:add_item({text="SIGTERM" , button1 = function() util.spawn("kill -s TERM "..module.client.pid);mainMenu.visible = false end,underlay="15"}) sigterm = sigMenu:add_item({text="SIGTERM" , button1 = function() util.spawn("kill -s TERM "..module.client.pid);mainMenu.visible = false end,infoshapes = {{text="15"}}})
sigkill = sigMenu:add_item({text="SIGKILL" , button1 = function() util.spawn("kill -s KILL "..module.client.pid);mainMenu.visible = false end,underlay="9"}) sigkill = sigMenu:add_item({text="SIGKILL" , button1 = function() util.spawn("kill -s KILL "..module.client.pid);mainMenu.visible = false end,infoshapes = {{text="9"}}})
sigint = sigMenu:add_item({text="SIGINT" , button1 = function() util.spawn("kill -s INT "..module.client.pid);mainMenu.visible = false end,underlay="2"}) sigint = sigMenu:add_item({text="SIGINT" , button1 = function() util.spawn("kill -s INT "..module.client.pid);mainMenu.visible = false end,infoshapes = {{text="2"}}})
sigquit = sigMenu:add_item({text="SIGQUIT" , button1 = function() util.spawn("kill -s QUIT "..module.client.pid);mainMenu.visible = false end,underlay="3"}) sigquit = sigMenu:add_item({text="SIGQUIT" , button1 = function() util.spawn("kill -s QUIT "..module.client.pid);mainMenu.visible = false end,infoshapes = {{text="3"}}})
-- sigMenu:add_widget(radical.widgets.separator()) -- sigMenu:add_widget(radical.widgets.separator())
sig0 = sigMenu:add_item({text="SIG0" , button1 = function() util.spawn("kill -s 0 "..module.client.pid);mainMenu.visible = false end,underlay=nil}) sig0 = sigMenu:add_item({text="SIG0" , button1 = function() util.spawn("kill -s 0 "..module.client.pid);mainMenu.visible = false end,infoshapes = { }})
sigalrm = sigMenu:add_item({text="SIGALRM" , button1 = function() util.spawn("kill -s ALRM "..module.client.pid);mainMenu.visible = false end,underlay="14"}) sigalrm = sigMenu:add_item({text="SIGALRM" , button1 = function() util.spawn("kill -s ALRM "..module.client.pid);mainMenu.visible = false end,infoshapes = {{text="14"}}})
sighup = sigMenu:add_item({text="SIGHUP" , button1 = function() util.spawn("kill -s HUP "..module.client.pid);mainMenu.visible = false end,underlay="1",tooltip="sdfsdfsdf"}) sighup = sigMenu:add_item({text="SIGHUP" , button1 = function() util.spawn("kill -s HUP "..module.client.pid);mainMenu.visible = false end,infoshapes = {{text="1"}},tooltip="sdfsdfsdf"})
sigpipe = sigMenu:add_item({text="SIGPIPE" , button1 = function() util.spawn("kill -s PIPE "..module.client.pid);mainMenu.visible = false end,underlay="13"}) sigpipe = sigMenu:add_item({text="SIGPIPE" , button1 = function() util.spawn("kill -s PIPE "..module.client.pid);mainMenu.visible = false end,infoshapes = {{text="13"}}})
sigpoll = sigMenu:add_item({text="SIGPOLL" , button1 = function() util.spawn("kill -s POLL "..module.client.pid);mainMenu.visible = false end,underlay=nil}) sigpoll = sigMenu:add_item({text="SIGPOLL" , button1 = function() util.spawn("kill -s POLL "..module.client.pid);mainMenu.visible = false end,infoshapes = {}})
sigprof = sigMenu:add_item({text="SIGPROF" , button1 = function() util.spawn("kill -s PROF "..module.client.pid);mainMenu.visible = false end,underlay="27"}) sigprof = sigMenu:add_item({text="SIGPROF" , button1 = function() util.spawn("kill -s PROF "..module.client.pid);mainMenu.visible = false end,infoshapes = {{text="27"}}})
sigusr1 = sigMenu:add_item({text="SIGUSR1" , button1 = function() util.spawn("kill -s USR1 "..module.client.pid);mainMenu.visible = false end,underlay="10"}) sigusr1 = sigMenu:add_item({text="SIGUSR1" , button1 = function() util.spawn("kill -s USR1 "..module.client.pid);mainMenu.visible = false end,infoshapes = {{text="10"}}})
sigusr2 = sigMenu:add_item({text="SIGUSR2" , button1 = function() util.spawn("kill -s USR2 "..module.client.pid);mainMenu.visible = false end,underlay="12"}) sigusr2 = sigMenu:add_item({text="SIGUSR2" , button1 = function() util.spawn("kill -s USR2 "..module.client.pid);mainMenu.visible = false end,infoshapes = {{text="12"}}})
sigsigvtalrm = sigMenu:add_item({text="SIGVTALRM" , button1 = function() util.spawn("kill -s VTALRM "..module.client.pid);mainMenu.visible = false end,underlay=nil}) sigsigvtalrm = sigMenu:add_item({text="SIGVTALRM" , button1 = function() util.spawn("kill -s VTALRM "..module.client.pid);mainMenu.visible = false end,infoshapes = {}})
sigstkflt = sigMenu:add_item({text="SIGSTKFLT" , button1 = function() util.spawn("kill -s STKFLT "..module.client.pid);mainMenu.visible = false end,underlay=nil}) sigstkflt = sigMenu:add_item({text="SIGSTKFLT" , button1 = function() util.spawn("kill -s STKFLT "..module.client.pid);mainMenu.visible = false end,infoshapes = {}})
sigpwr = sigMenu:add_item({text="SIGPWR" , button1 = function() util.spawn("kill -s PWR "..module.client.pid);mainMenu.visible = false end,underlay=nil}) sigpwr = sigMenu:add_item({text="SIGPWR" , button1 = function() util.spawn("kill -s PWR "..module.client.pid);mainMenu.visible = false end,infoshapes = {}})
sigwinch = sigMenu:add_item({text="SIGWINCH" , button1 = function() util.spawn("kill -s WINCH "..module.client.pid);mainMenu.visible = false end,underlay=nil}) sigwinch = sigMenu:add_item({text="SIGWINCH" , button1 = function() util.spawn("kill -s WINCH "..module.client.pid);mainMenu.visible = false end,infoshapes = {}})
sigchld = sigMenu:add_item({text="SIGCHLD" , button1 = function() util.spawn("kill -s CHLD "..module.client.pid);mainMenu.visible = false end,underlay="17"}) sigchld = sigMenu:add_item({text="SIGCHLD" , button1 = function() util.spawn("kill -s CHLD "..module.client.pid);mainMenu.visible = false end,infoshapes = {{text="17"}}})
sigurg = sigMenu:add_item({text="SIGURG" , button1 = function() util.spawn("kill -s URG "..module.client.pid);mainMenu.visible = false end,underlay=nil}) sigurg = sigMenu:add_item({text="SIGURG" , button1 = function() util.spawn("kill -s URG "..module.client.pid);mainMenu.visible = false end,infoshapes = {}})
sigtstp = sigMenu:add_item({text="SIGTSTP" , button1 = function() util.spawn("kill -s TSTP "..module.client.pid);mainMenu.visible = false end,underlay=nil}) sigtstp = sigMenu:add_item({text="SIGTSTP" , button1 = function() util.spawn("kill -s TSTP "..module.client.pid);mainMenu.visible = false end,infoshapes = {}})
sigttin = sigMenu:add_item({text="SIGTTIN" , button1 = function() util.spawn("kill -s TTIN "..module.client.pid);mainMenu.visible = false end,underlay="21"}) sigttin = sigMenu:add_item({text="SIGTTIN" , button1 = function() util.spawn("kill -s TTIN "..module.client.pid);mainMenu.visible = false end,infoshapes = {{text="21"}}})
sigttou = sigMenu:add_item({text="SIGTTOU" , button1 = function() util.spawn("kill -s TTOU "..module.client.pid);mainMenu.visible = false end,underlay="22"}) sigttou = sigMenu:add_item({text="SIGTTOU" , button1 = function() util.spawn("kill -s TTOU "..module.client.pid);mainMenu.visible = false end,infoshapes = {{text="22"}}})
sigstop = sigMenu:add_item({text="SIGSTOP" , button1 = function() util.spawn("kill -s STOP "..module.client.pid);mainMenu.visible = false end,underlay="17"}) sigstop = sigMenu:add_item({text="SIGSTOP" , button1 = function() util.spawn("kill -s STOP "..module.client.pid);mainMenu.visible = false end,infoshapes = {{text="17"}}})
sigcont = sigMenu:add_item({text="SIGCONT" , button1 = function() util.spawn("kill -s CONT "..module.client.pid);mainMenu.visible = false end,underlay="18"}) sigcont = sigMenu:add_item({text="SIGCONT" , button1 = function() util.spawn("kill -s CONT "..module.client.pid);mainMenu.visible = false end,infoshapes = {{text="18"}}})
sigabrt = sigMenu:add_item({text="SIGABRT" , button1 = function() util.spawn("kill -s ABRT "..module.client.pid);mainMenu.visible = false end,underlay="6"}) sigabrt = sigMenu:add_item({text="SIGABRT" , button1 = function() util.spawn("kill -s ABRT "..module.client.pid);mainMenu.visible = false end,infoshapes = {{text="6"}}})
sigfpe = sigMenu:add_item({text="SIGFPE" , button1 = function() util.spawn("kill -s FPE "..module.client.pid);mainMenu.visible = false end,underlay="8"}) sigfpe = sigMenu:add_item({text="SIGFPE" , button1 = function() util.spawn("kill -s FPE "..module.client.pid);mainMenu.visible = false end,infoshapes = {{text="8"}}})
sigill = sigMenu:add_item({text="SIGILL" , button1 = function() util.spawn("kill -s ILL "..module.client.pid);mainMenu.visible = false end,underlay="4"}) sigill = sigMenu:add_item({text="SIGILL" , button1 = function() util.spawn("kill -s ILL "..module.client.pid);mainMenu.visible = false end,infoshapes = {{text="4"}}})
sigsegv = sigMenu:add_item({text="SIGSEGV" , button1 = function() util.spawn("kill -s SEGV "..module.client.pid);mainMenu.visible = false end,underlay="11"}) sigsegv = sigMenu:add_item({text="SIGSEGV" , button1 = function() util.spawn("kill -s SEGV "..module.client.pid);mainMenu.visible = false end,infoshapes = {{text="11"}}})
sigtrap = sigMenu:add_item({text="SIGTRAP" , button1 = function() util.spawn("kill -s TRAP "..module.client.pid);mainMenu.visible = false end,underlay="5"}) sigtrap = sigMenu:add_item({text="SIGTRAP" , button1 = function() util.spawn("kill -s TRAP "..module.client.pid);mainMenu.visible = false end,infoshapes = {{text="5"}}})
sigsys = sigMenu:add_item({text="SIGSYS" , button1 = function() util.spawn("kill -s SYS "..module.client.pid);mainMenu.visible = false end,underlay="12"}) sigsys = sigMenu:add_item({text="SIGSYS" , button1 = function() util.spawn("kill -s SYS "..module.client.pid);mainMenu.visible = false end,infoshapes = {{text="12"}}})
sigemt = sigMenu:add_item({text="SIGEMT" , button1 = function() util.spawn("kill -s EMT "..module.client.pid);mainMenu.visible = false end,underlay=nil}) sigemt = sigMenu:add_item({text="SIGEMT" , button1 = function() util.spawn("kill -s EMT "..module.client.pid);mainMenu.visible = false end,infoshapes = {}})
sigbus = sigMenu:add_item({text="SIGBUS" , button1 = function() util.spawn("kill -s BUS "..module.client.pid);mainMenu.visible = false end,underlay="7"}) sigbus = sigMenu:add_item({text="SIGBUS" , button1 = function() util.spawn("kill -s BUS "..module.client.pid);mainMenu.visible = false end,infoshapes = {{text="7"}}})
sigxcpu = sigMenu:add_item({text="SIGXCPU" , button1 = function() util.spawn("kill -s XCPU "..module.client.pid);mainMenu.visible = false end,underlay=nil}) sigxcpu = sigMenu:add_item({text="SIGXCPU" , button1 = function() util.spawn("kill -s XCPU "..module.client.pid);mainMenu.visible = false end,infoshapes = {}})
sigxfsz = sigMenu:add_item({text="SIGXFSZ" , button1 = function() util.spawn("kill -s XFSZ "..module.client.pid);mainMenu.visible = false end,underlay=nil}) sigxfsz = sigMenu:add_item({text="SIGXFSZ" , button1 = function() util.spawn("kill -s XFSZ "..module.client.pid);mainMenu.visible = false end,infoshapes = {}})
return sigMenu return sigMenu
end end
@ -103,4 +103,4 @@ function module.screenshot(clients,geo)
end end
return module--setmetatable(module, {}) return module--setmetatable(module, {})
-- kate: space-indent on; indent-width 2; replace-tabs on; -- kate: space-indent on; indent-width 2; replace-tabs on;

View File

@ -17,6 +17,7 @@ local surface = require( "gears.surface")
local client_menu = require( "radical.impl.tasklist.client_menu") local client_menu = require( "radical.impl.tasklist.client_menu")
local theme = require( "radical.theme") local theme = require( "radical.theme")
local rad_client = require( "radical.impl.common.client") local rad_client = require( "radical.impl.common.client")
local shape = require("gears.shape")
local sticky,urgent,instances,module = {extensions=require("radical.impl.tasklist.extensions")},{},{},{} local sticky,urgent,instances,module = {extensions=require("radical.impl.tasklist.extensions")},{},{},{}
local _cache = setmetatable({}, { __mode = 'k' }) local _cache = setmetatable({}, { __mode = 'k' })
@ -126,22 +127,45 @@ local function unmanage_callback(c)
_cache[c] = nil _cache[c] = nil
end end
local infoshape_template = {
ontop = {
text = "ontop",
shape = shape.hexagon,
bg = beautiful.tasklist_bg_underlay,
},
float = {
text = "float",
shape = shape.hexagon,
bg = beautiful.tasklist_bg_underlay,
},
sticky = {
text = "sticky",
shape = shape.hexagon,
bg = beautiful.tasklist_bg_underlay,
},
}
-- Reload <float> <ontop> and <sticky> labels -- Reload <float> <ontop> and <sticky> labels
local function reload_underlay(c) local function reload_infoshapes(c)
local udl,item = {},_cache[c] local item = _cache[c]
if item then
if c.ontop then local infoshapes = {}
udl[#udl+1] = "ontop"
if item then
if c.ontop then
infoshapes[#infoshapes+1] = infoshape_template.ontop
end
if client.floating.get(c) then
infoshapes[#infoshapes+1] = infoshape_template.float
end
if c.sticky then
infoshapes[#infoshapes+1] = infoshape_template.sticky
end
item.infoshapes = infoshapes
item.widget:emit_signal("widget::updated")
end end
if client.floating.get(c) then
udl[#udl+1] = "float"
end
if c.sticky then
udl[#udl+1] = "sticky"
end
item.underlay = udl
item.widget:emit_signal("widget::updated")
end
end end
-- Reload title and icon -- Reload title and icon
@ -180,10 +204,13 @@ local function create_client_item(c,screen)
end end
item:connect_signal("mouse::enter", function() item:connect_signal("mouse::enter", function()
item.overlay = {"1:23:45", c.pid} item.infoshapes = {
{text = "1:23:45", bg = beautiful.tasklist_bg_overlay, align = "center"},
{text = c.pid , bg = beautiful.tasklist_bg_overlay, align = "center"}
}
end) end)
item:connect_signal("mouse::leave", function() item:connect_signal("mouse::leave", function()
item.overlay = nil item.infoshapes = {}
end) end)
item.add_suffix = function(w,w2) item.add_suffix = function(w,w2)
@ -198,7 +225,7 @@ end
local function add_client(c,screen) local function add_client(c,screen)
if not (c.skip_taskbar or c.hidden or c.type == "splash" or c.type == "dock" or c.type == "desktop") and c.screen == screen then if not (c.skip_taskbar or c.hidden or c.type == "splash" or c.type == "dock" or c.type == "desktop") and c.screen == screen then
local ret = create_client_item(c,screen) local ret = create_client_item(c,screen)
reload_underlay(c) reload_infoshapes(c)
if capi.client.focus == c then if capi.client.focus == c then
ret.selected = true ret.selected = true
end end
@ -276,10 +303,7 @@ local function new(screen)
disable_markup = true , disable_markup = true ,
fg = beautiful.tasklist_fg or beautiful.fg_normal , fg = beautiful.tasklist_fg or beautiful.fg_normal ,
bg = beautiful.tasklist_bg or beautiful.bg_normal , bg = beautiful.tasklist_bg or beautiful.bg_normal ,
underlay_style = beautiful.tasklist_underlay_style or radical.widgets.underlay.draw_arrow, -- overlay_bg = beautiful.tasklist_bg_overlay ,
overlay_align = "center" ,
overlay_alpha = 1 ,
overlay_bg = beautiful.tasklist_bg_overlay ,
icon_transformation = beautiful.tasklist_icon_transformation , icon_transformation = beautiful.tasklist_icon_transformation ,
default_item_margins = beautiful.tasklist_default_item_margins , default_item_margins = beautiful.tasklist_default_item_margins ,
default_margins = beautiful.tasklist_default_margins , default_margins = beautiful.tasklist_default_margins ,
@ -333,9 +357,9 @@ capi.client.connect_signal("property::urgent" , urgent_callback )
capi.client.connect_signal("unmanage" , unmanage_callback ) capi.client.connect_signal("unmanage" , unmanage_callback )
capi.client.connect_signal("focus" , focus ) capi.client.connect_signal("focus" , focus )
capi.client.connect_signal("unfocus" , unfocus ) capi.client.connect_signal("unfocus" , unfocus )
capi.client.connect_signal("property::sticky" , reload_underlay ) capi.client.connect_signal("property::sticky" , reload_infoshapes )
capi.client.connect_signal("property::ontop" , reload_underlay ) capi.client.connect_signal("property::ontop" , reload_infoshapes )
capi.client.connect_signal("property::floating" , reload_underlay ) capi.client.connect_signal("property::floating" , reload_infoshapes )
capi.client.connect_signal("property::name" , reload_content ) capi.client.connect_signal("property::name" , reload_content )
capi.client.connect_signal("property::icon" , reload_content ) capi.client.connect_signal("property::icon" , reload_content )
capi.client.connect_signal("property::minimized", minimize_callback ) capi.client.connect_signal("property::minimized", minimize_callback )

View File

@ -1,7 +1,6 @@
local type = type local type = type
local base = require( "wibox.widget.base" ) local base = require( "wibox.widget.base" )
local tooltip = require( "radical.tooltip" ) local tooltip = require( "radical.tooltip" )
local underlay = require( "radical.widgets.underlay")
local aw_button = require( "awful.button" ) local aw_button = require( "awful.button" )
local beautiful = require( "beautiful" ) local beautiful = require( "beautiful" )
@ -65,75 +64,6 @@ local function set_menu(self,menu, event, button_id)
return bt return bt
end end
local function layer_draw_common(self, context, cr, width, height, typename)
cr:save()
local udl = underlay.draw(self["_"..typename], {
height = height,
style = self["_"..typename.."_style"],
bg = self["_"..typename.."_color"]
},
context
)
cr:set_source_surface(udl,width-udl:get_width()-3)
cr:paint_with_alpha(self["_"..typename.."_alpha"] or beautiful[typename.."_alpha"] or 0.7)
cr:restore()
end
local function draw_underlay(self, context, cr, width, height)
layer_draw_common(self, context, cr, width, height, "underlay")
if self._draw_original then
self._draw_original(self, context, cr, width, height)
end
end
local function draw_overlay(self, context, cr, width, height)
if self._draw_original then
self._draw_original(self, context, cr, width, height)
end
layer_draw_common(self, context, cr, width, height, "overlay")
end
local function set_layer_common(typename, self ,udl ,args)
local args = args or {}
if self.draw and not self._draw_original then
self._draw_original = self.draw
if typename == "underlay" then
self.draw = draw_underlay
elseif typename == "overlay" then
self.draw = draw_overlay
end
elseif typename == "underlay" then
self.before_draw_children = draw_underlay
elseif typename == "overlay" then
self.after_draw_children = draw_overlay
end
-- TODO detect if it is a Radical item and get those properties,
-- then, delete item.layout implementations
self["_"..typename ] = udl
self["_"..typename.."_style"] = args.style
self["_"..typename.."_alpha"] = args.alpha
self["_"..typename.."_color"] = args.color
self:emit_signal("widget::updated")
end
local function set_underlay(...)
set_layer_common("underlay",...)
end
local function set_overlay(...)
set_layer_common("overlay",...)
end
local function get_preferred_size(self, context, width, height) local function get_preferred_size(self, context, width, height)
local context = context or 1 local context = context or 1
@ -152,8 +82,6 @@ base.make_widget = function(...)
local ret = base._make_widget(...) local ret = base._make_widget(...)
ret.set_tooltip = set_tooltip ret.set_tooltip = set_tooltip
ret.set_menu = set_menu ret.set_menu = set_menu
ret.set_underlay = set_underlay
ret.set_overlay = set_overlay
-- Textboxes already have it -- Textboxes already have it
if not ret.get_preferred_size then if not ret.get_preferred_size then

View File

@ -75,6 +75,15 @@ local function hide_sub_menu(item,data)
end end
end end
local function set_infoshapes(item, shapes)
if item.widget and item.widget.get_children_by_id then
local infoshape_widget = item.widget:get_children_by_id("infoshapes")[1]
if infoshape_widget then
infoshape_widget:set_infoshapes(shapes)
end
end
end
-- local registered_items = {} -- local registered_items = {}
-- local is_watching = false -- local is_watching = false
-- local mouse_tracker = object{} -- local mouse_tracker = object{}
@ -110,6 +119,7 @@ local function new_item(data,args)
tooltip = args.tooltip or nil , tooltip = args.tooltip or nil ,
style = args.style or data.item_style , style = args.style or data.item_style ,
layout = args.layout or args.item_layout or nil , layout = args.layout or args.item_layout or nil ,
infoshapes = args.infoshapes or nil ,
overlay_draw= args.overlay_draw or data.overlay_draw , overlay_draw= args.overlay_draw or data.overlay_draw ,
item_border_color = args.item_border_color or data.item_border_color or nil , item_border_color = args.item_border_color or data.item_border_color or nil ,
}, },
@ -138,27 +148,7 @@ local function new_item(data,args)
return data.fg return data.fg
end end
-- Setup underlay and overlay
for k, name in ipairs {"underlay", "overlay"} do
item["set_"..name] = function(item,underlay)
if not item._internal.underlay_init then
data:add_colors_group(name)
item._internal.underlay_init = true
end
item._internal[name.."_content"] = underlay
end
item.get_underlay = function(item)
return item._internal.underlay_content
end
item[name.."_alpha"] = args[name.."_alpha"]
item[name.."_style"] = args[name.."_style"]
item[name.."_align"] = args[name.."_align"]
end
item.state = theme.init_state(item) item.state = theme.init_state(item)
item.underlay = args.underlay
item.overlay = args.overlay
for i=1,10 do for i=1,10 do
item["button"..i] = args["button"..i] item["button"..i] = args["button"..i]
@ -202,6 +192,9 @@ local function new_item(data,args)
data._current_item = item data._current_item = item
end end
-- Overlay and underlay
item.set_infoshapes = set_infoshapes
item.set_icon = function (_,value) item.set_icon = function (_,value)
local icon_w = item._internal.icon_w local icon_w = item._internal.icon_w
@ -274,4 +267,4 @@ local function new_item(data,args)
end end
return setmetatable(module, { __call = function(_, ...) return new_item(...) end, __index=load_async}) return setmetatable(module, { __call = function(_, ...) return new_item(...) end, __index=load_async})
-- kate: space-indent on; indent-width 2; replace-tabs on; -- kate: space-indent on; indent-width 2; replace-tabs on;

View File

@ -1,20 +1,19 @@
local setmetatable = setmetatable local setmetatable = setmetatable
local beautiful = require( "beautiful" ) local beautiful = require( "beautiful" )
local color = require( "gears.color" ) local color = require( "gears.color" )
local cairo = require( "lgi" ).cairo local cairo = require( "lgi" ).cairo
local wibox = require( "wibox" ) local wibox = require( "wibox" )
local checkbox = require( "radical.widgets.checkbox" ) local checkbox = require( "radical.widgets.checkbox" )
local fkey = require( "radical.widgets.fkey" ) local fkey = require( "radical.widgets.fkey" )
local underlay = require( "radical.widgets.underlay" ) local infoshapes = require( "radical.widgets.infoshapes" )
local theme = require( "radical.theme" ) local theme = require( "radical.theme" )
local util = require( "awful.util" ) local util = require( "awful.util" )
local margins2 = require( "radical.margins") local margins2 = require( "radical.margins" )
local shape = require( "gears.shape" ) local shape = require( "gears.shape" )
local surface = require( "gears.surface" ) local surface = require( "gears.surface" )
local module = {} local module = {}
-- Add [F1], [F2] ... to items -- Add [F1], [F2] ... to items
function module:setup_fkey(item,data) function module:setup_fkey(item,data)
item.set_f_key = function(_,value) item.set_f_key = function(_,value)
@ -29,44 +28,11 @@ function module:setup_fkey(item,data)
item.get_f_key = function() return item._internal.f_key end item.get_f_key = function() return item._internal.f_key end
end end
-- Like an overlay, but under
function module.paint_underlay(data,item,cr,width,height, name)
name = name or "underlay"
cr:save()
local state = item.state or {}
local current_state = state._current_key or nil
local state_name = theme.colors_by_id[current_state] or ""
local bg_color = item[name.."_bg_"..state_name] or data[name.."_bg_"..state_name] or data[name.."_bg"]
local style = item[name.."_style" ] or data[name.."_style" ]
local alpha = item[name.."_alpha" ] or data[name.."_alpha" ]
local align = item[name.."_align" ] or data[name.."_align" ]
local udl = underlay.draw(item[name],{style=data.underlay_style,height=height,bg=bg_color, style = style})
if align == "center" then
local offset = (width-udl:get_width()-6)/2
cr:set_source_surface(udl,3 + offset)
else
cr:set_source_surface(udl,width-udl:get_width()-3)
end
cr:paint_with_alpha(data[name.."_alpha"])
cr:restore()
end
function module.after_draw_children(self, context, cr, width, height) function module.after_draw_children(self, context, cr, width, height)
if self._item.overlay then --TODO get rid of this, use the stack container
module.paint_underlay(self._data, self._item, cr, width, height, "overlay") if self._item.overlay_draw then
end self._item.overlay_draw(context,self._item,cr,width,height)
end
if self._item.overlay_draw then
self._item.overlay_draw(context,self._item,cr,width,height)
end
-- Draw the border, if any
if self._after_draw_children then
self._after_draw_children(self, context, cr, width, height)
end
end end
-- Apply icon transformation -- Apply icon transformation
@ -195,18 +161,6 @@ function module.setup_event(data,item,widget)
-- end) -- end)
end end
-- Use all the space, let "align_fit" compute the right size
local function textbox_fit(box,context,w,h)
return w,h
end
-- Force the width or compute the minimum space
local function align_fit(box,context,w,h)
local mar = util.table.join(box._data.item_style.margins,box._data.default_item_margins)
if box._item.width then return box._item.width - box._data.item_style.margins.LEFT - box._data.item_style.margins.RIGHT,h end
return box.first:fit(context,w,h)+wibox.widget.textbox.fit(box.second,context,w,h)+box.third:fit(context,w,h),h
end
-- Create the actual widget -- Create the actual widget
local function create_item(item,data,args) local function create_item(item,data,args)
@ -230,13 +184,7 @@ local function create_item(item,data,args)
-- Text -- Text
local tb = wibox.widget.textbox() local tb = wibox.widget.textbox()
tb.fit = data._internal.text_fit or textbox_fit
tb.draw = function(self, context, cr, width, height)
if item.underlay then
module.paint_underlay(data,item,cr,width,height)
end
wibox.widget.textbox.draw(self, context, cr, width, height)
end
tb:set_text(item.text) tb:set_text(item.text)
item.set_text = function (_,value) item.set_text = function (_,value)
if data.disable_markup then if data.disable_markup then
@ -260,6 +208,7 @@ local function create_item(item,data,args)
item.widget = wibox.widget.base.make_widget_declarative { item.widget = wibox.widget.base.make_widget_declarative {
-- Widgets -- Widgets
{ {
-- Widget -- Widget
{ {
-- This is where the content is placed -- This is where the content is placed
@ -276,7 +225,16 @@ local function create_item(item,data,args)
-- Attributes -- Attributes
layout = wibox.layout.fixed.horizontal layout = wibox.layout.fixed.horizontal
}, },
tb, {
-- Underlay and overlay
tb,
-- Attributes
widget = infoshapes,
spacing = 10,
infoshapes = item.infoshapes,
id = "infoshapes",
},
{ {
-- Suffixes -- Suffixes
@ -314,9 +272,6 @@ local function create_item(item,data,args)
item._internal.align = item.widget:get_children_by_id("main_align" )[1] item._internal.align = item.widget:get_children_by_id("main_align" )[1]
-- Override some methods -- Override some methods
item.widget._after_draw_children = item.widget.after_draw_children
item.widget.after_draw_children = module.after_draw_children
item._internal.align.fit = data._internal.align_fit or align_fit
item._internal.text_w = tb item._internal.text_w = tb
item._internal.icon_w = icon item._internal.icon_w = icon
@ -336,11 +291,6 @@ local function create_item(item,data,args)
local item_style = item.style or data.item_style local item_style = item.style or data.item_style
item_style(item,{}) item_style(item,{})
-- Setup dynamic underlay
item:connect_signal("underlay::changed",function(_,udl)
item.widget:emit_signal("widget::updated")
end)
-- Setup events -- Setup events
module.setup_event(data,item) module.setup_event(data,item)

View File

@ -1,13 +1,11 @@
local setmetatable = setmetatable local setmetatable = setmetatable
local beautiful = require( "beautiful" ) local beautiful = require( "beautiful" )
local color = require( "gears.color" ) local color = require( "gears.color" )
local cairo = require( "lgi" ).cairo local wibox = require( "wibox" )
local wibox = require( "wibox" ) local checkbox = require( "radical.widgets.checkbox" )
local checkbox = require( "radical.widgets.checkbox" ) local horizontal = require( "radical.item.layout.horizontal" )
local fkey = require( "radical.widgets.fkey" ) local util = require( "awful.util" )
local horizontal = require( "radical.item.layout.horizontal" ) local margins2 = require( "radical.margins" )
local util = require( "awful.util" )
local margins2 = require("radical.margins")
local module = {} local module = {}

View File

@ -1,130 +1,10 @@
local setmetatable = setmetatable local setmetatable = setmetatable
local beautiful = require( "beautiful" )
local color = require( "gears.color" )
local cairo = require( "lgi" ).cairo
local wibox = require( "wibox" ) local wibox = require( "wibox" )
local checkbox = require( "radical.widgets.checkbox" )
local fkey = require( "radical.widgets.fkey" )
local underlay = require( "radical.widgets.underlay" )
local theme = require( "radical.theme" )
local horizontal= require( "radical.item.layout.horizontal") local horizontal= require( "radical.item.layout.horizontal")
local margins2 = require( "radical.margins" ) local margins2 = require( "radical.margins" )
local module = {} local module = {}
-- Add [F1], [F2] ... to items
function module:setup_fkey(item,data)
item.set_f_key = function(_,value)
item._internal.has_changed = true
item._internal.f_key = value
data:remove_key_hook("F"..value)
data:add_key_hook({}, "F"..value , "press", function()
item.button1(data,menu)
data.visible = false
end)
end
item.get_f_key = function() return item._internal.f_key end
end
-- Show the checkbox
function module:setup_checked(item,data)
if item.checkable then
item.get_checked = function(data,item)
if type(item._private_data.checked) == "function" then
return item._private_data.checked()
else
return item._private_data.checked
end
end
local ck = wibox.widget.imagebox()
ck:set_image(item.checked and checkbox.checked() or checkbox.unchecked())
item.set_checked = function (_,value)
item._private_data.checked = value
ck:set_image(item.checked and checkbox.checked() or checkbox.unchecked())
item._internal.has_changed = true
end
return ck
end
end
-- Setup hover
function module:setup_hover(item,data)
item.set_hover = function(_,value)
local item_style = item.item_style or data.item_style
item.state[-1] = value and true or nil
item_style(item,{})
end
end
-- Create sub_menu arrows
local sub_arrow = nil
function module:setup_sub_menu_arrow(item,data)
if item._private_data.sub_menu_f or item._private_data.sub_menu_m then
if not sub_arrow then
sub_arrow = wibox.widget.imagebox() --TODO, make global
sub_arrow.fit = function(box, context, w, h) return sub_arrow._image:get_width(),item.height end
sub_arrow:set_image( beautiful.menu_submenu_icon )
end
return sub_arrow
end
end
-- Proxy all events to the parent
function module.setup_event(data,item,widget)
local widget = widget or item.widget
-- Setup data signals
widget:connect_signal("button::press",function(_,__,___,id,mod)
local mods_invert = {}
for k,v in ipairs(mod) do
mods_invert[v] = i
end
item.state[4] = true
data:emit_signal("button::press",item,id,mods_invert)
item:emit_signal("button::press",item,id,mods_invert)
end)
widget:connect_signal("button::release",function(_,__,___,id,mod)
local mods_invert = {}
for k,v in ipairs(mod) do
mods_invert[v] = i
end
item.state[4] = nil
data:emit_signal("button::release",item,id,mods_invert)
item:emit_signal("button::release",item,id,mods_invert)
end)
widget:connect_signal("mouse::enter",function(b,t)
data:emit_signal("mouse::enter",item)
item:emit_signal("mouse::enter",item)
end)
widget:connect_signal("mouse::leave",function(b,t)
data:emit_signal("mouse::leave",item)
item:emit_signal("mouse::leave",item)
end)
-- Always tracking mouse::move is expensive, only do it when necessary
-- local function conn(b,t)
-- item:emit_signal("mouse::move",item)
-- end
-- item:connect_signal("connection",function(_,name,count)
-- if name == "mouse::move" then
-- widget:connect_signal("mouse::move",conn)
-- end
-- end)
-- item:connect_signal("disconnection",function(_,name,count)
-- if count == 0 then
-- widget:connect_signal("mouse::move",conn)
-- end
-- end)
end
-- Use all the space, let "align_fit" compute the right size
local function textbox_fit(box,context,w,h)
local w2,h2 = wibox.widget.textbox.fit(box,context,w,h)
return w,h2
end
-- Force the width or compute the minimum space -- Force the width or compute the minimum space
local function align_fit(box,context,w,h) local function align_fit(box,context,w,h)
if box._item.width then return box._item.width - box._data.item_style.margins.LEFT - box._data.item_style.margins.RIGHT,h end if box._item.width then return box._item.width - box._data.item_style.margins.LEFT - box._data.item_style.margins.RIGHT,h end
@ -150,12 +30,6 @@ local function create_item(item,data,args)
-- Layout (right) -- Layout (right)
local right = wibox.layout.fixed.horizontal() local right = wibox.layout.fixed.horizontal()
-- F keys
module:setup_fkey(item,data)
if data.fkeys_prefix == true then
layout:add(fkey(data,item))
end
-- Icon -- Icon
local icon = horizontal.setup_icon(horizontal,item,data) local icon = horizontal.setup_icon(horizontal,item,data)
icon.fit = function(...) icon.fit = function(...)
@ -170,16 +44,16 @@ local function create_item(item,data,args)
end end
-- Checkbox -- Checkbox
local ck = module:setup_checked(item,data) local ck = horizontal:setup_checked(item,data)
if ck then if ck then
right:add(ck) right:add(ck)
end end
-- Hover -- Hover
module:setup_hover(item,data) horizontal:setup_hover(item,data)
-- Sub_arrow -- Sub_arrow
local ar = module:setup_sub_menu_arrow(item,data) local ar = horizontal:setup_sub_menu_arrow(item,data)
if ar then if ar then
right:add(ar) right:add(ar)
end end
@ -195,12 +69,6 @@ local function create_item(item,data,args)
-- Text -- Text
local tb4 = wibox.widget.textbox() local tb4 = wibox.widget.textbox()
tb4.draw = function(self, context, cr, width, height)
if item.underlay then
horizontal.paint_underlay(data,item,cr,width,height)
end
wibox.widget.textbox.draw(self, context, cr, width, height)
end
item.set_text = function (_,value) item.set_text = function (_,value)
if data.disable_markup then if data.disable_markup then
@ -254,20 +122,10 @@ local function create_item(item,data,args)
item.widget:set_fg(item._private_data.fg) item.widget:set_fg(item._private_data.fg)
-- Setup events -- Setup events
module.setup_event(data,item) horizontal.setup_event(data,item)
-- Setup dynamic underlay
-- Setup dynamic underlay
item:connect_signal("underlay::changed",function(_,udl)
bg:emit_signal("widget::updated")
end)
-- if item.buttons then
-- bg:buttons(item.buttons)
-- end
return bg return bg
end end
return setmetatable(module, { __call = function(_, ...) return create_item(...) end }) return setmetatable(module, { __call = function(_, ...) return create_item(...) end })
-- kate: space-indent on; indent-width 2; replace-tabs on; -- kate: space-indent on; indent-width 4; replace-tabs on;

View File

@ -19,32 +19,6 @@ local function item_fit(data,item,self,context, width,height)
return w, item.height or h return w, item.height or h
end end
function module.setup_text(item,data,text_w)
local text_w = item._internal.text_w
if not text_w then return end
text_w.draw = function(self,context, cr, width, height)
if item.underlay then
horizontal_item_layout.paint_underlay(data,item,cr,width,height)
end
wibox.widget.textbox.draw(self, context, cr, width, height)
end
text_w.fit = function(self,context,width,height) return width,height end
item.set_text = function (_,value)
if data.disable_markup then
text_w:set_text(value)
else
text_w:set_markup(value)
end
item._private_data.text = value
end
item:set_text(item._private_data.text)
return text_w
end
function module:setup_item(data,item,args) function module:setup_item(data,item,args)
item._private_data._fit = wibox.widget.background.fit item._private_data._fit = wibox.widget.background.fit
if item._internal.margin_w then if item._internal.margin_w then
@ -56,9 +30,6 @@ function module:setup_item(data,item,args)
end end
end end
-- Text need to take as much space as possible, override default
module.setup_text(item,data)
-- Compute the minimum width -- Compute the minimum width
if data.auto_resize and item._internal.margin_w then if data.auto_resize and item._internal.margin_w then
local fit_w = wibox.layout.margin.fit(item._internal.margin_w,{dpi=96},9999,9999) local fit_w = wibox.layout.margin.fit(item._internal.margin_w,{dpi=96},9999,9999)

View File

@ -96,7 +96,6 @@ function module.setup_colors(data,args)
or beautiful["menu_border_color_"..v.beautiful_name] or beautiful["menu_border_color_"..v.beautiful_name]
or beautiful["border_color_"..v.beautiful_name] or beautiful["border_color_"..v.beautiful_name]
or (v.fallback and beautiful.border_color) or (v.fallback and beautiful.border_color)
--priv["underlay_bg_"..k] = args["underlay_bg_"..k] or beautiful["menu_underlay_bg_"..v.beautiful_name] or beautiful["underlay_bg_"..v.beautiful_name]
end end
-- Handle custom sections -- Handle custom sections
@ -182,4 +181,4 @@ function module.add_section(data,section,args)
end end
return module return module
-- kate: space-indent on; indent-width 2; replace-tabs on; -- kate: space-indent on; indent-width 2; replace-tabs on;

View File

@ -8,6 +8,7 @@ local beautiful = require( "beautiful" )
local module = {} local module = {}
--TODO broken
local function new(data) local function new(data)
local filter_tb = wibox.widget.textbox() local filter_tb = wibox.widget.textbox()
local bg = wibox.widget.background() local bg = wibox.widget.background()
@ -17,7 +18,7 @@ local function new(data)
filter_tb.fit = function(tb,context,width,height) filter_tb.fit = function(tb,context,width,height)
return width,data.item_height return width,data.item_height
end end
filter_tb:set_underlay(data.filter_underlay,{alpha=data.filter_underlay_alpha,color=data.filter_underlay_color}) -- filter_tb:set_underlay(data.filter_underlay,{alpha=data.filter_underlay_alpha,color=data.filter_underlay_color})
data:connect_signal("filter_string::changed",function() data:connect_signal("filter_string::changed",function()
local is_empty = data.filter_string == "" local is_empty = data.filter_string == ""
filter_tb:set_markup(" <b>".. data.filter_prefix .."</b> "..(is_empty and data.filter_placeholder or data.filter_string)) filter_tb:set_markup(" <b>".. data.filter_prefix .."</b> "..(is_empty and data.filter_placeholder or data.filter_string))

330
widgets/infoshapes.lua Normal file
View File

@ -0,0 +1,330 @@
local setmetatable = setmetatable
--TODO rename to infoshape and infolayer, merge with constrainedtext, support icons
local util = require( "awful.util" )
local base = require( "wibox.widget.base" )
local shape = require( "gears.shape" )
local beautiful = require( "beautiful" )
local color = require( "gears.color" )
local cairo = require("lgi").cairo
local pango = require("lgi").Pango
local pangocairo = require("lgi").PangoCairo
local infoshape = { mt = {} }
local default_shape = shape.rounded_bar
local default_font_description = nil
local pango_l = {}
local padding = 2 --TODO do not hardcode
-- Cache the pango layout
local function init_pango(height)
if pango_l[height] then return pango_l[height] end
-- Get text height
if not pango_l[height] then
local pango_crx = pangocairo.font_map_get_default():create_context()
pango_l[height] = pango.Layout.new(pango_crx)
local desc = pango.FontDescription()
desc:set_family("Verdana")
desc:set_weight(pango.Weight.BOLD)
-- desc:set_size((height-padding*2) * pango.SCALE)
desc:set_absolute_size((height - 2*padding) * pango.SCALE)
-- desc:set_variant(pango.Variant.SMALL_CAPS)
pango_l[height]:set_font_description(desc)
return pango_l[height]
end
end
local function get_extents(text, height)
local l = init_pango(height)
l.text = text
return l:get_pixel_extents()
end
local function get_group_extents(self, group, height)
local ret = 0
for k, v in ipairs(group) do
ret = ret + get_extents(v.text, height).width + 2*height + (self._padding or 2) + (self.spacing or 0)
end
return ret
end
-- Add the shape to the context
local function draw_shape2(self, cr, width, height, ...)
local shape = self.shape or default_shape
if shape then
shape(cr, width, height, ...)
end
end
-- Draw a single buble
local function draw_shape(self, cr, width, height, infoshape)
local text = infoshape.text
-- Get the extents
local extents = get_extents(text, height)
local w,h = extents.width + 2*height, height - 2*padding
-- Draw the shape
draw_shape2(infoshape, cr, w, h) --TODO support padding, shape args
-- The border
local border_width = infoshape.border_width or self._shape_border_width or beautiful.infoshape_shape_border_width
local border_color = infoshape.border_color or self._shape_border_color or beautiful.infoshape_shape_border_color
if self._shape_border and border_color then
cr:set_source(color())
cr:set_line_width(border_width)
cr:srtoke_preserve()
end
-- The background
local bg = infoshape.bg or self._bg or beautiful.infoshape_shape_bg or beautiful.bg_focus
cr:set_source(color(bg))
-- The text
local fg = infoshape.fg or self._bg or beautiful.infoshape_shape_fg-- or "#ff0000"
local l = init_pango(height)
if fg then
cr:fill()
cr:translate(height, 0)
cr:set_source(color(fg))
cr:show_layout(l)
else
-- Allow the text to be transparent while the shape is solid
--TODO find a better way to do this
cr:clip()
local img = cairo.ImageSurface(cairo.Format.ARGB32, w,h)
local cr3 = cairo.Context(img)
cr3:set_source_rgba(1,1,0,1)
cr3:paint_with_alpha(infoshape.alpha or 1)
cr3:translate(height, 0)
cr3:layout_path(l)
cr3:set_operator(cairo.Operator.CLEAR)
cr3:fill()
cr:mask_surface(img)
cr:reset_clip()
cr:translate(height, 0)
end
return extents.width + (border_width or 0), height
end
-- Draw a single section
local function draw_section_common(self, context, cr, width, height, section)
cr:translate(0, padding)
for k, v in ipairs(section) do
local w, h = draw_shape(self, cr, width, height, v)
cr:translate(w + (self._padding or 2) + height, 0)
end
end
-- Compute the each section points [x,y] and paint them
local function draw_layer_common(self, context, cr, width, height, layer)
if layer.left then
cr:save()
draw_section_common(self, context, cr, width, height, layer.left)
cr:restore()
end
if layer.right then
cr:save()
cr:translate(width-get_group_extents(self, layer.right, height), 0)
draw_section_common(self, context, cr, width, height, layer.right)
cr:restore()
end
if layer.center then
cr:save()
local w = get_group_extents(self, layer.center, height)/2
cr:translate(width/2-w, 0)
draw_section_common(self, context, cr, width, height, layer.center)
cr:restore()
end
end
function infoshape:before_draw_children(context, cr, width, height)
if self._below then
draw_layer_common(self, context, cr, width, height, self._below)
end
end
function infoshape:after_draw_children(context, cr, width, height)
if self._above then
draw_layer_common(self, context, cr, width, height, self._above)
end
end
-- Support multiple align modes
function infoshape:layout(context, width, height)
if self.widget then
local w, h = self.widget:fit(context, width, height)
if not self._align or self._align == "left" then --TODO use base.fit_widget
return { base.place_widget_at(self.widget, 0, 0, w, height) }
else
if self._align == "center" then
return { base.place_widget_at(self.widget, width/2-w/2, 0, w, height) }
elseif self._align == "right" then
return { base.place_widget_at(self.widget, width-w, 0, w, height) }
end
end
end
end
-- The minimum fit is the same as the child widget, but extra space is welcome
function infoshape:fit(context, width, height)
if not self.widget then
return 0, 0
end
if self._expand_mode == "fill" then
return width, height
else
return base.fit_widget(self, context, self.widget, width, height)
end
end
function infoshape:set_widget(widget)
if widget then
base.check_widget(widget)
end
self.widget = widget
self:emit_signal("widget::layout_changed")
end
function infoshape:get_children()
return {self.widget}
end
function infoshape:set_children(children)
self.widget = children and children[1]
self:emit_signal("widget::layout_changed")
end
function infoshape:reset()
self.direction = nil
self:set_widget(nil)
end
--- Add a new info info shape.
--
-- Valid args are:
--
-- * align: "right" (default), "left" or "center"
-- * shape: A `gears.shape` compatible function (default: gears.shape.rounded_bar)
-- * layer: "below" (default) or "above"
-- * shape_border_width: The border width (default: 0)
-- * shape_border_color: The shape border color (default: none)
-- * font_description: A pango font description or string (default: Verdana bold)
-- * bg: The infoshape background color (default: beautiful.bg_infoshape or beautiful.bg_focus)
-- * fg: The text color (default: transparent)
-- * alpha: The infoshape alpha (transparency) a number between 0 and 1
--
-- @tparam string text The info text
-- @tparam[opt={}] table args the arguments
-- @treturn A unique identifier key
--
function infoshape:add_infoshape(args)
local args = args or {}
local align = args.align or "right"
local layer = args.layer or "below"
if not self["_"..layer] then
self["_"..layer] = {}
end
local l = self["_"..layer]
if not l[align] then
l[align] = {}
end
table.insert(l[align], args)
self:emit_signal("widget::redraw_needed")
end
function infoshape:add_infoshapes(args)
for k, v in ipairs(args or {}) do
self:add_infoshape(v)
end
end
--- Replace all infshapes with "args"
function infoshape:set_infoshapes(args)
self._above = {}
self._below = {}
self:add_infoshapes(args)
self:emit_signal("widget::redraw_needed")
end
--TODO use beautiful
function infoshape:set_default_shape(shape)
default_shape = shape
end
function infoshape:set_default_font_description(desc)
default_font_description = desc
end
--TODO set default bg
--TODO set default fg
function infoshape:remove(key)
end
function infoshape:set_text(key, text)
end
function infoshape:set_spacing(spacing)
end
function infoshape:set_bg(col)
end
function infoshape:set_fg(col)
end
--- Set the expand mode.
-- Valid modes are:
--
-- * "fit": Take the same space as the child widget (default)
-- * "fill": Take all the available space
--
-- @tparams string mode The expand mode
function infoshape:set_expand(mode)
self._expand_mode = mode
end
function infoshape:set_align(align)
self._align = align
end
local function new(widget, dir)
local ret = base.make_widget()
util.table.crush(ret, infoshape)
ret:set_widget(widget)
return ret
end
function infoshape.mt:__call(...)
return new(...)
end
return setmetatable(infoshape, infoshape.mt)
-- kate: space-indent on; indent-width 4; replace-tabs on;

View File

@ -1,11 +1,11 @@
return { return {
checkbox = require( "radical.widgets.checkbox" ), checkbox = require( "radical.widgets.checkbox" ),
scroll = require( "radical.widgets.scroll" ), scroll = require( "radical.widgets.scroll" ),
filter = require( "radical.widgets.filter" ), filter = require( "radical.widgets.filter" ),
fkey = require( "radical.widgets.fkey" ), fkey = require( "radical.widgets.fkey" ),
table = require( "radical.widgets.table" ), table = require( "radical.widgets.table" ),
header = require( "radical.widgets.header" ), header = require( "radical.widgets.header" ),
piechart = require( "radical.widgets.piechart" ), piechart = require( "radical.widgets.piechart" ),
separator= require( "radical.widgets.separator"), separator = require( "radical.widgets.separator"),
underlay = require( "radical.widgets.underlay" ) infoshapes = require( "radical.widgets.infoshapes" ),
} }

View File

@ -1,111 +0,0 @@
local type = type
local ipairs = ipairs
local color = require("gears.color")
local gsurface = require("gears.surface")
local cairo = require("lgi").cairo
local pango = require("lgi").Pango
local pangocairo = require("lgi").PangoCairo
local beautiful = require("beautiful")
local shape = require("gears.shape")
local module = {}
local pango_l,pango_crx = {},{}
--TODO using the current cairo path extents, it would be possible to merge the 2 function
-- and have an abstract underlay that work with most shapes
local function draw_item(cr,x,y,width,height,padding,args)
cr:save()
cr:rectangle(x,y,width+padding,height+padding)
cr:clip()
local s = shape.transform(shape.rounded_bar) : translate(x + padding, y + padding/4)
s(cr, width - 2*padding, height - padding/2)
cr:set_source(color(args.bg or beautiful.bg_underlay or beautiful.bg_alternate))
cr:fill()
cr:set_source(color(args.fg or beautiful.bg_normal))
cr:set_operator(cairo.Operator.CLEAR)
cr:move_to(x+height/2 + 2,y+padding/4 + (args.margins or 0)-(args.padding or 0)/2)
cr:show_layout(pango_l[height])
cr:restore()
end
function module.draw_arrow(cr,x,y,width,height,padding,args)
cr:save()
cr:rectangle(x,y,width+padding,height+padding)
cr:clip()
padding=padding/2
local mid = (height-2*padding)/2
local s = shape.transform(shape.hexagon) : translate(x, padding)
s(cr, width, height - 2*padding)
cr:set_source(color(args.bg or beautiful.bg_underlay or beautiful.bg_alternate))
cr:fill()
cr:set_source(color(args.fg or beautiful.bg_normal))
cr:set_operator(cairo.Operator.CLEAR)
cr:move_to(x+height/2+2,y+padding/2)
cr:show_layout(pango_l[height])
cr:restore()
end
function module.fit(text, args, context)
local context = context or {}
local args = args or {}
local height = args.height or (beautiful.menu_height)
local padding = height/4--beautiful.default_height/3
local dpi = context.dpi or beautiful.xresources.get_dpi(1)
-- Get text height
if not pango_l[height] then
local pango_crx = pangocairo.font_map_get_default():create_context()
pango_l[height] = pango.Layout.new(pango_crx)
local desc = pango.FontDescription()
desc:set_family("Verdana")
desc:set_weight(pango.Weight.BOLD)
desc:set_size((height-padding*2) * pango.SCALE)
-- desc:set_variant(pango.Variant.SMALL_CAPS)
pango_l[height]:set_font_description(desc)
end
local pango_layout = pango_l[height]
pango_layout:get_context():set_resolution(dpi)
pango_layout:context_changed()
-- Compute full width
local ret,full_width = {},0
for k,v in ipairs(type(text) == "table" and text or {text}) do
pango_layout.text = v
ret[k] = pango_layout:get_pixel_extents().width + height + padding
full_width = full_width + ret[k]
end
return full_width,ret
end
function module.draw(text, args, context)
local args = args or {}
local height = args.height or (beautiful.menu_height)
local padding = height/4--beautiful.default_height/3
local full_width,ret = module.fit(text, args, context)
local img = cairo.ImageSurface.create(cairo.Format.ARGB32, full_width+(args.padding_right or 0), height+padding)
cr = cairo.Context(img)
-- Draw every item
local x = 0
for k,v in ipairs(type(text) == "table" and text or {text}) do
pango_l[height].text = v
local draw_f = args.style or draw_item
draw_f(cr,x,0,ret[k],height,padding,args)
x = x + ret[k]
end
return img
end
return setmetatable(module, { __call = function(_, ...) return new(...) end })
-- kate: space-indent on; indent-width 2; replace-tabs on;