Refactor menu layout to maximize code sharing
This commit is contained in:
parent
9aab9b0d3c
commit
4db83034b8
72
bar.lua
72
bar.lua
|
@ -8,9 +8,11 @@ local beautiful = require( "beautiful" )
|
||||||
local cairo = require( "lgi" ).cairo
|
local cairo = require( "lgi" ).cairo
|
||||||
local awful = require( "awful" )
|
local awful = require( "awful" )
|
||||||
local util = require( "awful.util" )
|
local util = require( "awful.util" )
|
||||||
|
local fkey = require( "radical.widgets.fkey" )
|
||||||
local button = require( "awful.button" )
|
local button = require( "awful.button" )
|
||||||
local checkbox = require( "radical.widgets.checkbox" )
|
local checkbox = require( "radical.widgets.checkbox" )
|
||||||
local item_style = require( "radical.item_style.arrow_alt" )
|
local item_style = require( "radical.item_style.arrow_alt" )
|
||||||
|
local vertical = require( "radical.layout.vertical" )
|
||||||
|
|
||||||
local capi,module = { mouse = mouse , screen = screen, keygrabber = keygrabber },{}
|
local capi,module = { mouse = mouse , screen = screen, keygrabber = keygrabber },{}
|
||||||
|
|
||||||
|
@ -75,7 +77,22 @@ local function setup_drawable(data)
|
||||||
data.draw = internal.margin.draw
|
data.draw = internal.margin.draw
|
||||||
end
|
end
|
||||||
|
|
||||||
local function create_item(item,data)
|
-- Use all the space, let "align_fit" compute the right size
|
||||||
|
local function textbox_fit(box,w,h)
|
||||||
|
return w,h
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Force the width or compute the minimum space
|
||||||
|
local function align_fit(box,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
|
||||||
|
local lw = box.first:fit(w,h)
|
||||||
|
local cw = wibox.widget.textbox.fit(box.second,w,h)
|
||||||
|
local lr = box.third:fit(w,h)
|
||||||
|
return lw+cw+lr,h
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create the actual widget
|
||||||
|
local function create_item(item,data,args)
|
||||||
-- Background
|
-- Background
|
||||||
local bg = wibox.widget.background()
|
local bg = wibox.widget.background()
|
||||||
|
|
||||||
|
@ -87,21 +104,54 @@ local function create_item(item,data)
|
||||||
m:set_top ( data.item_style.margins.TOP )
|
m:set_top ( data.item_style.margins.TOP )
|
||||||
m:set_bottom( data.item_style.margins.BOTTOM )
|
m:set_bottom( data.item_style.margins.BOTTOM )
|
||||||
|
|
||||||
-- Layout
|
-- Layout (left)
|
||||||
local layout = wibox.layout.fixed.horizontal()
|
local layout = wibox.layout.fixed.horizontal()
|
||||||
bg:set_widget(m)
|
bg:set_widget(m)
|
||||||
m:set_widget(layout)
|
|
||||||
|
|
||||||
-- Content
|
-- Layout (right)
|
||||||
if item.icon then
|
local right = wibox.layout.fixed.horizontal()
|
||||||
local icon = wibox.widget.imagebox()
|
|
||||||
icon:set_image(item.icon)
|
-- F keys
|
||||||
layout:add(icon)
|
vertical:setup_fkey(item,data)
|
||||||
|
if data.fkeys_prefix == true then
|
||||||
|
layout:add(fkey(data,item))
|
||||||
|
m:set_left ( 0 )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Icon
|
||||||
|
layout:add(vertical:setup_icon(item,data))
|
||||||
|
|
||||||
|
-- Prefix
|
||||||
|
if args.prefix_widget then
|
||||||
|
layout:add(args.prefix_widget)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Text
|
||||||
local tb = wibox.widget.textbox()
|
local tb = wibox.widget.textbox()
|
||||||
layout:add(tb)
|
tb.fit = textbox_fit
|
||||||
item.widget = bg
|
item.widget = bg
|
||||||
tb:set_text("bob")
|
tb:set_text(item.text)
|
||||||
|
|
||||||
|
-- Checkbox
|
||||||
|
local ck = vertical:setup_checked(item,data)
|
||||||
|
if ck then
|
||||||
|
right:add(ck)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Suffix
|
||||||
|
if args.suffix_widget then
|
||||||
|
right:add(args.suffix_widget)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Layout (align)
|
||||||
|
local align = wibox.layout.align.horizontal()
|
||||||
|
align:set_middle( tb )
|
||||||
|
align:set_left ( layout )
|
||||||
|
align:set_right ( right )
|
||||||
|
m:set_widget ( align )
|
||||||
|
align._item = item
|
||||||
|
align._data = data
|
||||||
|
align.fit = align_fit
|
||||||
|
|
||||||
-- Tooltip
|
-- Tooltip
|
||||||
item.widget:set_tooltip(item.tooltip)
|
item.widget:set_tooltip(item.tooltip)
|
||||||
|
@ -116,7 +166,7 @@ end
|
||||||
local function setup_item(data,item,args)
|
local function setup_item(data,item,args)
|
||||||
|
|
||||||
-- Add widgets
|
-- Add widgets
|
||||||
data._internal.layout:add(create_item(item,data))
|
data._internal.layout:add(create_item(item,data,args))
|
||||||
item.widget:connect_signal("mouse::enter", function() item.selected = true end)
|
item.widget:connect_signal("mouse::enter", function() item.selected = true end)
|
||||||
item.widget:connect_signal("mouse::leave", function() item.selected = false end)
|
item.widget:connect_signal("mouse::leave", function() item.selected = false end)
|
||||||
|
|
||||||
|
|
11
base.lua
11
base.lua
|
@ -124,15 +124,16 @@ local function add_item(data,args)
|
||||||
private_data = {
|
private_data = {
|
||||||
text = args.text or "" ,
|
text = args.text or "" ,
|
||||||
height = args.height or beautiful.menu_height or 30 ,
|
height = args.height or beautiful.menu_height or 30 ,
|
||||||
|
width = args.width or nil ,
|
||||||
icon = args.icon or nil ,
|
icon = args.icon or nil ,
|
||||||
prefix = args.prefix or "" ,
|
prefix = args.prefix or "" ,
|
||||||
suffix = args.suffix or "" ,
|
suffix = args.suffix or "" ,
|
||||||
bg = args.bg or nil ,
|
bg = args.bg or nil ,
|
||||||
fg = args.fg or data.fg or beautiful.menu_fg_normal or beautiful.fg_normal,
|
fg = args.fg or data.fg or beautiful.menu_fg_normal or beautiful.fg_normal ,
|
||||||
fg_focus = args.fg_focus or data.fg_focus or beautiful.menu_fg_focus or beautiful.fg_focus ,
|
fg_focus = args.fg_focus or data.fg_focus or beautiful.menu_fg_focus or beautiful.fg_focus ,
|
||||||
bg_focus = args.bg_focus or data.bg_focus or beautiful.menu_bg_focus or beautiful.bg_focus ,
|
bg_focus = args.bg_focus or data.bg_focus or beautiful.menu_bg_focus or beautiful.bg_focus ,
|
||||||
sub_menu_m = (args.sub_menu and type(args.sub_menu) == "table" and args.sub_menu.is_menu) and args.sub_menu or nil,
|
sub_menu_m = (args.sub_menu and type(args.sub_menu) == "table" and args.sub_menu.is_menu) and args.sub_menu or nil,
|
||||||
sub_menu_f = (args.sub_menu and type(args.sub_menu) == "function") and args.sub_menu or nil,
|
sub_menu_f = (args.sub_menu and type(args.sub_menu) == "function") and args.sub_menu or nil ,
|
||||||
selected = false,
|
selected = false,
|
||||||
checkable = args.checkable or (args.checked ~= nil) or false,
|
checkable = args.checkable or (args.checked ~= nil) or false,
|
||||||
checked = args.checked or false,
|
checked = args.checked or false,
|
||||||
|
@ -400,7 +401,7 @@ local function new(args)
|
||||||
end
|
end
|
||||||
|
|
||||||
function data:remove_key_hook(key)
|
function data:remove_key_hook(key)
|
||||||
for k,v in pairs(internal.filter_hooks) do
|
for k,v in pairs(internal.filter_hooks or {}) do
|
||||||
if k.key == key then
|
if k.key == key then
|
||||||
internal.filter_hooks[k] = nil
|
internal.filter_hooks[k] = nil
|
||||||
break
|
break
|
||||||
|
|
|
@ -94,6 +94,90 @@ local function cache_pixmap(item)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function module:setup_fkey(item,data)
|
||||||
|
item._internal.set_map.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.visible = false
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
item._internal.get_map.f_key = function() return item._internal.f_key end
|
||||||
|
end
|
||||||
|
|
||||||
|
function module:setup_checked(item,data)
|
||||||
|
if item.checkable then
|
||||||
|
item._internal.get_map.checked = function()
|
||||||
|
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._internal.set_map.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
|
||||||
|
|
||||||
|
function module:setup_icon(item,data)
|
||||||
|
local icon = wibox.widget.imagebox()
|
||||||
|
icon.fit = function(...)
|
||||||
|
local w,h = wibox.widget.imagebox.fit(...)
|
||||||
|
return w+3,h
|
||||||
|
end
|
||||||
|
if item.icon then
|
||||||
|
icon:set_image(item.icon)
|
||||||
|
end
|
||||||
|
|
||||||
|
item._internal.set_map.icon = function (value)
|
||||||
|
icon:set_image(value)
|
||||||
|
end
|
||||||
|
return icon
|
||||||
|
end
|
||||||
|
|
||||||
|
function module:setup_text(item,data)
|
||||||
|
local text_w = wibox.widget.textbox()
|
||||||
|
|
||||||
|
text_w.draw = function(self,w, cr, width, height)
|
||||||
|
if item.underlay then
|
||||||
|
paint_underlay(data,item,cr,width,height)
|
||||||
|
end
|
||||||
|
wibox.widget.textbox.draw(self,w, cr, width, height)
|
||||||
|
end
|
||||||
|
text_w.fit = function(self,width,height) return width,height end
|
||||||
|
|
||||||
|
item._internal.set_map.text = function (value)
|
||||||
|
if data.disable_markup then
|
||||||
|
text_w:set_text(value)
|
||||||
|
else
|
||||||
|
text_w:set_markup(value)
|
||||||
|
end
|
||||||
|
if data.auto_resize then
|
||||||
|
local fit_w,fit_h = wibox.widget.textbox.fit(text_w,9999,9999)
|
||||||
|
local is_largest = item == data._internal.largest_item_w
|
||||||
|
item._internal.has_changed = true
|
||||||
|
if not data._internal.largest_item_w_v or data._internal.largest_item_w_v < fit_w then
|
||||||
|
data._internal.largest_item_w = item
|
||||||
|
data._internal.largest_item_w_v = fit_w
|
||||||
|
end
|
||||||
|
--TODO find new largest is item is smaller
|
||||||
|
-- if data._internal.largest_item_h_v < fit_h then
|
||||||
|
-- data._internal.largest_item_h =item
|
||||||
|
-- data._internal.largest_item_h_v = fit_h
|
||||||
|
-- end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
item._internal.set_map.text(item._private_data.text)
|
||||||
|
return text_w
|
||||||
|
end
|
||||||
|
|
||||||
function module:setup_item(data,item,args)
|
function module:setup_item(data,item,args)
|
||||||
--Create the background
|
--Create the background
|
||||||
|
@ -130,16 +214,11 @@ function module:setup_item(data,item,args)
|
||||||
m:set_right ( data.item_style.margins.RIGHT )
|
m:set_right ( data.item_style.margins.RIGHT )
|
||||||
m:set_top ( data.item_style.margins.TOP )
|
m:set_top ( data.item_style.margins.TOP )
|
||||||
m:set_bottom( data.item_style.margins.BOTTOM )
|
m:set_bottom( data.item_style.margins.BOTTOM )
|
||||||
local text_w = wibox.widget.textbox()
|
|
||||||
|
|
||||||
text_w.draw = function(self,w, cr, width, height)
|
-- Text
|
||||||
if item.underlay then
|
local text_w = module:setup_text(item,data)
|
||||||
paint_underlay(data,item,cr,width,height)
|
|
||||||
end
|
|
||||||
wibox.widget.textbox.draw(self,w, cr, width, height)
|
|
||||||
end
|
|
||||||
text_w.fit = function(self,width,height) return width,height end
|
|
||||||
|
|
||||||
|
-- Background
|
||||||
item._private_data._fit = wibox.widget.background.fit
|
item._private_data._fit = wibox.widget.background.fit
|
||||||
m.fit = function(...)
|
m.fit = function(...)
|
||||||
if not data.visible or (item.visible == false or item._filter_out == true or item._hidden == true) then
|
if not data.visible or (item.visible == false or item._filter_out == true or item._hidden == true) then
|
||||||
|
@ -148,24 +227,21 @@ function module:setup_item(data,item,args)
|
||||||
return data._internal.layout.item_fit(data,item,...)
|
return data._internal.layout.item_fit(data,item,...)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- F keys
|
||||||
if data.fkeys_prefix == true then
|
if data.fkeys_prefix == true then
|
||||||
l:add(fkey(data,item))
|
l:add(fkey(data,item))
|
||||||
m:set_left ( 0 )
|
m:set_left ( 0 )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Prefix
|
||||||
if args.prefix_widget then
|
if args.prefix_widget then
|
||||||
l:add(args.prefix_widget)
|
l:add(args.prefix_widget)
|
||||||
end
|
end
|
||||||
|
|
||||||
local icon = wibox.widget.imagebox()
|
-- Icon
|
||||||
icon.fit = function(...)
|
local icon = module:setup_icon(item,data)
|
||||||
local w,h = wibox.widget.imagebox.fit(...)
|
|
||||||
return w+3,h
|
|
||||||
end
|
|
||||||
if args.icon then
|
|
||||||
icon:set_image(args.icon)
|
|
||||||
end
|
|
||||||
l:add(icon)
|
l:add(icon)
|
||||||
|
|
||||||
if item._private_data.sub_menu_f or item._private_data.sub_menu_m then
|
if item._private_data.sub_menu_f or item._private_data.sub_menu_m then
|
||||||
local subArrow = wibox.widget.imagebox() --TODO, make global
|
local subArrow = wibox.widget.imagebox() --TODO, make global
|
||||||
subArrow.fit = function(box, w, h) return subArrow._image:get_width(),item.height end
|
subArrow.fit = function(box, w, h) return subArrow._image:get_width(),item.height end
|
||||||
|
@ -176,26 +252,19 @@ function module:setup_item(data,item,args)
|
||||||
return wibox.widget.background.fit(box,w,h)
|
return wibox.widget.background.fit(box,w,h)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if item.checkable then
|
|
||||||
item._internal.get_map.checked = function()
|
-- Checkbox
|
||||||
if type(item._private_data.checked) == "function" then
|
local ck = module:setup_checked(item,data)
|
||||||
return item._private_data.checked()
|
if ck then
|
||||||
else
|
|
||||||
return item._private_data.checked
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local ck = wibox.widget.imagebox()
|
|
||||||
ck:set_image(item.checked and checkbox.checked() or checkbox.unchecked())
|
|
||||||
lr:add(ck)
|
lr:add(ck)
|
||||||
item._internal.set_map.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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Suffix
|
||||||
if args.suffix_widget then
|
if args.suffix_widget then
|
||||||
lr:add(args.suffix_widget)
|
lr:add(args.suffix_widget)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Layout
|
||||||
la:set_left(l)
|
la:set_left(l)
|
||||||
la:set_middle(text_w)
|
la:set_middle(text_w)
|
||||||
la:set_right(lr)
|
la:set_right(lr)
|
||||||
|
@ -203,45 +272,14 @@ function module:setup_item(data,item,args)
|
||||||
local fit_w,fit_h = data._internal.layout:fit()
|
local fit_w,fit_h = data._internal.layout:fit()
|
||||||
data.width = fit_w
|
data.width = fit_w
|
||||||
data.height = fit_h
|
data.height = fit_h
|
||||||
data.style(data)
|
if data.style then
|
||||||
item._internal.set_map.text = function (value)
|
data.style(data)
|
||||||
if data.disable_markup then
|
|
||||||
text_w:set_text(value)
|
|
||||||
else
|
|
||||||
text_w:set_markup(value)
|
|
||||||
end
|
|
||||||
if data.auto_resize then
|
|
||||||
local fit_w,fit_h = wibox.widget.textbox.fit(text_w,9999,9999)
|
|
||||||
local is_largest = item == data._internal.largest_item_w
|
|
||||||
item._internal.has_changed = true
|
|
||||||
if not data._internal.largest_item_w_v or data._internal.largest_item_w_v < fit_w then
|
|
||||||
data._internal.largest_item_w = item
|
|
||||||
data._internal.largest_item_w_v = fit_w
|
|
||||||
end
|
|
||||||
--TODO find new largest is item is smaller
|
|
||||||
-- if data._internal.largest_item_h_v < fit_h then
|
|
||||||
-- data._internal.largest_item_h =item
|
|
||||||
-- data._internal.largest_item_h_v = fit_h
|
|
||||||
-- end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
item._internal.set_map.f_key = function(value)
|
-- F keys
|
||||||
item._internal.has_changed = true
|
module:setup_fkey(item,data)
|
||||||
item._internal.f_key = value
|
|
||||||
data:remove_key_hook("F"..value)
|
|
||||||
data:add_key_hook({}, "F"..value , "press", function()
|
|
||||||
item.button1()
|
|
||||||
data.visible = false
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
item._internal.get_map.f_key = function() return item._internal.f_key end
|
|
||||||
|
|
||||||
item._internal.set_map.icon = function (value)
|
|
||||||
icon:set_image(value)
|
|
||||||
end
|
|
||||||
item._internal.set_map.text(item._private_data.text)
|
|
||||||
|
|
||||||
|
-- Enable scrollbar if necessary
|
||||||
if data._internal.scroll_w and data.rowcount > data.max_items then
|
if data._internal.scroll_w and data.rowcount > data.max_items then
|
||||||
data._internal.scroll_w.visible = true
|
data._internal.scroll_w.visible = true
|
||||||
data._internal.scroll_w["up"]:emit_signal("widget::updated")
|
data._internal.scroll_w["up"]:emit_signal("widget::updated")
|
||||||
|
|
|
@ -11,18 +11,18 @@ local module = {}
|
||||||
|
|
||||||
local keys = {}
|
local keys = {}
|
||||||
|
|
||||||
local pango_l,pango_crx,max_width,m_h = nil,nil,0,0
|
local pango_l,pango_crx,max_width = nil,nil,0
|
||||||
local function create_pango()
|
local function create_pango(height)
|
||||||
local padding = beautiful.menu_height/5
|
local padding = beautiful.menu_height/5
|
||||||
pango_crx = pangocairo.font_map_get_default():create_context()
|
pango_crx = pangocairo.font_map_get_default():create_context()
|
||||||
pango_l = pango.Layout.new(pango_crx)
|
pango_l = pango.Layout.new(pango_crx)
|
||||||
local desc = pango.FontDescription()
|
local desc = pango.FontDescription()
|
||||||
desc:set_family("Verdana")
|
desc:set_family("Verdana")
|
||||||
desc:set_weight(pango.Weight.BOLD)
|
desc:set_weight(pango.Weight.BOLD)
|
||||||
desc:set_size((m_h-padding*2) * pango.SCALE)
|
desc:set_size((height-padding*2) * pango.SCALE)
|
||||||
pango_l:set_font_description(desc)
|
pango_l:set_font_description(desc)
|
||||||
pango_l.text = "F88"
|
pango_l.text = "F88"
|
||||||
max_width = pango_l:get_pixel_extents().width + m_h + 4
|
max_width = pango_l:get_pixel_extents().width + height + 4
|
||||||
end
|
end
|
||||||
|
|
||||||
local function new(data,item)
|
local function new(data,item)
|
||||||
|
@ -30,19 +30,17 @@ local function new(data,item)
|
||||||
local padding = beautiful.menu_height/5
|
local padding = beautiful.menu_height/5
|
||||||
pref.draw = function(self,w, cr, width, height)
|
pref.draw = function(self,w, cr, width, height)
|
||||||
local key = item._internal.f_key
|
local key = item._internal.f_key
|
||||||
if m_h == 0 then
|
if not keys[height] then
|
||||||
m_h = height
|
|
||||||
pref:emit_signal("widget::updated")
|
pref:emit_signal("widget::updated")
|
||||||
create_pango()
|
create_pango(height)
|
||||||
keys = {}
|
keys[height] = {}
|
||||||
end
|
end
|
||||||
if key and key > 12 and keys[0] then
|
if key and key > 12 and keys[height][0] then
|
||||||
cr:set_source_surface(keys[0])
|
cr:set_source_surface(keys[height][0])
|
||||||
cr:paint()
|
cr:paint()
|
||||||
elseif not keys[key] then
|
elseif not keys[height] or not keys[height][key] then
|
||||||
if not pango_l then
|
if not pango_l then
|
||||||
m_h = height
|
create_pango(height)
|
||||||
create_pango()
|
|
||||||
end
|
end
|
||||||
local img = cairo.ImageSurface(cairo.Format.ARGB32, max_width,beautiful.menu_height)
|
local img = cairo.ImageSurface(cairo.Format.ARGB32, max_width,beautiful.menu_height)
|
||||||
local cr2 = cairo.Context(img)
|
local cr2 = cairo.Context(img)
|
||||||
|
@ -59,16 +57,16 @@ local function new(data,item)
|
||||||
pango_l.text = text
|
pango_l.text = text
|
||||||
cr2:show_layout(pango_l)
|
cr2:show_layout(pango_l)
|
||||||
if key > 12 then
|
if key > 12 then
|
||||||
keys[0] = img
|
keys[height][0] = img
|
||||||
else
|
else
|
||||||
keys[key] = img
|
keys[height][key] = img
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if key and key > 12 and keys[0] then
|
if key and key > 12 and keys[height][0] then
|
||||||
cr:set_source_surface(keys[0])
|
cr:set_source_surface(keys[height][0])
|
||||||
cr:paint()
|
cr:paint()
|
||||||
else
|
else
|
||||||
cr:set_source_surface(keys[key])
|
cr:set_source_surface(keys[height][key])
|
||||||
cr:paint()
|
cr:paint()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue