2013-05-11 21:02:42 +02:00
local setmetatable = setmetatable
local pairs , ipairs = pairs , ipairs
local type , string = type , string
local print , unpack = print , unpack
2014-02-06 03:43:06 +01:00
local table = table
2014-01-16 06:25:50 +01:00
local beautiful = require ( " beautiful " )
local util = require ( " awful.util " )
local aw_key = require ( " awful.key " )
local object = require ( " radical.object " )
local vertical = require ( " radical.layout.vertical " )
2014-02-23 05:59:03 +01:00
local theme = require ( " radical.theme " )
local item_mod = require ( " radical.item " )
2013-05-11 21:02:42 +02:00
2014-01-15 05:19:49 +01:00
local capi = { mouse = mouse , screen = screen , keygrabber = keygrabber , root = root , }
2013-05-11 21:02:42 +02:00
local module = {
arrow_type = {
NONE = 0 ,
PRETTY = 1 ,
CENTERED = 2 ,
2014-01-04 06:49:20 +01:00
} ,
2014-02-06 04:48:26 +01:00
event = {
2014-01-04 07:27:52 +01:00
NEVER = 0 ,
BUTTON1 = 1 ,
BUTTON2 = 2 ,
BUTTON3 = 3 ,
SELECTED = 100 ,
2014-02-06 04:48:26 +01:00
HOVER = 1000 ,
LEAVE = 1001 ,
2014-01-04 07:27:52 +01:00
} ,
2014-01-08 06:59:57 +01:00
item_flags = {
2014-02-22 04:22:13 +01:00
NONE = 999999 ,
DISABLED = 1 , -- Cannot be interacted with
URGENT = 2 , -- Need attention
SELECTED = 3 , -- Single item selected [[FOCUS]]
PRESSED = 4 , -- Mouse pressed
2014-03-13 06:14:52 +01:00
HOVERED = - 1 , -- Mouse hover
2014-03-02 22:28:30 +01:00
CHANGED = 6 , -- The item changed, need attention
USED = 7 , -- Common flag
CHECKED = 8 , -- When checkbox isn't enough
ALTERNATE = 9 ,
HIGHLIGHT = 10 ,
HEADER = 11 ,
2014-02-09 06:54:59 +01:00
-- Implementation defined flags
USR1 = 101 ,
USR2 = 102 ,
USR3 = 103 ,
USR4 = 104 ,
USR5 = 105 ,
USR6 = 106 ,
USR7 = 107 ,
USR8 = 108 ,
USR9 = 109 ,
USR10 = 110 ,
2014-02-22 04:22:13 +01:00
} ,
2014-02-23 05:59:03 +01:00
colors_by_id = theme.colors_by_id
2014-01-04 07:27:52 +01:00
}
2013-05-11 21:02:42 +02:00
2014-02-23 05:59:03 +01:00
theme.register_color ( module.item_flags . DISABLED , " disabled " , " disabled " , true )
theme.register_color ( module.item_flags . URGENT , " urgent " , " urgent " , true )
theme.register_color ( module.item_flags . SELECTED , " focus " , " focus " , true )
theme.register_color ( module.item_flags . PRESSED , " pressed " , " pressed " , true )
theme.register_color ( module.item_flags . HOVERED , " hover " , " hover " , true )
2014-03-02 22:28:30 +01:00
theme.register_color ( module.item_flags . CHANGED , " changed " , " changed " , true )
2014-02-23 05:59:03 +01:00
theme.register_color ( module.item_flags . USED , " used " , " used " , true )
theme.register_color ( module.item_flags . CHECKED , " checked " , " checked " , true )
theme.register_color ( module.item_flags . ALTERNATE , " alternate " , " alternate " , true )
theme.register_color ( module.item_flags . HIGHLIGHT , " highlight " , " highlight " , true )
2014-02-22 04:22:13 +01:00
-- register_color(item_flags.HEADER , ""
-- register_color(item_flags.USR1 , ""
-- register_color(item_flags.USR2 , ""
-- register_color(item_flags.USR3 , ""
-- register_color(item_flags.USR4 , ""
-- register_color(item_flags.USR5 , ""
-- register_color(item_flags.USR6 , ""
-- register_color(item_flags.USR7 , ""
-- register_color(item_flags.USR8 , ""
-- register_color(item_flags.USR9 , ""
-- register_color(item_flags.USR10 , ""
2013-07-02 00:18:25 +02:00
local function filter ( data )
2013-07-18 06:03:19 +02:00
if not data.filter == false then
local fs , visible_counter = data.filter_string : lower ( ) , 0
data._internal . visible_item_count = 0
for k , v in pairs ( data.items ) do
2014-03-22 22:35:43 +01:00
local tmp = v._filter_out
v._filter_out = ( v.text : lower ( ) : find ( fs ) == nil ) -- or (fs ~= "")
if tmp ~= v._filter_out then
v.widget : emit_signal ( " widget::updated " )
2013-07-18 06:03:19 +02:00
end
2014-03-22 22:35:43 +01:00
if ( not v._filter_out ) and ( not v._hidden ) then
visible_counter = visible_counter + v.height
2013-07-18 06:03:19 +02:00
data._internal . visible_item_count = data._internal . visible_item_count + 1
2014-03-22 22:35:43 +01:00
v.f_key = data._internal . visible_item_count
2013-07-18 06:03:19 +02:00
end
2013-05-11 21:02:42 +02:00
end
2013-07-18 06:03:19 +02:00
data._total_item_height = visible_counter
local w , h = data._internal . layout : fit ( )
2014-06-01 05:45:46 +02:00
-- Make sure to select an item
if data._current_item and data._current_item . _filter_out then
local n = data.next_item
if n then
n.selected = true
end
end
2013-07-18 06:03:19 +02:00
data.height = h
2013-05-11 21:02:42 +02:00
end
end
2014-10-05 23:59:06 +02:00
-- Get the number of visible rows
local function get_visible_row_count ( data )
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
return visblerow
end
2013-05-11 21:02:42 +02:00
------------------------------------KEYBOARD HANDLING-----------------------------------
local function activateKeyboard ( data )
if not data then return end
if not data or grabKeyboard == true then return end
2013-08-07 21:32:44 +02:00
if ( not ( data._internal . private_data.enable_keyboard == false ) ) and data.visible == true then
2013-05-11 21:02:42 +02:00
capi.keygrabber . run ( function ( mod , key , event )
2013-12-20 06:25:54 +01:00
for k , v in pairs ( data._internal . filter_hooks or { } ) do --TODO modkeys
2014-04-04 05:25:35 +02:00
if ( k.key == " Mod4 " or k.key == " Mod1 " ) and ( key == " End " or key == " Super_L " or key == " Alt_L " ) then
2013-12-20 06:25:54 +01:00
local found = false
for k3 , v3 in ipairs ( mod ) do
2014-04-04 05:25:35 +02:00
for k4 , v4 in ipairs ( { " Mod4 " , " Mod1 " } ) do
if v3 == v4 and event == k.event then
local retval , self = v ( data , mod )
if self and type ( self ) == " table " then
data = self
end
2013-12-20 06:25:54 +01:00
end
2013-05-11 21:02:42 +02:00
end
2013-12-20 06:25:54 +01:00
end
2013-05-11 21:02:42 +02:00
end
2013-12-20 06:25:54 +01:00
if k.key == key and k.event == event then
local retval , self = v ( data , mod )
if self and type ( self ) == " table " then
data = self
end
2014-03-23 05:14:25 +01:00
if retval == false then
data.visible = false
capi.keygrabber . stop ( )
end
2013-12-20 06:25:54 +01:00
return retval
2013-05-11 21:02:42 +02:00
end
2013-12-20 06:25:54 +01:00
end
if event == " release " then
return true
end
2013-05-11 21:02:42 +02:00
2013-12-20 06:25:54 +01:00
if ( key == ' Return ' ) and data._current_item and data._current_item . button1 then
2014-02-06 04:48:26 +01:00
if data.sub_menu_on == module.event . BUTTON1 then
2014-02-23 05:59:03 +01:00
item_mod.execute_sub_menu ( data , data._current_item )
2014-01-04 07:27:52 +01:00
else
2014-04-04 05:25:35 +02:00
data._current_item . button1 ( data , data._current_item )
2014-01-04 07:27:52 +01:00
data.visible = false
end
2013-12-20 06:25:54 +01:00
elseif key == ' Escape ' or ( key == ' Tab ' and data.filter_string == " " ) then
data.visible = false
capi.keygrabber . stop ( )
elseif ( key == ' BackSpace ' ) and data.filter_string ~= " " and data.filter == true then
data.filter_string = data.filter_string : sub ( 1 , - 2 )
filter ( data )
elseif data.filter == true and key : len ( ) == 1 then
data.filter_string = data.filter_string .. key : lower ( )
filter ( data )
else
data.visible = false
capi.keygrabber . stop ( )
end
return true
2013-05-11 21:02:42 +02:00
end )
end
end
---------------------------------ITEM HANDLING----------------------------------
2013-07-04 07:20:46 +02:00
local function add_item ( data , args )
2014-02-23 05:59:03 +01:00
local item = item_mod ( data , args )
2014-01-12 07:27:46 +01:00
data._internal . setup_item ( data , item , args )
2014-01-21 06:24:51 +01:00
if args.selected == true then
item.selected = true
end
2014-03-02 22:28:30 +01:00
item.index = data.rowcount
2014-03-05 06:12:48 +01:00
data : emit_signal ( " item::added " , item )
2013-05-11 21:02:42 +02:00
return item
end
2014-12-29 04:23:59 +01:00
local function add_items ( data , items )
local ret = { }
for k , item in ipairs ( items ) do
ret [ k ] = data : add_item ( item )
end
return ret
end
2013-05-11 21:02:42 +02:00
2013-07-04 07:20:46 +02:00
local function add_widget ( data , widget , args )
args = args or { }
data._internal . has_widget = true
widget._fit = widget.fit
2013-07-21 10:15:56 +02:00
widget.fit = function ( self , width , height )
local w , h = widget._fit ( self , width or 1 , height or 1 )
2013-07-04 07:20:46 +02:00
return args.width or w , args.height or h
end
2014-03-05 06:12:48 +01:00
local item , private_data = object ( {
2013-07-04 07:20:46 +02:00
private_data = {
widget = widget ,
selected = false ,
} ,
force_private = {
visible = true ,
selected = true ,
} ,
autogen_getmap = true ,
autogen_setmap = true ,
autogen_signals = true ,
} )
item._private_data = private_data
2014-03-05 06:12:48 +01:00
item._internal = { }
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 end --Hack around missing :fit call for last item
2013-07-23 08:12:19 +02:00
2013-07-04 07:20:46 +02:00
data._internal . widgets [ # data._internal . widgets + 1 ] = item
2014-03-26 05:21:42 +01:00
data._internal . items [ # data._internal . items + 1 ] = item
2014-03-12 05:31:50 +01:00
data : emit_signal ( " widget::added " , item , widget )
2013-07-04 07:20:46 +02:00
if data.visible then
2014-03-12 05:31:50 +01:00
local fit_w , fit_h = data._internal . layout : fit ( 9999 , 9999 )
2013-08-09 08:07:27 +02:00
data.width = data._internal . width or fit_w
2013-07-04 07:20:46 +02:00
data.height = fit_h
end
end
2014-12-29 04:23:59 +01:00
local function add_widgets ( data , widgets )
for k , item in ipairs ( widgets ) do
data : add_widget ( item )
end
end
2014-03-12 01:49:49 +01:00
local function add_prefix_widget ( data , widget , args )
data : emit_signal ( " prefix_widget::added " , widget , args )
end
local function add_suffix_widget ( data , widget , args )
data : emit_signal ( " suffix_widget::added " , widget , args )
end
2014-10-05 23:59:06 +02:00
-- Sum all widgets height and width
local function get_widget_fit_sum ( data )
local h , w = 0 , 0
for k , v in ipairs ( data._internal . widgets ) do
local fw , fh = v.widget : fit ( 9999 , 9999 )
w , h = w + fw , h + fh
end
return w , h
end
local function get_widget_fit_width_sum ( data )
return get_widget_fit_sum ( data )
end
local function get_widget_fit_height_sum ( data )
local w , h = get_widget_fit_sum ( data )
return h
end
2013-07-04 07:20:46 +02:00
local function add_embeded_menu ( data , menu )
2013-07-21 10:15:56 +02:00
add_widget ( data , menu._internal . layout )
2013-12-31 22:13:11 +01:00
menu._embeded_parent = data
2013-07-04 07:20:46 +02:00
end
2014-12-30 23:27:57 +01:00
local function add_colors_namespace ( data , namespace )
theme.add_colors_from_namespace ( data , namespace )
end
2014-01-15 05:19:49 +01:00
local function add_key_binding ( data , mod , key , func )
capi.root . keys ( util.table . join ( capi.root . keys ( ) , aw_key ( mod or { } , key , func and func ( ) or function ( )
data.visible = not data.visible
end ) ) )
end
2013-05-11 21:02:42 +02:00
---------------------------------MENU HANDLING----------------------------------
local function new ( args )
2014-10-05 23:59:06 +02:00
local args = args or { }
local internal = args.internal or { }
2013-05-11 21:02:42 +02:00
if not internal.items then internal.items = { } end
2013-07-04 07:20:46 +02:00
if not internal.widgets then internal.widgets = { } end
2015-01-11 05:59:51 +01:00
print ( beautiful.menu_border_color )
2013-05-11 21:02:42 +02:00
-- All the magic in the universe
2014-03-05 06:12:48 +01:00
local data , private_data = object ( {
2013-05-11 21:02:42 +02:00
private_data = {
-- Default settings
bg = args.bg or beautiful.menu_bg_normal or beautiful.bg_normal or " #000000 " ,
fg = args.fg or beautiful.menu_fg_normal or beautiful.fg_normal or " #ffffff " ,
2013-08-03 07:03:43 +02:00
bg_header = args.bg_header or beautiful.menu_bg_header or beautiful.fg_normal ,
2014-02-03 05:01:31 +01:00
bg_prefix = args.bg_prefix or nil ,
2013-05-11 21:02:42 +02:00
border_color = args.border_color or beautiful.menu_border_color or beautiful.border_color or " #333333 " ,
border_width = args.border_width or beautiful.menu_border_width or beautiful.border_width or 3 ,
2014-01-05 00:51:07 +01:00
separator_color = args.separator_color or beautiful.menu_separator_color or args.border_color or beautiful.menu_border_color or beautiful.border_color or " #333333 " ,
2013-05-11 21:02:42 +02:00
item_height = args.item_height or beautiful.menu_height or 30 ,
2013-05-27 02:49:51 +02:00
item_width = args.item_width or nil ,
2014-07-28 01:20:04 +02:00
width = args.width or args.menu_width or beautiful.menu_width or 130 ,
default_width = args.width or args.menu_width or beautiful.menu_width or 130 ,
2013-05-27 02:49:51 +02:00
icon_size = args.icon_size or nil ,
2013-05-11 21:02:42 +02:00
auto_resize = args.auto_resize or true ,
parent_geometry = args.parent or nil ,
arrow_type = args.arrow_type or beautiful.menu_arrow_type or module.arrow_type . PRETTY ,
visible = args.visible or false ,
direction = args.direction or " top " ,
has_changed = false ,
row = args.row or nil ,
column = args.column or nil ,
layout = args.layout or nil ,
screen = args.screen or nil ,
style = args.style or nil ,
2015-01-11 05:59:51 +01:00
item_style = args.item_style or beautiful.menu_item_style or require ( " radical.item.style.basic " ) ,
2014-04-09 05:38:31 +02:00
item_layout = args.item_layout or nil ,
2013-07-18 06:03:19 +02:00
filter = args.filter ~= false ,
2013-05-11 21:02:42 +02:00
show_filter = args.show_filter or false ,
filter_string = args.filter_string or " " ,
suffix_widget = args.suffix_widget or nil ,
prefix_widget = args.prefix_widget or nil ,
fkeys_prefix = args.fkeys_prefix or false ,
2014-03-12 05:31:50 +01:00
underlay_alpha = args.underlay_alpha or beautiful.underlay_alpha or 0.7 ,
underlay_style = args.underlay_style or nil ,
2014-03-13 03:56:56 +01:00
filter_underlay = args.filter_underlay or nil ,
2013-07-07 06:39:17 +02:00
filter_prefix = args.filter_prefix or " Filter: " ,
2013-08-07 21:32:44 +02:00
enable_keyboard = ( args.enable_keyboard ~= false ) ,
2013-07-07 06:39:17 +02:00
max_items = args.max_items or nil ,
2013-10-01 04:19:38 +02:00
disable_markup = args.disable_markup or false ,
2013-08-07 06:35:49 +02:00
x = args.x or 0 ,
y = args.y or 0 ,
2014-02-06 04:48:26 +01:00
sub_menu_on = args.sub_menu_on or module.event . SELECTED ,
select_on = args.select_on or module.event . HOVER ,
2014-02-13 05:09:55 +01:00
overlay = args.overlay or nil ,
2014-02-18 04:57:04 +01:00
opacity = args.opacity or beautiful.menu_opacity or 1 ,
2014-11-15 05:46:06 +01:00
spacing = args.spacing or nil , --TODO add to README once merged upstream
2014-10-18 05:52:26 +02:00
default_margins = args.default_margins or { } ,
2014-12-25 07:10:55 +01:00
icon_per_state = args.icon_per_state or false ,
2014-10-18 05:52:26 +02:00
default_item_margins = args.default_item_margins or { } ,
icon_transformation = args.icon_transformation or nil ,
2014-03-13 03:56:56 +01:00
filter_underlay_style = args.filter_underlay_style or nil ,
filter_underlay_color = args.filter_underlay_color ,
filter_placeholder = args.filter_placeholder or " " ,
2014-12-25 07:10:55 +01:00
disable_submenu_icon = args.disable_submenu_icon or false ,
2015-01-11 05:59:51 +01:00
item_border_color = args.item_border_color or beautiful.menu_item_border_color or nil ,
2013-05-11 21:02:42 +02:00
} ,
force_private = {
parent = true ,
visible = true ,
} ,
always_handle = {
width = true ,
height = true ,
} ,
autogen_getmap = true ,
autogen_setmap = true ,
autogen_signals = true ,
} )
2014-03-05 06:12:48 +01:00
internal.private_data = private_data
2014-12-30 23:27:57 +01:00
-- Methods
2014-01-15 05:19:49 +01:00
data.add_item , data.add_widget , data.add_embeded_menu , data._internal , data.add_key_binding = add_item , add_widget , add_embeded_menu , internal , add_key_binding
2014-12-29 04:23:59 +01:00
data.add_prefix_widget , data.add_suffix_widget , data.add_items , data.add_widgets = add_prefix_widget , add_suffix_widget , add_items , add_widgets
2014-12-30 23:27:57 +01:00
data.add_colors_namespace = add_colors_namespace
-- Load colors
2014-02-23 05:59:03 +01:00
theme.setup_colors ( data , args )
2014-03-05 06:12:48 +01:00
-- Getters
2014-10-05 23:59:06 +02:00
data.get_is_menu = function ( _ ) return true end
data.get_margin = function ( _ ) return { left = 0 , bottom = 0 , right = 0 , left = 0 } end
data.get_items = function ( _ ) return internal.items end
data.get_rowcount = function ( _ ) return # internal.items end
data.get_visible_row_count = get_visible_row_count
data.get_widget_fit_height_sum = get_widget_fit_height_sum
data.get_widget_fit_width_sum = get_widget_fit_width_sum
2014-03-05 06:12:48 +01:00
-- Setters
data.set_auto_resize = function ( _ , val ) private_data [ " " ] = val end
data.set_parent_geometry = function ( _ , value )
2013-05-11 21:02:42 +02:00
private_data.parent_geometry = value
if data._internal . get_direction then
data.direction = data._internal . get_direction ( data )
end
if data._internal . set_position then
data._internal . set_position ( data )
end
end
2014-03-05 06:12:48 +01:00
data.set_visible = function ( _ , value )
2013-07-04 07:51:01 +02:00
private_data.visible = value
2013-07-04 07:20:46 +02:00
if value then
2013-07-21 10:15:56 +02:00
local fit_w , fit_h = data._internal . layout : fit ( 9999 , 9999 )
2013-08-09 08:07:27 +02:00
data.width = internal.width or fit_w
2013-07-04 07:20:46 +02:00
data.height = fit_h
2013-07-18 06:03:19 +02:00
elseif data._tmp_menu and data._current_item then
-- data._tmp_menu = nil
data._current_item . _tmp_menu = nil
-- data._current_item.selected = false
2014-03-02 22:28:30 +01:00
data.item_style ( data._current_item , { } )
2013-07-04 07:20:46 +02:00
end
2013-05-11 21:02:42 +02:00
if internal.has_changed and data.style then
data.style ( data , { arrow_x = 20 , margin = internal.margin } )
end
2014-01-05 23:35:23 +01:00
-- if not internal.parent_geometry and data._internal.set_position then
2013-05-11 21:02:42 +02:00
internal.set_position ( data )
2014-01-05 23:35:23 +01:00
-- end
2013-05-11 21:02:42 +02:00
if internal.set_visible then
internal : set_visible ( value )
end
if value and not capi.keygrabber . isrunning ( ) then
activateKeyboard ( data )
2013-12-19 06:22:49 +01:00
elseif data.parent_geometry and not data.parent_geometry . is_menu and data.enable_keyboard then
2013-05-11 21:02:42 +02:00
capi.keygrabber . stop ( )
end
end
2014-03-05 06:12:48 +01:00
2014-12-31 06:30:52 +01:00
data.add_colors_group = function ( data , section )
theme.add_section ( data , section , args )
end
2014-03-05 06:12:48 +01:00
data.set_layout = function ( _ , value )
2013-05-11 21:02:42 +02:00
if value then
value : setup_key_hooks ( data )
end
private_data.layout = value
end
-- set_map.auto_resize = function(value)
-- for k,v in ipairs(internal.items) do
-- TODO check all items size, ajustthe fit and global width
-- end
-- end
2014-03-05 06:12:48 +01:00
data.get_current_index = function ( _ )
2013-05-11 21:02:42 +02:00
if data._current_item then
for k , v in ipairs ( internal.items ) do --rows
2014-03-22 22:35:43 +01:00
if data._current_item == v then
return k
2013-05-11 21:02:42 +02:00
end
end
end
end
2014-03-05 06:12:48 +01:00
data.get_previous_item = function ( _ )
2014-01-21 06:24:51 +01:00
local candidate , idx = internal.items [ ( data.current_index or 0 ) - 1 ] , ( data.current_index or 0 ) - 1
2014-03-22 22:35:43 +01:00
while candidate and ( candidate._hidden or candidate._filter_out ) and idx > 0 do
2014-01-21 06:24:51 +01:00
candidate , idx = internal.items [ idx - 1 ] , idx - 1
end
2014-03-22 22:35:43 +01:00
return ( candidate or internal.items [ data.rowcount ] )
2014-01-21 06:24:51 +01:00
end
2014-03-05 06:12:48 +01:00
data.get_next_item = function ( _ )
2014-01-21 06:24:51 +01:00
local candidate , idx = internal.items [ ( data.current_index or 0 ) + 1 ] , ( data.current_index or 0 ) + 1
2014-03-22 22:35:43 +01:00
while candidate and ( candidate._hidden or candidate._filter_out ) and idx <= data.rowcount do
2014-01-21 06:24:51 +01:00
candidate , idx = internal.items [ idx + 1 ] , idx + 1
end
2014-03-23 05:14:25 +01:00
return ( candidate or internal.items [ 1 ] )
2014-01-21 06:24:51 +01:00
end
2013-05-11 21:02:42 +02:00
--Repaint when appearance properties change
for k , v in ipairs ( { " bg " , " fg " , " border_color " , " border_width " , " item_height " , " width " , " arrow_type " } ) do
data : connect_signal ( v .. " ::changed " , function ( )
if data.visible and data.style then
-- data.style(data,{arrow_x=20,margin=internal.margin})
else
data.has_changed = true
end
end )
end
function data : add_key_hook ( mod , key , event , func )
if key and event and func then
internal.filter_hooks = internal.filter_hooks or { }
internal.filter_hooks [ { key = key , event = event , mod = mod } ] = func
end
end
2014-01-15 05:39:24 +01:00
function data : remove_key_hook ( key ) --TODO broken?
2014-01-05 07:04:40 +01:00
for k , v in pairs ( internal.filter_hooks or { } ) do
2013-07-05 06:57:30 +02:00
if k.key == key then
internal.filter_hooks [ k ] = nil
break
end
end
end
2013-05-16 21:18:55 +02:00
function data : clear ( )
internal.items = { }
data : emit_signal ( " clear::menu " )
end
2014-02-05 07:03:25 +01:00
function data : swap ( item1 , item2 )
2014-02-08 06:52:42 +01:00
if not item1 or not item2 then return end
2014-02-05 07:03:25 +01:00
if not item1 or not item2 and item1 ~= item2 then return end
local idx1 , idx2
for k , v in ipairs ( internal.items ) do --rows
for k2 , v2 in ipairs ( v ) do --columns
if item2 == v2 then
idx2 = k
end
if item1 == v2 then
idx1 = k
end
end
if idx1 and idx2 then
break
end
end
if idx1 and idx2 then
internal.items [ idx1 ] , internal.items [ idx2 ] = internal.items [ idx2 ] , internal.items [ idx1 ]
2014-03-02 22:28:30 +01:00
item1.index , item2.index = idx2 , idx1
2014-02-05 07:03:25 +01:00
data : emit_signal ( " item::swapped " , item1 , item2 , idx1 , idx2 )
end
end
2014-02-06 03:43:06 +01:00
function data : move ( item , idx )
2014-02-08 06:52:42 +01:00
if not item or not idx then return end
2014-02-06 03:43:06 +01:00
local idx1 = nil
for k , v in ipairs ( internal.items ) do --rows
2014-03-22 22:35:43 +01:00
if item == v then
2014-02-06 03:43:06 +01:00
idx1 = k
break
end
end
if idx1 then
-- if idx < idx1 then
-- idx = idx + 1
-- end
if idx1 > # internal.items + 1 then
idx1 = # internal.items + 1
end
if idx ~= idx1 then
table.insert ( internal.items , idx1 , table.remove ( internal.items , idx ) )
2014-03-02 22:28:30 +01:00
item.index = idx
2014-02-06 03:43:06 +01:00
data : emit_signal ( " item::moved " , item , idx , idx1 )
2014-03-02 22:28:30 +01:00
for i = idx , idx1 do
2014-03-22 22:35:43 +01:00
internal.items [ i ] . index = i
2014-03-02 22:28:30 +01:00
end
2014-02-06 03:43:06 +01:00
end
end
end
function data : remove ( item )
2014-02-08 06:52:42 +01:00
if not item then return end
2014-02-06 03:43:06 +01:00
local idx1 = nil
for k , v in ipairs ( internal.items ) do --rows
2014-03-22 22:35:43 +01:00
if item == v then
2014-02-06 03:43:06 +01:00
idx1 = k
break
end
end
if idx1 then
table.remove ( internal.items , idx1 )
data : emit_signal ( " item::removed " , item , idx1 )
2014-03-02 22:28:30 +01:00
for i = idx1 , # internal.items do
2014-03-22 22:35:43 +01:00
internal.items [ i ] . index = i
2014-03-02 22:28:30 +01:00
end
2014-02-06 03:43:06 +01:00
end
end
2014-02-07 05:47:24 +01:00
function data : append ( item )
2014-02-08 06:52:42 +01:00
if not item then return end
2014-03-26 05:21:42 +01:00
internal.items [ # internal.items + 1 ] = item
2014-02-07 05:47:24 +01:00
data : emit_signal ( " item::appended " , item )
end
2013-07-08 00:18:55 +02:00
function data : scroll_up ( )
if data.max_items ~= nil and data.rowcount >= data.max_items and ( data._start_at or 1 ) > 1 then
2014-03-22 04:20:50 +01:00
local current_item = data._current_item
if current_item then
2014-03-22 05:11:03 +01:00
current_item : set_selected ( false , true )
2014-03-22 04:20:50 +01:00
end
2013-07-08 00:18:55 +02:00
data._start_at = ( data._start_at or 1 ) - 1
2014-03-22 22:35:43 +01:00
internal.items [ data._start_at ] . _hidden = false
data : emit_signal ( " _hidden::changed " , internal.items [ data._start_at ] )
internal.items [ data._start_at + data.max_items ] . _hidden = true
data : emit_signal ( " _hidden::changed " , internal.items [ data._start_at + data.max_items ] )
2013-08-09 08:07:27 +02:00
filter ( data )
2013-07-08 00:18:55 +02:00
end
end
2013-12-20 06:25:54 +01:00
2013-07-08 00:18:55 +02:00
function data : scroll_down ( )
if data.max_items ~= nil and data.rowcount >= data.max_items and ( data._start_at or 1 ) + data.max_items <= data.rowcount then
2014-03-22 04:20:50 +01:00
local current_item = data._current_item
if current_item then
2014-03-22 05:11:03 +01:00
current_item : set_selected ( false , true )
2014-03-22 04:20:50 +01:00
end
2013-07-08 00:18:55 +02:00
data._start_at = ( data._start_at or 1 ) + 1
2014-03-22 22:35:43 +01:00
internal.items [ data._start_at - 1 ] . _hidden = true
data : emit_signal ( " _hidden::changed " , internal.items [ data._start_at - 1 ] )
internal.items [ data._start_at - 1 + data.max_items ] . _hidden = false
data : emit_signal ( " _hidden::changed " , internal.items [ data._start_at - 1 + data.max_items ] )
2013-08-09 08:07:27 +02:00
filter ( data )
2013-07-08 00:18:55 +02:00
end
end
2014-08-03 00:04:47 +02:00
function data : hide ( )
data.visible = false
if data.parent_geometry and data.parent_geometry . is_menu then
local parent = data.parent_geometry
while parent do
parent.visible = false
parent = parent.parent_geometry and parent.parent_geometry . is_menu and parent.parent_geometry
end
end
end
2013-05-11 21:02:42 +02:00
if private_data.layout then
private_data.layout : setup_key_hooks ( data )
end
data._internal . setup_drawable ( data )
return data
end
return setmetatable ( module , { __call = function ( _ , ... ) return new ( ... ) end } )
-- kate: space-indent on; indent-width 2; replace-tabs on;