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
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 |
| filter_string | Default filter string | string |
| 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 |
| max_items | Maximum number of items before showing scrollbar | number |
| 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 |
| checkable | Is the item dual state (a checkbox) | 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 |
| suffix_widget | Widget to append at the end of the item | widget |
| 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 |
| overlay | See menu.overlay | function |
| margins | Read/Write table (left,right,top and bottom) | dynamic table |
| underlay_alpha | Underlay (see item options) opacity | 0-1 |
| 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" |
| infoshapes | See the infoshapes widget documentation | array of infoshapes|
| overlay_draw | Draw a custom painter on top of the item | draw function |
###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_draw_underlay | Function returning the underlay pixmap | function(array,width) |
| 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) |
| dock_corner_radius | The dock menu type corner radius | Number (default 10) |
| 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
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
allow to register such new category. For a common example, the underlay, it
will be possible to pass `underlay_bg_focus` or `underlay_fg_disabled` colors
or any other registered states.
allow to register such new category.
Some generic menu can also register beautiful namespaces using the
`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,
prefix_widget = args.prefix_widget or nil,
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_bg = args.overlay_bg or nil,
filter_underlay = args.filter_underlay or nil,
filter_prefix = args.filter_prefix or "Filter:",
enable_keyboard = (args.enable_keyboard ~= false),
@ -375,8 +367,6 @@ local function new(args)
y = args.y or 0,
sub_menu_on = args.sub_menu_on or module.event.SELECTED,
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,
spacing = args.spacing or nil,
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")
end
-- Setup the infoshapes
if item._internal.infoshapes then
item.infoshapes = item._internal.infoshapes
end
item.widget:emit_signal("widget::updated")
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.layout = args.layout or args.internal.layout_func
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
-- Create the dock

View File

@ -81,15 +81,15 @@ local function is_in_tag(t,c)
return false
end
local function reload_underlay(client,item)
local underlays = {}
local function reload_infoshapes(client,item)
local infoshapes = {}
for k,v in ipairs(client:tags()) do
underlays[#underlays+1] = v.name
infoshapes[#infoshapes+1] = {text = v.name}
end
if item then
item.underlay = underlays
item.infoshapes = infoshapes
end
return underlays
return infoshapes
end
local function reload_highlight(i)
@ -155,7 +155,7 @@ local function new(args)
local c = item.client
if c.screen ~= scr then return end
client2.toggletag (t, c)
reload_underlay(c,item)
reload_infoshapes(c,item)
if not auto_release then
reload_highlight(item)
end
@ -170,7 +170,7 @@ local function new(args)
local c = item.client
if c.screen ~= scr then return end
client2.movetotag(t, c)
reload_underlay(c,item)
reload_infoshapes(c,item)
if not auto_release then
reload_highlight(item)
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 = "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 = "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
end
local underlays = reload_underlay(v)
local underlays = reload_infoshapes(v)
local i = currentMenu:add_item({
text = v.name,
icon = v.icon or module.default_icon,
suffix_widget = not auto_release and l or nil,
selected = capi.client.focus and capi.client.focus == v,
underlay = underlays,
infoshapes = underlays,
checkable = (not auto_release) and v.screen == scr,
checked = v.screen == scr and (not auto_release and is_in_tag(t,v)) or nil,
button1 = function(a,b,c,d,no_hide)

View File

@ -22,40 +22,40 @@ function module.signals()
return sigMenu
end
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"})
sigkill = sigMenu:add_item({text="SIGKILL" , button1 = function() util.spawn("kill -s KILL "..module.client.pid);mainMenu.visible = false end,underlay="9"})
sigint = sigMenu:add_item({text="SIGINT" , button1 = function() util.spawn("kill -s INT "..module.client.pid);mainMenu.visible = false end,underlay="2"})
sigquit = sigMenu:add_item({text="SIGQUIT" , button1 = function() util.spawn("kill -s QUIT "..module.client.pid);mainMenu.visible = false end,underlay="3"})
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,infoshapes = {{text="9"}}})
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,infoshapes = {{text="3"}}})
-- 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})
sigalrm = sigMenu:add_item({text="SIGALRM" , button1 = function() util.spawn("kill -s ALRM "..module.client.pid);mainMenu.visible = false end,underlay="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"})
sigpipe = sigMenu:add_item({text="SIGPIPE" , button1 = function() util.spawn("kill -s PIPE "..module.client.pid);mainMenu.visible = false end,underlay="13"})
sigpoll = sigMenu:add_item({text="SIGPOLL" , button1 = function() util.spawn("kill -s POLL "..module.client.pid);mainMenu.visible = false end,underlay=nil})
sigprof = sigMenu:add_item({text="SIGPROF" , button1 = function() util.spawn("kill -s PROF "..module.client.pid);mainMenu.visible = false end,underlay="27"})
sigusr1 = sigMenu:add_item({text="SIGUSR1" , button1 = function() util.spawn("kill -s USR1 "..module.client.pid);mainMenu.visible = false end,underlay="10"})
sigusr2 = sigMenu:add_item({text="SIGUSR2" , button1 = function() util.spawn("kill -s USR2 "..module.client.pid);mainMenu.visible = false end,underlay="12"})
sigsigvtalrm = sigMenu:add_item({text="SIGVTALRM" , button1 = function() util.spawn("kill -s VTALRM "..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,underlay=nil})
sigpwr = sigMenu:add_item({text="SIGPWR" , button1 = function() util.spawn("kill -s PWR "..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,underlay=nil})
sigchld = sigMenu:add_item({text="SIGCHLD" , button1 = function() util.spawn("kill -s CHLD "..module.client.pid);mainMenu.visible = false end,underlay="17"})
sigurg = sigMenu:add_item({text="SIGURG" , button1 = function() util.spawn("kill -s URG "..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,underlay=nil})
sigttin = sigMenu:add_item({text="SIGTTIN" , button1 = function() util.spawn("kill -s TTIN "..module.client.pid);mainMenu.visible = false end,underlay="21"})
sigttou = sigMenu:add_item({text="SIGTTOU" , button1 = function() util.spawn("kill -s TTOU "..module.client.pid);mainMenu.visible = false end,underlay="22"})
sigstop = sigMenu:add_item({text="SIGSTOP" , button1 = function() util.spawn("kill -s STOP "..module.client.pid);mainMenu.visible = false end,underlay="17"})
sigcont = sigMenu:add_item({text="SIGCONT" , button1 = function() util.spawn("kill -s CONT "..module.client.pid);mainMenu.visible = false end,underlay="18"})
sigabrt = sigMenu:add_item({text="SIGABRT" , button1 = function() util.spawn("kill -s ABRT "..module.client.pid);mainMenu.visible = false end,underlay="6"})
sigfpe = sigMenu:add_item({text="SIGFPE" , button1 = function() util.spawn("kill -s FPE "..module.client.pid);mainMenu.visible = false end,underlay="8"})
sigill = sigMenu:add_item({text="SIGILL" , button1 = function() util.spawn("kill -s ILL "..module.client.pid);mainMenu.visible = false end,underlay="4"})
sigsegv = sigMenu:add_item({text="SIGSEGV" , button1 = function() util.spawn("kill -s SEGV "..module.client.pid);mainMenu.visible = false end,underlay="11"})
sigtrap = sigMenu:add_item({text="SIGTRAP" , button1 = function() util.spawn("kill -s TRAP "..module.client.pid);mainMenu.visible = false end,underlay="5"})
sigsys = sigMenu:add_item({text="SIGSYS" , button1 = function() util.spawn("kill -s SYS "..module.client.pid);mainMenu.visible = false end,underlay="12"})
sigemt = sigMenu:add_item({text="SIGEMT" , button1 = function() util.spawn("kill -s EMT "..module.client.pid);mainMenu.visible = false end,underlay=nil})
sigbus = sigMenu:add_item({text="SIGBUS" , button1 = function() util.spawn("kill -s BUS "..module.client.pid);mainMenu.visible = false end,underlay="7"})
sigxcpu = sigMenu:add_item({text="SIGXCPU" , button1 = function() util.spawn("kill -s XCPU "..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,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,infoshapes = {{text="14"}}})
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,infoshapes = {{text="13"}}})
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,infoshapes = {{text="27"}}})
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,infoshapes = {{text="12"}}})
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,infoshapes = {}})
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,infoshapes = {}})
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,infoshapes = {}})
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,infoshapes = {{text="21"}}})
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,infoshapes = {{text="17"}}})
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,infoshapes = {{text="6"}}})
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,infoshapes = {{text="4"}}})
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,infoshapes = {{text="5"}}})
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,infoshapes = {}})
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,infoshapes = {}})
sigxfsz = sigMenu:add_item({text="SIGXFSZ" , button1 = function() util.spawn("kill -s XFSZ "..module.client.pid);mainMenu.visible = false end,infoshapes = {}})
return sigMenu
end
@ -103,4 +103,4 @@ function module.screenshot(clients,geo)
end
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 theme = require( "radical.theme")
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 _cache = setmetatable({}, { __mode = 'k' })
@ -126,22 +127,45 @@ local function unmanage_callback(c)
_cache[c] = nil
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
local function reload_underlay(c)
local udl,item = {},_cache[c]
if item then
if c.ontop then
udl[#udl+1] = "ontop"
local function reload_infoshapes(c)
local item = _cache[c]
local infoshapes = {}
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
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
-- Reload title and icon
@ -180,10 +204,13 @@ local function create_client_item(c,screen)
end
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)
item:connect_signal("mouse::leave", function()
item.overlay = nil
item.infoshapes = {}
end)
item.add_suffix = function(w,w2)
@ -198,7 +225,7 @@ end
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
local ret = create_client_item(c,screen)
reload_underlay(c)
reload_infoshapes(c)
if capi.client.focus == c then
ret.selected = true
end
@ -276,10 +303,7 @@ local function new(screen)
disable_markup = true ,
fg = beautiful.tasklist_fg or beautiful.fg_normal ,
bg = beautiful.tasklist_bg or beautiful.bg_normal ,
underlay_style = beautiful.tasklist_underlay_style or radical.widgets.underlay.draw_arrow,
overlay_align = "center" ,
overlay_alpha = 1 ,
overlay_bg = beautiful.tasklist_bg_overlay ,
-- overlay_bg = beautiful.tasklist_bg_overlay ,
icon_transformation = beautiful.tasklist_icon_transformation ,
default_item_margins = beautiful.tasklist_default_item_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("focus" , focus )
capi.client.connect_signal("unfocus" , unfocus )
capi.client.connect_signal("property::sticky" , reload_underlay )
capi.client.connect_signal("property::ontop" , reload_underlay )
capi.client.connect_signal("property::floating" , reload_underlay )
capi.client.connect_signal("property::sticky" , reload_infoshapes )
capi.client.connect_signal("property::ontop" , reload_infoshapes )
capi.client.connect_signal("property::floating" , reload_infoshapes )
capi.client.connect_signal("property::name" , reload_content )
capi.client.connect_signal("property::icon" , reload_content )
capi.client.connect_signal("property::minimized", minimize_callback )

View File

@ -1,7 +1,6 @@
local type = type
local base = require( "wibox.widget.base" )
local tooltip = require( "radical.tooltip" )
local underlay = require( "radical.widgets.underlay")
local aw_button = require( "awful.button" )
local beautiful = require( "beautiful" )
@ -65,75 +64,6 @@ local function set_menu(self,menu, event, button_id)
return bt
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 context = context or 1
@ -152,8 +82,6 @@ base.make_widget = function(...)
local ret = base._make_widget(...)
ret.set_tooltip = set_tooltip
ret.set_menu = set_menu
ret.set_underlay = set_underlay
ret.set_overlay = set_overlay
-- Textboxes already have it
if not ret.get_preferred_size then

View File

@ -75,6 +75,15 @@ local function hide_sub_menu(item,data)
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 is_watching = false
-- local mouse_tracker = object{}
@ -110,6 +119,7 @@ local function new_item(data,args)
tooltip = args.tooltip or nil ,
style = args.style or data.item_style ,
layout = args.layout or args.item_layout or nil ,
infoshapes = args.infoshapes or nil ,
overlay_draw= args.overlay_draw or data.overlay_draw ,
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
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.underlay = args.underlay
item.overlay = args.overlay
for i=1,10 do
item["button"..i] = args["button"..i]
@ -202,6 +192,9 @@ local function new_item(data,args)
data._current_item = item
end
-- Overlay and underlay
item.set_infoshapes = set_infoshapes
item.set_icon = function (_,value)
local icon_w = item._internal.icon_w
@ -274,4 +267,4 @@ local function new_item(data,args)
end
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 beautiful = require( "beautiful" )
local color = require( "gears.color" )
local cairo = require( "lgi" ).cairo
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 util = require( "awful.util" )
local margins2 = require( "radical.margins")
local shape = require( "gears.shape" )
local surface = require( "gears.surface" )
local beautiful = require( "beautiful" )
local color = require( "gears.color" )
local cairo = require( "lgi" ).cairo
local wibox = require( "wibox" )
local checkbox = require( "radical.widgets.checkbox" )
local fkey = require( "radical.widgets.fkey" )
local infoshapes = require( "radical.widgets.infoshapes" )
local theme = require( "radical.theme" )
local util = require( "awful.util" )
local margins2 = require( "radical.margins" )
local shape = require( "gears.shape" )
local surface = require( "gears.surface" )
local module = {}
-- Add [F1], [F2] ... to items
function module:setup_fkey(item,data)
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
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)
if self._item.overlay then
module.paint_underlay(self._data, self._item, cr, width, height, "overlay")
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
--TODO get rid of this, use the stack container
if self._item.overlay_draw then
self._item.overlay_draw(context,self._item,cr,width,height)
end
end
-- Apply icon transformation
@ -195,18 +161,6 @@ function module.setup_event(data,item,widget)
-- 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
local function create_item(item,data,args)
@ -230,13 +184,7 @@ local function create_item(item,data,args)
-- Text
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)
item.set_text = function (_,value)
if data.disable_markup then
@ -260,6 +208,7 @@ local function create_item(item,data,args)
item.widget = wibox.widget.base.make_widget_declarative {
-- Widgets
{
-- Widget
{
-- This is where the content is placed
@ -276,7 +225,16 @@ local function create_item(item,data,args)
-- Attributes
layout = wibox.layout.fixed.horizontal
},
tb,
{
-- Underlay and overlay
tb,
-- Attributes
widget = infoshapes,
spacing = 10,
infoshapes = item.infoshapes,
id = "infoshapes",
},
{
-- Suffixes
@ -314,9 +272,6 @@ local function create_item(item,data,args)
item._internal.align = item.widget:get_children_by_id("main_align" )[1]
-- 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.icon_w = icon
@ -336,11 +291,6 @@ local function create_item(item,data,args)
local item_style = item.style or data.item_style
item_style(item,{})
-- Setup dynamic underlay
item:connect_signal("underlay::changed",function(_,udl)
item.widget:emit_signal("widget::updated")
end)
-- Setup events
module.setup_event(data,item)

View File

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

View File

@ -1,130 +1,10 @@
local setmetatable = setmetatable
local beautiful = require( "beautiful" )
local color = require( "gears.color" )
local cairo = require( "lgi" ).cairo
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 margins2 = require( "radical.margins" )
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
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
@ -150,12 +30,6 @@ local function create_item(item,data,args)
-- Layout (right)
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
local icon = horizontal.setup_icon(horizontal,item,data)
icon.fit = function(...)
@ -170,16 +44,16 @@ local function create_item(item,data,args)
end
-- Checkbox
local ck = module:setup_checked(item,data)
local ck = horizontal:setup_checked(item,data)
if ck then
right:add(ck)
end
-- Hover
module:setup_hover(item,data)
horizontal:setup_hover(item,data)
-- Sub_arrow
local ar = module:setup_sub_menu_arrow(item,data)
local ar = horizontal:setup_sub_menu_arrow(item,data)
if ar then
right:add(ar)
end
@ -195,12 +69,6 @@ local function create_item(item,data,args)
-- Text
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)
if data.disable_markup then
@ -254,20 +122,10 @@ local function create_item(item,data,args)
item.widget:set_fg(item._private_data.fg)
-- Setup events
module.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
horizontal.setup_event(data,item)
return bg
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
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)
item._private_data._fit = wibox.widget.background.fit
if item._internal.margin_w then
@ -56,9 +30,6 @@ function module:setup_item(data,item,args)
end
end
-- Text need to take as much space as possible, override default
module.setup_text(item,data)
-- Compute the minimum width
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)

View File

@ -96,7 +96,6 @@ function module.setup_colors(data,args)
or beautiful["menu_border_color_"..v.beautiful_name]
or beautiful["border_color_"..v.beautiful_name]
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
-- Handle custom sections
@ -182,4 +181,4 @@ function module.add_section(data,section,args)
end
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 = {}
--TODO broken
local function new(data)
local filter_tb = wibox.widget.textbox()
local bg = wibox.widget.background()
@ -17,7 +18,7 @@ local function new(data)
filter_tb.fit = function(tb,context,width,height)
return width,data.item_height
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()
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))

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 {
checkbox = require( "radical.widgets.checkbox" ),
scroll = require( "radical.widgets.scroll" ),
filter = require( "radical.widgets.filter" ),
fkey = require( "radical.widgets.fkey" ),
table = require( "radical.widgets.table" ),
header = require( "radical.widgets.header" ),
piechart = require( "radical.widgets.piechart" ),
separator= require( "radical.widgets.separator"),
underlay = require( "radical.widgets.underlay" )
}
checkbox = require( "radical.widgets.checkbox" ),
scroll = require( "radical.widgets.scroll" ),
filter = require( "radical.widgets.filter" ),
fkey = require( "radical.widgets.fkey" ),
table = require( "radical.widgets.table" ),
header = require( "radical.widgets.header" ),
piechart = require( "radical.widgets.piechart" ),
separator = require( "radical.widgets.separator"),
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;