2014-02-23 05:59:03 +01:00
local type = type
2014-04-05 05:44:23 +02:00
local capi = { timer = timer }
2014-02-23 05:59:03 +01:00
local beautiful = require ( " beautiful " )
local theme = require ( " radical.theme " )
local object = require ( " radical.object " )
local module = {
-- style = require("radical.item.style"),
-- layout = require("radical.item.layout"),
arrow_type = {
NONE = 0 ,
PRETTY = 1 ,
CENTERED = 2 ,
} ,
event = {
NEVER = 0 ,
BUTTON1 = 1 ,
BUTTON2 = 2 ,
BUTTON3 = 3 ,
SELECTED = 100 ,
HOVER = 1000 ,
LEAVE = 1001 ,
} ,
item_flags = {
NONE = 999999 ,
DISABLED = 1 , -- Cannot be interacted with
URGENT = 2 , -- Need attention
SELECTED = 3 , -- Single item selected [[FOCUS]]
2014-03-13 06:14:52 +01:00
HOVERED = - 1 , -- Mouse hover
2014-03-12 01:49:49 +01:00
PRESSED = 4 , -- Mouse pressed
2014-02-23 05:59:03 +01:00
USED = 6 , -- Common flag
CHECKED = 7 , -- When checkbox isn't enough
ALTERNATE = 8 ,
HIGHLIGHT = 9 ,
HEADER = 10 ,
-- Implementation defined flags
USR1 = 101 ,
USR2 = 102 ,
USR3 = 103 ,
USR4 = 104 ,
USR5 = 105 ,
USR6 = 106 ,
USR7 = 107 ,
USR8 = 108 ,
USR9 = 109 ,
USR10 = 110 ,
} ,
}
local function load_async ( tab , key )
if key == " style " then
module.style = require ( " radical.item.style " )
return module.style
elseif key == " layout " then
module.layout = require ( " radical.item.layout " )
return module.layout
2016-02-11 07:36:50 +01:00
--TODO handle colors this way
-- elseif key:sub(1,7 ) == "get_fg_" then
--
-- elseif key:sub(1,7 ) == "get_bg_" then
--
-- elseif key:sub(1,17) == "get_border_color_" then
--
2014-02-23 05:59:03 +01:00
end
return rawget ( module , key )
end
2014-04-16 06:26:31 +02:00
local function hide_sub_menu ( item , data )
if item._tmp_menu then
item._tmp_menu . visible = false
item._tmp_menu = nil
data._tmp_menu = nil
item : emit_signal ( " state::changed " )
end
end
2016-02-28 08:04:51 +01:00
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
2014-04-09 05:38:31 +02:00
-- local registered_items = {}
-- local is_watching = false
-- local mouse_tracker = object{}
2014-04-16 06:26:31 +02:00
-- local function watch_mouse(a,b,c)
-- print("move",a,b,c)
-- end
2014-04-09 05:38:31 +02:00
-- local function register_mouse_track()
-- if not is_watching then
--
-- end
-- end
2014-02-23 05:59:03 +01:00
local function new_item ( data , args )
local args = args or { }
2014-03-05 06:12:48 +01:00
local item , private_data = object ( {
2014-02-23 05:59:03 +01:00
private_data = {
text = args.text or " " ,
2014-07-28 01:20:04 +02:00
-- height = args.height or data.item_height or beautiful.menu_height or 30 ,
2014-02-23 05:59:03 +01:00
width = args.width or nil ,
icon = args.icon or nil ,
prefix = args.prefix or " " ,
suffix = args.suffix or " " ,
bg = args.bg or nil ,
2014-03-02 22:28:30 +01:00
fg = args.fg or data.fg , --TODO don't do this
2016-02-11 07:36:50 +01:00
border_color = args.border_color or data.item_border_color ,
border_width = args.border_width or data.item_border_width ,
2014-02-23 05:59:03 +01:00
bg_prefix = args.bg_prefix or data.bg_prefix ,
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 ,
checkable = args.checkable or ( args.checked ~= nil ) or false ,
checked = args.checked or false ,
tooltip = args.tooltip or nil ,
2014-03-02 22:28:30 +01:00
style = args.style or data.item_style ,
2014-04-05 05:44:23 +02:00
layout = args.layout or args.item_layout or nil ,
2016-02-28 08:04:51 +01:00
infoshapes = args.infoshapes or nil ,
2016-01-12 09:33:38 +01:00
overlay_draw = args.overlay_draw or data.overlay_draw ,
2015-01-01 08:08:40 +01:00
item_border_color = args.item_border_color or data.item_border_color or nil ,
2014-02-23 05:59:03 +01:00
} ,
force_private = {
visible = true ,
selected = true ,
2014-03-02 22:28:30 +01:00
index = true ,
2014-02-23 05:59:03 +01:00
} ,
autogen_getmap = true ,
autogen_setmap = true ,
autogen_signals = true ,
} )
item._private_data = private_data
2014-08-08 08:02:37 +02:00
item._internal = args._internal or { }
2014-03-02 22:28:30 +01:00
theme.setup_item_colors ( data , item , args )
2016-02-28 11:00:44 +01:00
-- item.get_y = function()
-- return (args.y and args.y >= 0) and args.y or data.height - (data.margins.top or data.border_width) - data.item_height --Hack around missing :fit call for last item
-- end
2014-07-28 01:20:04 +02:00
item.get_height = function ( )
return args.height or data.item_height or beautiful.menu_height or 30
end
2014-03-02 22:28:30 +01:00
item.get_bg = function ( )
return data.bg
end
item.get_fg = function ( )
return data.fg
end
2014-12-31 06:30:52 +01:00
2014-03-02 22:28:30 +01:00
item.state = theme.init_state ( item )
2014-02-23 05:59:03 +01:00
for i = 1 , 10 do
item [ " button " .. i ] = args [ " button " .. i ]
end
-- Use _internal to avoid the radical.object trigger
data._internal . visible_item_count = ( data._internal . visible_item_count or 0 ) + 1
item._internal . f_key = data._internal . visible_item_count
-- Need to be done before painting
data._internal . items [ # data._internal . items + 1 ] = { }
2014-03-22 22:35:43 +01:00
data._internal . items [ # data._internal . items ] = item
2014-02-23 05:59:03 +01:00
2014-03-23 05:14:25 +01:00
-- Getters
item.get_selected = function ( _ )
2014-04-16 06:26:31 +02:00
return item.state [ module.item_flags . SELECTED ] == true
2014-03-23 05:14:25 +01:00
end
2014-02-23 05:59:03 +01:00
-- Setters
2014-03-22 05:11:03 +01:00
item.set_selected = function ( _ , value , force )
2014-02-23 05:59:03 +01:00
private_data.selected = value
2014-03-22 04:20:50 +01:00
-- Hide the sub-menu
2014-02-23 05:59:03 +01:00
local current_item = data._current_item
2014-03-22 05:11:03 +01:00
if current_item and current_item ~= item or force then
2014-02-23 05:59:03 +01:00
current_item.state [ module.item_flags . SELECTED ] = nil
2014-08-08 08:02:37 +02:00
current_item : emit_signal ( " selected::changed " , false )
2014-04-16 06:26:31 +02:00
hide_sub_menu ( current_item , data )
2014-02-23 05:59:03 +01:00
end
2014-03-22 04:20:50 +01:00
-- Unselect item
if value == false then
item.state [ module.item_flags . SELECTED ] = nil
return
end
2014-02-23 05:59:03 +01:00
item.state [ module.item_flags . SELECTED ] = true
data._current_item = item
end
2014-03-17 04:46:23 +01:00
2016-02-28 08:04:51 +01:00
-- Overlay and underlay
item.set_infoshapes = set_infoshapes
2016-02-21 08:34:05 +01:00
item.set_icon = function ( _ , value )
local icon_w = item._internal . icon_w
if not icon_w then return end
icon_w : set_image ( value )
end
2014-03-17 04:46:23 +01:00
-- Listen to signals
item : connect_signal ( " state::changed " , function ( )
item : style ( )
2016-01-09 10:25:46 +01:00
-- Some item.style need full widget repaint
if item.style . need_full_repaint then
--TODO HACK HACK HACK for the repaint, this is really, really stupid
data._internal . layout : emit_signal ( " widget::redraw_needed " )
--TODO END HACK
end
2014-03-17 04:46:23 +01:00
end )
2014-04-05 05:44:23 +02:00
-- Add support for long hover and press
local main_timer , press_timer = nil
2014-10-05 23:59:06 +02:00
item : connect_signal ( " mouse::enter " , function ( _ , m , --[[mod,]] geo )
2014-04-05 05:44:23 +02:00
if not main_timer then
main_timer = timer { }
main_timer.timeout = 1.5
main_timer : connect_signal ( " timeout " , function ( )
2014-04-09 05:38:31 +02:00
item._internal . _is_long_hover = true
2014-10-05 23:59:06 +02:00
item : emit_signal ( " long::hover " , item , mod , geo )
data : emit_signal ( " long::hover " , item , mod , geo )
2014-04-05 05:44:23 +02:00
main_timer : stop ( )
end )
end
if not main_timer.started then
2014-04-09 05:38:31 +02:00
-- item:connect_signal("mouse::move",test)
2014-04-05 05:44:23 +02:00
main_timer : start ( )
end
end )
item : connect_signal ( " mouse::leave " , function ( )
if main_timer and main_timer.started then
main_timer : stop ( )
2014-04-09 05:38:31 +02:00
-- item:disconnect_signal("mouse::move",test)
elseif item._internal . _is_long_hover then
item._internal . _is_long_hover = nil
item : emit_signal ( " long::exit " , data , item )
2014-04-05 05:44:23 +02:00
end
end )
item : connect_signal ( " button::press " , function ( )
if not press_timer then
press_timer = timer { }
press_timer.timeout = 1.5
press_timer : connect_signal ( " timeout " , function ( )
2014-04-09 05:38:31 +02:00
item : emit_signal ( " long::press " , data , item )
-- item:disconnect_signal("mouse::move",test)
2014-04-05 05:44:23 +02:00
press_timer : stop ( )
end )
end
if not press_timer.started then
2014-04-09 05:38:31 +02:00
-- item:connect_signal("mouse::move",test)
2014-04-05 05:44:23 +02:00
press_timer : start ( )
end
end )
item : connect_signal ( " button::release " , function ( )
if press_timer and press_timer.started then
press_timer : stop ( )
end
end )
2014-02-23 05:59:03 +01:00
return item
end
return setmetatable ( module , { __call = function ( _ , ... ) return new_item ( ... ) end , __index = load_async } )
2016-02-28 08:04:51 +01:00
-- kate: space-indent on; indent-width 2; replace-tabs on;