z_mirror/TaskList
git clone https://git.raiguard.me/z_mirror/TaskList
fa77a7d
task-details-gui
1local gui =require ( "__flib__.gui" ) 2 3local actions =require ( "scripts.gui.task.actions" ) 4local constants =require ( "constants" ) 5local templates =require ( "scripts.gui.templates" ) 6local util =require ( "scripts.util" ) 7 8--- @class TaskGuiRefs 9--- @field window LuaGuiElement 10--- @field titlebar_flow LuaGuiElement 11 12--- @class TaskGui 13local TaskGui ={} 14 15TaskGui . actions =actions 16 17function TaskGui : destroy () 18local window =self . refs . window 19if window and window . valid then 20self . refs . window . destroy () 21end 22 23self . player_table . guis . task [ self . Task . id ] =nil 24end 25 26function TaskGui : open () 27self . refs . window . bring_to_front () 28self . refs . window . visible =true 29end 30 31function TaskGui : close () 32self . refs . window . visible =false 33 34if self . player . opened == self . refs . window then 35self . player . opened =nil 36end 37end 38 39function TaskGui : toggle () 40if self . refs . window . visible then 41self : close () 42else 43self : open () 44end 45end 46 47function TaskGui : dispatch ( msg , e ) 48if msg . transform and msg . transform == "handle_expand_click" then 49if e . button == defines . mouse_button_type . middle then 50msg . action ="open_task_gui" 51else 52if e . shift then 53msg . action ="move_task" 54msg . delta =- 1 55elseif e . control then 56msg . action ="move_task" 57msg . delta =1 58else 59msg . action ="expand_task" 60end 61end 62end 63 64if msg . action then 65local handler =self . actions [ msg . action ] 66if handler then 67handler ( self , msg , e ) 68end 69end 70end 71 72--- Get the parent flow for the given task 73--- @param Task Task 74function TaskGui : get_parent_flow ( Task ) 75local route ={} 76 77local owner =Task . owner 78while owner . object_name == "Task" and owner . id ~= self . Task . id do 79table . insert ( route , 1 , owner ) 80owner =owner . owner 81end 82 83local flow =self . refs . subtasks_scroll_pane 84for _ , owner in pairs ( route ) do 85local subflow =owner . completed and flow . completed or flow . incompleted 86local row =subflow [ tostring ( owner . id )] 87if row then 88flow =row . details_flow . subtasks_flow 89end 90end 91 92return flow 93end 94 95--- @param Task Task 96--- @param index number 97function TaskGui : add_task ( Task , index , completed ) 98if completed == nil then 99completed =Task . completed 100end 101local flow =self : get_parent_flow ( Task ) 102--- @type LuaGuiElement 103local flow =completed and flow . completed or flow . incompleted 104 105gui . add ( flow , templates . task_item ( Task , { name ="task" , id =self . Task . id } , index , completed )) 106 107if # flow . children > 0 and ( not completed or self . state . show_completed ) then 108flow . visible =true 109else 110flow . visible =false 111end 112 113-- Add subtasks 114for _ , subtasks in pairs ( { Task . completed_tasks , Task . tasks } ) do 115for _ , subtask_id in pairs ( subtasks ) do 116local subtask =global . tasks [ subtask_id ] 117if subtask then 118self : add_task ( subtask ) 119end 120end 121end 122end 123 124--- @param Task Task 125function TaskGui : update_task ( Task ) 126local flow =self : get_parent_flow ( Task ) 127--- @type LuaGuiElement 128local flow =Task . completed and flow . completed or flow . incompleted 129 130local row =flow [ tostring ( Task . id )] 131if row then 132local status_info =constants . task_status [ Task . status ] 133local assignee_name =Task . assignee and Task . assignee . name or nil 134gui . update ( row , { 135{ 136{ elem_mods ={ caption =Task . title } } , 137{ elem_mods ={ caption =assignee_name , visible =assignee_name and true or false } } , 138{ 139elem_mods ={ 140sprite ="flib_indicator_" .. status_info . color , 141tooltip =status_info . label , 142} , 143} , 144} , 145{ 146{ elem_mods ={ caption =Task . description , visible =# Task . description > 0 } } , 147} , 148} ) 149end 150end 151 152--- @param Task Task 153function TaskGui : delete_task ( Task , completed ) 154if completed == nil then 155completed =Task . completed 156end 157local flow =self : get_parent_flow ( Task ) 158--- @type LuaGuiElement 159local flow =completed and flow . completed or flow . incompleted 160 161local row =flow [ tostring ( Task . id )] 162if row then 163row . destroy () 164end 165 166if # flow . children > 0 and ( not completed or self . state . show_completed ) then 167flow . visible =true 168else 169flow . visible =false 170end 171end 172 173--- @param Task Task 174--- @param delta number 175function TaskGui : move_task ( Task , delta ) 176local flow =self : get_parent_flow ( Task ) 177--- @type LuaGuiElement 178local flow =Task . completed and flow . completed or flow . incompleted 179local row =flow [ tostring ( Task . id )] 180if row then 181flow . swap_children ( row . get_index_in_parent (), row . get_index_in_parent () + delta ) 182end 183end 184 185function TaskGui : update_show_completed () 186util . recursive_show_completed ( self . refs . subtasks_scroll_pane , self . state . show_completed ) 187end 188 189-- BOOTSTRAP 190 191local index ={} 192 193--- @param player LuaPlayer 194--- @param player_table PlayerTable 195--- @param Task Task 196function index . new ( player , player_table , Task ) 197local status_items ={} 198local selected_status_index =1 199for status_name , status_info in pairs ( constants . task_status ) do 200if status_name == Task . status then 201selected_status_index =status_info . index 202end 203table . insert ( status_items , { "" , "[img=flib_indicator_" .. status_info . color .. "] " , status_info . label } ) 204end 205 206local refs =gui . build ( player . gui . screen , { 207{ 208type ="frame" , 209style_mods ={ width =500 } , 210direction ="vertical" , 211ref ={ "window" } , 212{ 213type ="flow" , 214style ="flib_titlebar_flow" , 215ref ={ "titlebar_flow" } , 216actions ={ on_click ={ gui ={ name ="task" , id =Task . id } , action ="recenter" } } , 217{ type ="label" , style ="frame_title" , caption ={ "gui.tlst-task" } , ignored_by_interaction =true } , 218{ type ="empty-widget" , style ="flib_titlebar_drag_handle" , ignored_by_interaction =true } , 219templates . frame_action_button ( 220"utility/close" , 221{ "gui.close" } , 222{ gui ={ name ="task" , id =Task . id } , action ="close" } 223), 224} , 225{ 226type ="frame" , 227style ="inside_shallow_frame" , 228direction ="vertical" , 229{ 230type ="frame" , 231style ="subheader_frame" , 232{ type ="label" , style ="subheader_caption_label" , caption =Task . title } , 233{ type ="empty-widget" , style ="flib_horizontal_pusher" } , 234{ 235type ="drop-down" , 236items =status_items , 237selected_index =selected_status_index , 238ref ={ "status_dropdown" } , 239} , 240{ 241type ="sprite-button" , 242style ="tool_button" , 243sprite ="utility/rename_icon_normal" , 244tooltip ={ "gui.tlst-edit-task" } , 245actions ={ 246on_click ={ gui ={ name ="task" , id =Task . id } , action ="edit_task" , task_id =Task . id } , 247} , 248} , 249} , 250{ 251type ="flow" , 252style_mods ={ padding =12 , vertical_spacing =12 } , 253direction ="vertical" , 254{ 255type ="frame" , 256style ="tlst_description_frame" , 257style_mods ={ horizontally_stretchable =true } , 258visible =# Task . description > 0 , 259{ 260type ="label" , 261style_mods ={ single_line =false } , 262caption =Task . description , 263} , 264} , 265{ 266type ="frame" , 267style ="flib_shallow_frame_in_shallow_frame" , 268direction ="vertical" , 269{ 270type ="frame" , 271style ="subheader_frame" , 272style_mods ={ left_padding =12 } , 273{ 274type ="checkbox" , 275caption ={ "gui.tlst-show-completed" } , 276state =false , 277actions ={ 278on_click ={ gui ={ name ="task" , id =Task . id } , action ="toggle_show_completed" } , 279} , 280} , 281{ type ="empty-widget" , style ="flib_horizontal_pusher" } , 282{ 283type ="sprite-button" , 284style ="flib_tool_button_light_green" , 285sprite ="utility/add" , 286tooltip ={ "gui.tlst-new-task" } , 287actions ={ 288on_click ={ gui ={ name ="task" , id =Task . id } , action ="edit_task" , parent_task_id =Task . id } , 289} , 290} , 291} , 292{ 293type ="scroll-pane" , 294style ="flib_naked_scroll_pane" , 295ref ={ "subtasks_scroll_pane" } , 296{ type ="flow" , name ="incompleted" , direction ="vertical" } , 297{ type ="flow" , name ="completed" , direction ="vertical" , visible =false } , 298} , 299} , 300} , 301} , 302} , 303} ) 304 305refs . titlebar_flow . drag_target =refs . window 306refs . window . force_auto_center () 307 308--- @type TaskGui 309local self ={ 310player =player , 311player_table =player_table , 312refs =refs , 313state ={} , 314Task =Task , 315} 316 317index . load ( self ) 318 319player_table . guis . task [ Task . id ] =self 320 321-- Add existing tasks 322for _ , tasks in pairs ( { 323Task . completed_tasks , 324Task . tasks , 325} ) do 326for _ , task_id in pairs ( tasks ) do 327local Task =global . tasks [ task_id ] 328if Task then 329self : add_task ( Task ) 330end 331end 332end 333end 334 335--- @param Gui TasksGui 336function index . load ( Gui ) 337setmetatable ( Gui , { __index =TaskGui } ) 338end 339 340return index