diff --git a/README.md b/README.md index 43dacde..ddadafb 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/base.lua b/base.lua index e6e4203..45295fe 100644 --- a/base.lua +++ b/base.lua @@ -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 {}, diff --git a/common.lua b/common.lua index ede8c61..1bc3a82 100644 --- a/common.lua +++ b/common.lua @@ -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 \ No newline at end of file +return module +-- kate: space-indent on; indent-width 4; replace-tabs on; diff --git a/dock.lua b/dock.lua index a54a76a..ec82069 100644 --- a/dock.lua +++ b/dock.lua @@ -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 diff --git a/impl/alttab/init.lua b/impl/alttab/init.lua index 7677f62..dd2a5d2 100644 --- a/impl/alttab/init.lua +++ b/impl/alttab/init.lua @@ -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) diff --git a/impl/common/client.lua b/impl/common/client.lua index bef44cb..bca5c82 100644 --- a/impl/common/client.lua +++ b/impl/common/client.lua @@ -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; \ No newline at end of file +-- kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/impl/tasklist/init.lua b/impl/tasklist/init.lua index e2ddded..0689c0a 100644 --- a/impl/tasklist/init.lua +++ b/impl/tasklist/init.lua @@ -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 and 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 ) diff --git a/init.lua b/init.lua index c73bf04..7acdd57 100644 --- a/init.lua +++ b/init.lua @@ -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 diff --git a/item/init.lua b/item/init.lua index b4b7c4d..7c0be97 100644 --- a/item/init.lua +++ b/item/init.lua @@ -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; \ No newline at end of file +-- kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/item/layout/horizontal.lua b/item/layout/horizontal.lua index 6e12e2f..d71b350 100644 --- a/item/layout/horizontal.lua +++ b/item/layout/horizontal.lua @@ -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) diff --git a/item/layout/icon.lua b/item/layout/icon.lua index d60f658..34e6ae1 100644 --- a/item/layout/icon.lua +++ b/item/layout/icon.lua @@ -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 = {} diff --git a/item/layout/notification.lua b/item/layout/notification.lua index 95db371..74efa55 100644 --- a/item/layout/notification.lua +++ b/item/layout/notification.lua @@ -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; diff --git a/layout/vertical.lua b/layout/vertical.lua index 3d0afa6..96c41f1 100644 --- a/layout/vertical.lua +++ b/layout/vertical.lua @@ -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) diff --git a/theme/init.lua b/theme/init.lua index 99e3229..b120dea 100644 --- a/theme/init.lua +++ b/theme/init.lua @@ -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; \ No newline at end of file +-- kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/widgets/filter.lua b/widgets/filter.lua index dd9f750..aa587d8 100644 --- a/widgets/filter.lua +++ b/widgets/filter.lua @@ -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(" ".. data.filter_prefix .." "..(is_empty and data.filter_placeholder or data.filter_string)) diff --git a/widgets/infoshapes.lua b/widgets/infoshapes.lua new file mode 100644 index 0000000..f5c8f86 --- /dev/null +++ b/widgets/infoshapes.lua @@ -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; diff --git a/widgets/init.lua b/widgets/init.lua index 3b9d961..b06b03d 100644 --- a/widgets/init.lua +++ b/widgets/init.lua @@ -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" ) -} \ No newline at end of file + 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" ), +} diff --git a/widgets/underlay.lua b/widgets/underlay.lua deleted file mode 100644 index b5b6e71..0000000 --- a/widgets/underlay.lua +++ /dev/null @@ -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; \ No newline at end of file