Add better tooling to track menu dimensions
This commit is contained in:
parent
f215d24f35
commit
46481f0a8a
30
context.lua
30
context.lua
|
@ -2,6 +2,7 @@ local base = require( "radical.base" )
|
|||
local print = print
|
||||
local unpack = unpack
|
||||
local debug = debug
|
||||
local rawset = rawset
|
||||
local type = type
|
||||
local setmetatable = setmetatable
|
||||
local color = require( "gears.color" )
|
||||
|
@ -15,6 +16,7 @@ local checkbox = require( "radical.widgets.checkbox" )
|
|||
local arrow_style = require( "radical.style.arrow" )
|
||||
local item_mod = require("radical.item")
|
||||
local glib = require("lgi").GLib
|
||||
local margins2 = require("radical.margins")
|
||||
|
||||
local capi,module = { mouse = mouse , screen = screen, keygrabber = keygrabber },{}
|
||||
|
||||
|
@ -72,7 +74,8 @@ local function set_position(self)
|
|||
if parent.direction == "right" then
|
||||
ret={x=parent.x-self.width,y=parent.y+(self.parent_item.y)}
|
||||
else
|
||||
ret={x=parent.x+parent.width,y=parent.y+(self.parent_item.y)-self.style.margins.TOP}
|
||||
local margins = self.margins
|
||||
ret={x=parent.x+parent.width,y=parent.y+(self.parent_item.y)-(margins and self.margins.top or self.style.margins.TOP)}
|
||||
|
||||
--Handle when the menu doesn't fit in the srceen horizontally
|
||||
if ret.x+self.width > src_geo.x + src_geo.width then
|
||||
|
@ -81,13 +84,13 @@ local function set_position(self)
|
|||
|
||||
-- Handle when the menu doesn't fit on the screen vertically
|
||||
if ret.y+self.height > src_geo.y + src_geo.height then
|
||||
ret.y = ret.y - self.height + self.item_height + 2*self.style.margins.TOP
|
||||
ret.y = ret.y - self.height + self.item_height + 2*(margins and self.margins.top or self.style.margins.TOP)
|
||||
end
|
||||
end
|
||||
elseif parent then
|
||||
local drawable_geom = parent.drawable.drawable.geometry(parent.drawable.drawable)
|
||||
if (self.direction == "left") or (self.direction == "right") then
|
||||
ret = {x=drawable_geom.x+((self.direction == "right") and - self.width or drawable_geom.width),y=drawable_geom.y+parent.y+((self.arrow_type ~= base.arrow_type.NONE) and parent.height/2-(self.arrow_x or 20)-6 or 0)}
|
||||
ret = {x=drawable_geom.x+((self.direction == "right") and - self.width or drawable_geom.width),y=drawable_geom.y+parent.y--[[+((self.arrow_type ~= base.arrow_type.NONE) and parent.height/2-(self.arrow_x or 20)-6 or 0)]]}
|
||||
else
|
||||
ret = {x=drawable_geom.x+parent.x-((self.arrow_type ~= base.arrow_type.NONE) and (self.arrow_x or 20)+11-parent.width/2 or 0),y=(self.direction == "bottom") and drawable_geom.y-self.height or drawable_geom.y+drawable_geom.height}
|
||||
end
|
||||
|
@ -99,7 +102,7 @@ local function set_position(self)
|
|||
if prefy then
|
||||
ret.y = prefy
|
||||
end
|
||||
elseif not parent then --Use mouse position to set position --TODO it is called too often
|
||||
else --Use mouse position to set position --TODO it is called too often
|
||||
ret = capi.mouse.coords()
|
||||
local draw = awful.mouse.wibox_under_pointer and awful.mouse.wibox_under_pointer() or awful.mouse.drawin_under_pointer and awful.mouse.drawin_under_pointer()
|
||||
if draw then
|
||||
|
@ -152,11 +155,22 @@ local function setup_drawable(data)
|
|||
data.get_visible = function() return private_data.visible end
|
||||
data.get_direction = function() return private_data.direction end
|
||||
data.get_margins = function()
|
||||
local ret = {left=data.border_width,right=data.border_width,top=data.style.margins.TOP,bottom=data.style.margins.BOTTOM}
|
||||
if data.arrow_type ~= base.arrow_type.NONE then
|
||||
ret[data.direction] = ret[data.direction]+13
|
||||
if not internal._margins then
|
||||
local ret = {
|
||||
left = data.border_width+data.style.margins.LEFT ,
|
||||
right = data.border_width+data.style.margins.RIGHT ,
|
||||
top = data.border_width+data.style.margins.TOP ,
|
||||
bottom = data.border_width+data.style.margins.BOTTOM ,
|
||||
}
|
||||
m = margins2(internal.margin,ret)
|
||||
rawset(m,"_reset",m.reset)
|
||||
m.reset = function(margins)
|
||||
m.defaults = ret
|
||||
m:_reset()
|
||||
end
|
||||
internal._margins = m
|
||||
end
|
||||
return ret
|
||||
return internal._margins
|
||||
end
|
||||
|
||||
--Setters
|
||||
|
|
|
@ -14,25 +14,48 @@ local module = {
|
|||
}
|
||||
}
|
||||
|
||||
local focussed,default = nil, nil
|
||||
local state_cache = {}
|
||||
|
||||
local function gen(item_height,bg_color,border_color)
|
||||
local img = cairo.ImageSurface(cairo.Format.ARGB32, item_height,item_height)
|
||||
local function gen(width,height,bg_color,border_color)
|
||||
local img = cairo.ImageSurface(cairo.Format.ARGB32, width,height)
|
||||
local cr = cairo.Context(img)
|
||||
local rad = corner_radius or 3
|
||||
cr:set_source(color(bg_color))
|
||||
cr:arc(rad,rad,rad,0,2*math.pi)
|
||||
cr:arc(item_height-rad,rad,rad,0,2*math.pi)
|
||||
cr:arc(rad,item_height-rad,rad,0,2*math.pi)
|
||||
cr:arc(item_height-rad,item_height-rad,rad,0,2*math.pi)
|
||||
cr:arc(width-rad,rad,rad,0,2*math.pi)
|
||||
cr:arc(rad,height-rad,rad,0,2*math.pi)
|
||||
cr:arc(width-rad,height-rad,rad,0,2*math.pi)
|
||||
cr:fill()
|
||||
cr:rectangle(0,rad, item_height, item_height-2*rad)
|
||||
cr:rectangle(rad,0, item_height-2*rad, item_height)
|
||||
cr:rectangle(0,rad, width, height-2*rad)
|
||||
cr:rectangle(rad,0, width-2*rad, height)
|
||||
cr:fill()
|
||||
return cairo.Pattern.create_for_surface(img)
|
||||
end
|
||||
|
||||
local function widget_draw(self, w, cr, width, height)
|
||||
|
||||
local state = self._item.state or {}
|
||||
local current_state = state._current_key or ""
|
||||
if not state_cache[current_state] then
|
||||
state_cache[current_state] = {}
|
||||
end
|
||||
local cache = state_cache[current_state]
|
||||
local hash = width+1234*height
|
||||
|
||||
local cached = cache[hash]
|
||||
|
||||
--Generate the pixmap
|
||||
if not cached then
|
||||
local state_name = current_state == "" and "bg" or "bg_"..(base.colors_by_id[current_state] or "")
|
||||
cached = gen(width,height,self._item[state_name],bc)
|
||||
cache[hash] = cached
|
||||
end
|
||||
|
||||
if current_state ~= self._last_state then
|
||||
self:set_bg(cached)
|
||||
self._last_state = current_state
|
||||
end
|
||||
|
||||
self:_drawrounded(w, cr, width, height)
|
||||
local overlay = self._item and self._item.overlay
|
||||
if overlay then
|
||||
|
@ -47,21 +70,7 @@ local function draw(item,args)
|
|||
item.widget._drawrounded = item.widget.draw
|
||||
item.widget.draw = widget_draw
|
||||
item.widget._overlay_init = true
|
||||
end
|
||||
|
||||
local ih = item.height
|
||||
local iw = item.width
|
||||
if iw and iw > ih then
|
||||
ih = iw
|
||||
end
|
||||
if not focussed or not focussed[ih] then
|
||||
if not focussed then
|
||||
focussed,default={},{}
|
||||
end
|
||||
local bc = item.border_color
|
||||
|
||||
focussed[ih] = gen(ih,item.bg_focus,bc)
|
||||
default [ih] = gen(ih,item.bg,bc)
|
||||
item.widget._item = item
|
||||
end
|
||||
|
||||
local state = item.state or {}
|
||||
|
@ -69,13 +78,10 @@ local function draw(item,args)
|
|||
local state_name = base.colors_by_id[current_state]
|
||||
|
||||
if current_state == base.item_flags.SELECTED or (item._tmp_menu) then
|
||||
item.widget:set_bg(focussed[ih])
|
||||
item.widget:set_fg(item["fg_focus"])
|
||||
elseif state_name then --TODO incomplete
|
||||
item.widget:set_bg(args.color or item["bg_"..state_name])
|
||||
elseif state_name then
|
||||
item.widget:set_fg( item["fg_"..state_name])
|
||||
else
|
||||
item.widget:set_bg(default[ih])
|
||||
item.widget:set_fg(item["fg_normal"])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -144,9 +144,8 @@ local function new(data)
|
|||
base = require( "radical.base" )
|
||||
end
|
||||
local l = wibox.layout.fixed.horizontal()
|
||||
l.fit = function(a1,a2,a3)
|
||||
local result,r2 = wibox.layout.fixed.fit(a1,99999,99999)
|
||||
-- return data.rowcount*(data.item_width or data.default_width),data.item_height
|
||||
l.fit = function(a1,a2,a3,force_values)
|
||||
local result,r2 = wibox.layout.fixed.fit(a1,force_values and a2 or 99999,force_values and a3 or 99999)
|
||||
local w,h
|
||||
if data.auto_resize and data._internal.largest_item_h then
|
||||
w,h = data.rowcount*(data.item_width or data.default_width),data._internal.largest_item_h_v > data.item_height and data._internal.largest_item_h_v or data.item_height
|
||||
|
|
|
@ -194,33 +194,21 @@ function module:setup_item(data,item,args)
|
|||
item.widget:emit_signal("widget::updated")
|
||||
end
|
||||
|
||||
local function compute_geo(data)
|
||||
local function compute_geo(data,width,height,force_values)
|
||||
local w = data.default_width
|
||||
if data.auto_resize and data._internal.largest_item_w then
|
||||
w = data._internal.largest_item_w_v > data.default_width and data._internal.largest_item_w_v or data.default_width
|
||||
end
|
||||
local visblerow = data.filter_string == "" and data.rowcount or data._internal.visible_item_count
|
||||
if data.max_items and data.max_items < data.rowcount then
|
||||
visblerow = data.max_items
|
||||
if data.filter_string ~= "" then
|
||||
local cur,vis = (data._start_at or 1),0
|
||||
while (data._internal.items[cur] and data._internal.items[cur]) and cur < data.max_items + (data._start_at or 1) do
|
||||
vis = vis + (data._internal.items[cur]._filter_out and 0 or 1)
|
||||
cur = cur +1
|
||||
end
|
||||
visblerow = vis
|
||||
end
|
||||
end
|
||||
|
||||
local visblerow = data.visible_row_count
|
||||
|
||||
local sw,sh = data._internal.suf_l:fit(9999,9999)
|
||||
local pw,ph = data._internal.pref_l:fit(9999,9999)
|
||||
if not data._internal.has_widget then
|
||||
return w,(total and total > 0 and total or visblerow*data.item_height) + ph + sh
|
||||
else
|
||||
local h = (visblerow-#data._internal.widgets)*data.item_height
|
||||
for k,v in ipairs(data._internal.widgets) do
|
||||
local fw,fh = v.widget:fit(9999,9999)
|
||||
h = h + fh
|
||||
end
|
||||
local sumh = data.widget_fit_height_sum
|
||||
local h = (visblerow-#data._internal.widgets)*data.item_height + sumh
|
||||
return w,h
|
||||
end
|
||||
end
|
||||
|
@ -251,10 +239,9 @@ local function new(data)
|
|||
suf_l:add(data._internal.scroll_w["down"])
|
||||
end
|
||||
end
|
||||
real_l.fit = function(a1,a2,a3)
|
||||
real_l.fit = function(a1,a2,a3,force_values)
|
||||
if not data.visible then return 1,1 end
|
||||
local result,r2 = wibox.layout.fixed.fit(a1,99999,99999)
|
||||
local w,h = compute_geo(data)
|
||||
local w,h = compute_geo(data,a2,a3,force_values)
|
||||
data:emit_signal("layout_size",w,h)
|
||||
return w,h
|
||||
end
|
||||
|
|
|
@ -4,6 +4,7 @@ local color = require( "gears.color" )
|
|||
local cairo = require( "lgi" ).cairo
|
||||
local base = require( "radical.base" )
|
||||
local glib = require("lgi").GLib
|
||||
local margins = require("radical.margins")
|
||||
|
||||
local module = {
|
||||
margins = {
|
||||
|
@ -75,14 +76,17 @@ local function gen_arrow_x(data,direction)
|
|||
--TODO
|
||||
end
|
||||
elseif at == base.arrow_type.CENTERED then
|
||||
data._arrow_x = data.width/2 - 13
|
||||
if direction == "left" or direction == "right" then
|
||||
data._arrow_x = data.height/2 - 13
|
||||
else
|
||||
data._arrow_x = data.width/2 - 13
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function _set_direction(data,direction)
|
||||
local height,width = data.height,data.width
|
||||
local hash = height*1000+width
|
||||
print("DIR",direction,hash,data._arrow_x,data._internal.last_size)
|
||||
|
||||
-- Try not to waste time for nothing
|
||||
if data._internal._last_direction == direction..(hash) then return end
|
||||
|
@ -110,9 +114,12 @@ local function _set_direction(data,direction)
|
|||
top_clip_surface = rotate(top_clip_surface,geometry,angle,swap)
|
||||
end
|
||||
data.wibox.shape_bounding = top_bounding_surface._native
|
||||
-- data.wibox.shape_clip = top_clip_surface._native
|
||||
data.wibox:set_bg(cairo.Pattern.create_for_surface(top_clip_surface))
|
||||
data._internal._need_direction_reload = false
|
||||
data._internal._last_direction = direction..(hash)
|
||||
|
||||
|
||||
end
|
||||
|
||||
-- Try to avoid useless repaint, this function is heavy
|
||||
|
@ -122,6 +129,15 @@ local function set_direction(data,direction)
|
|||
glib.idle_add(glib.PRIORITY_HIGH_IDLE, function() _set_direction(data,data._internal._need_direction) end)
|
||||
data._internal._need_direction_reload = true
|
||||
end
|
||||
|
||||
-- Margins need to set manually, a reset will override user changes
|
||||
if data.arrow_type ~= base.arrow_type.NONE and (not (data.parent_geometry and data.parent_geometry.is_menu)) and data._internal.former_direction ~= direction then
|
||||
if data._internal.former_direction then
|
||||
data.margins[data._internal.former_direction] = data.border_width + module.margins[data._internal.former_direction:upper()]
|
||||
end
|
||||
data.margins[direction] = 13 + 2*data.border_width
|
||||
end
|
||||
data._internal.former_direction = direction
|
||||
end
|
||||
|
||||
local function get_arrow_x(data)
|
||||
|
@ -146,11 +162,7 @@ local function draw(data,args)
|
|||
set_direction(data,direction)
|
||||
-- data._internal.set_position(data) --TODO DEAD CODE?
|
||||
|
||||
local margins = data.margins
|
||||
local margin = data._internal.margin
|
||||
for k,v in pairs(margins) do
|
||||
margin["set_"..k](margin,v)
|
||||
end
|
||||
--TODO call this less often
|
||||
return w,w2
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue