z_mirror/TaskList
git clone https://git.raiguard.me/z_mirror/TaskList
c741b03
trunk
1local gui =require ( "gui" ) 2 3local constants =require ( "constants" ) 4 5local util =require ( "scripts.util" ) 6 7local active_task_button =require ( "scripts.gui.active-task-button" ) 8 9local actions =require ( "scripts.gui.tasks.actions" ) 10local templates =require ( "scripts.gui.tasks.templates" ) 11 12-- GUI 13 14--- @class TasksGuiState 15--- @field ignore_close boolean 16--- @field pinned boolean 17--- @field show_completed boolean 18--- @field visible boolean 19 20--- @class TasksGuiRefs 21--- @field window LuaGuiElement 22--- @field titlebar_flow LuaGuiElement 23--- @field pin_button LuaGuiElement 24--- @field visibility_switch LuaGuiElement 25--- @field new_task_button LuaGuiElement 26--- @field scroll_pane LuaGuiElement 27--- @field force_flow LuaGuiElement 28--- @field private_flow LuaGuiElement 29 30--- @class TasksGui 31local TasksGui ={} 32 33TasksGui . actions =actions 34 35function TasksGui : destroy () 36local window =self . refs . window 37if window and window . valid then 38self . refs . window . destroy () 39end 40 41self . player_table . guis . tasks =nil 42end 43 44function TasksGui : open () 45self . refs . window . bring_to_front () 46self . refs . window . visible =true 47self . state . visible =true 48 49if not self . state . pinned then 50self . player . opened =self . refs . window 51end 52 53self . player . set_shortcut_toggled ( "tlst-toggle-gui" , true ) 54end 55 56function TasksGui : close () 57if self . state . ignore_close then 58self . state . ignore_close =false 59return 60end 61 62self . refs . window . visible =false 63self . state . visible =false 64 65if self . player . opened == self . refs . window then 66self . player . opened =nil 67end 68 69self . player . set_shortcut_toggled ( "tlst-toggle-gui" , false ) 70end 71 72function TasksGui : toggle () 73if self . state . visible then 74self : close () 75else 76self : open () 77end 78end 79 80function TasksGui : dispatch ( msg , e ) 81local transform =msg . transform 82if transform then 83if transform == "handle_titlebar_click" and e . button == defines . mouse_button_type . middle then 84msg . action ="recenter" 85elseif transform == "handle_expand_click" then 86if e . shift then 87msg . action ="move_task" 88msg . delta =- 1 89elseif e . control then 90msg . action ="move_task" 91msg . delta =1 92else 93msg . action ="expand_task" 94end 95end 96end 97 98if msg . action then 99local handler =self . actions [ msg . action ] 100if handler then 101handler ( self , msg , e ) 102end 103end 104end 105 106--- Get the parent flow for the given task 107--- @param Task Task 108function TasksGui : get_parent_flow ( Task ) 109local route ={} 110 111local owner =Task . owner 112while owner . object_name == "Task" do 113table . insert ( route , 1 , owner ) 114owner =owner . owner 115end 116 117-- At this point, the owner will be a LuaForce or LuaPlayer 118local flow =owner . object_name == "LuaForce" and self . refs . force_flow or self . refs . private_flow 119for _ , owner in pairs ( route ) do 120local subflow =owner . completed and flow . completed or flow . incompleted --[[@as LuaGuiElement]] 121local row =subflow [ tostring ( owner . id )] 122if row then 123flow =row . details_flow . subtasks_flow 124end 125end 126 127return flow 128end 129 130--- @param Task Task 131--- @param index number? 132--- @param completed boolean? 133function TasksGui : add_task ( Task , index , completed ) 134if completed == nil then 135completed =Task . completed 136end 137local flow =self : get_parent_flow ( Task ) 138local flow =completed and flow . completed or flow . incompleted --[[@as LuaGuiElement]] 139 140-- Somehow the task state is getting desynced from the GUI sometimes 141local existing =flow [ tostring ( Task . id )] 142if existing then 143existing . destroy () 144end 145 146gui . add ( flow , templates . task_item ( Task , index , completed )) 147 148if # flow . children > 0 and ( not completed or self . state . show_completed ) then 149flow . visible =true 150else 151flow . visible =false 152end 153 154-- Add subtasks 155for _ , subtasks in pairs ( { Task . completed_tasks , Task . tasks } ) do 156for _ , subtask_id in pairs ( subtasks ) do 157local subtask =storage . tasks [ subtask_id ] 158if subtask then 159self : add_task ( subtask ) 160end 161end 162end 163 164active_task_button . update ( self . player , self . player_table ) 165end 166 167--- @param Task Task 168function TasksGui : update_task ( Task ) 169local flow =self : get_parent_flow ( Task ) 170local flow =Task . completed and flow . completed or flow . incompleted --[[@as LuaGuiElement]] 171 172local row =flow [ tostring ( Task . id )] 173if row then 174local status_info =constants . task_status [ Task . status ] 175local assignee_name =Task . assignee and Task . assignee . name or nil 176gui . update ( row , { 177{ 178{ elem_mods ={ caption =Task . title } } , 179{ elem_mods ={ caption =assignee_name , visible =assignee_name and true or false } } , 180{ 181elem_mods ={ 182sprite ="flib_indicator_" .. status_info . color , 183tooltip =status_info . label , 184} , 185} , 186} , 187{ 188{ elem_mods ={ caption =Task . description , visible =# Task . description > 0 } } , 189} , 190} ) 191 192active_task_button . update ( self . player , self . player_table ) 193end 194end 195 196--- @param Task Task 197function TasksGui : delete_task ( Task , completed ) 198if completed == nil then 199completed =Task . completed 200end 201local flow =self : get_parent_flow ( Task ) 202--- @type LuaGuiElement 203local flow =completed and flow . completed or flow . incompleted --[[@as LuaGuiElement]] 204 205local row =flow [ tostring ( Task . id )] 206if row then 207row . destroy () 208end 209 210if # flow . children > 0 and ( not completed or self . state . show_completed ) then 211flow . visible =true 212else 213flow . visible =false 214end 215 216active_task_button . update ( self . player , self . player_table ) 217end 218 219--- @param Task Task 220--- @param delta number 221function TasksGui : move_task ( Task , delta ) 222local flow =self : get_parent_flow ( Task ) 223--- @type LuaGuiElement 224local flow =Task . completed and flow . completed or flow . incompleted --[[@as LuaGuiElement]] 225local row =flow [ tostring ( Task . id )] 226if row then 227flow . swap_children ( row . get_index_in_parent (), row . get_index_in_parent () + delta --[[@as uint]] ) 228end 229 230active_task_button . update ( self . player , self . player_table ) 231end 232 233function TasksGui : update_show_completed () 234local show_completed =self . state . show_completed 235 236util . recursive_show_completed ( self . refs . force_flow , show_completed ) 237util . recursive_show_completed ( self . refs . private_flow , show_completed ) 238end 239 240-- BOOTSTRAP 241 242local index ={} 243 244--- @param player LuaPlayer 245--- @param player_table PlayerTable 246function index . new ( player , player_table ) 247local new_task_on_confirm =player . mod_settings [ "tlst-new-task-on-confirm" ]. value 248--- @type TasksGuiRefs 249local refs =gui . build ( player . gui . screen , { 250{ 251type ="frame" , 252name ="tlst_tasks_window" , 253style_mods ={ width =500 } , 254direction ="vertical" , 255ref ={ "window" } , 256visible =false , 257actions ={ 258on_closed ={ gui ="tasks" , action ="close" } , 259} , 260{ 261type ="flow" , 262style ="flib_titlebar_flow" , 263ref ={ "titlebar_flow" } , 264actions ={ 265on_click ={ gui ="tasks" , transform ="handle_titlebar_click" } , 266} , 267{ type ="label" , style ="frame_title" , caption ={ "gui.tlst-tasks" } , ignored_by_interaction =true } , 268{ type ="empty-widget" , style ="flib_titlebar_drag_handle" , ignored_by_interaction =true } , 269templates . frame_action_button ( 270"flib_pin_white" , 271{ "gui.flib-keep-open" } , 272{ gui ="tasks" , action ="pin" } , 273{ "pin_button" } 274), 275templates . frame_action_button ( "utility/close" , { "gui.close" } , { 276gui ="tasks" , 277action ="close" , 278} ), 279} , 280{ 281type ="frame" , 282style ="inside_shallow_frame" , 283direction ="vertical" , 284{ 285type ="frame" , 286style ="subheader_frame" , 287{ 288type ="checkbox" , 289style_mods ={ left_margin =8 } , 290caption ={ "gui.tlst-show-completed" } , 291state =false , 292actions ={ 293on_checked_state_changed ={ gui ="tasks" , action ="toggle_show_completed" } , 294} , 295} , 296{ type ="empty-widget" , style ="flib_horizontal_pusher" } , 297{ 298type ="switch" , 299left_label_caption ={ "gui.tlst-force" } , 300left_label_tooltip ={ "gui.tlst-force-switch-description" } , 301right_label_caption ={ "gui.tlst-private" } , 302right_label_tooltip ={ "gui.tlst-private-switch-description" } , 303switch_state ="left" , 304ref ={ "visibility_switch" } , 305actions ={ 306on_switch_state_changed ={ gui ="tasks" , action ="toggle_tasks_mode" } , 307} , 308} , 309{ type ="empty-widget" , style_mods ={ width =20 } } , 310{ 311type ="sprite-button" , 312style ="flib_tool_button_light_green" , 313sprite ="utility/add" , 314tooltip =new_task_on_confirm and { "gui.tlst-new-task-instruction" } or { "gui.tlst-new-task" } , 315ref ={ "new_task_button" } , 316actions ={ 317on_click ={ gui ="tasks" , action ="edit_task" } , 318} , 319} , 320} , 321{ 322type ="scroll-pane" , 323style ="tlst_tasks_scroll_pane" , 324style_mods ={ maximal_height =800 } , 325ref ={ "scroll_pane" } , 326templates . checkboxes_flow ( "force" ), 327templates . checkboxes_flow ( "private" , false ), 328} , 329} , 330} , 331} ) 332 333refs . window . force_auto_center () 334refs . titlebar_flow . drag_target =refs . window 335 336--- @class TasksGui 337local self ={ 338player =player , 339player_table =player_table , 340refs =refs , 341--- @type TasksGuiState 342state ={ 343ignore_close =false , 344pinned =false , 345show_completed =false , 346visible =false , 347} , 348} 349 350setmetatable ( self , { __index =TasksGui } ) 351 352player_table . guis . tasks =self 353 354-- Add existing tasks 355local force_table =storage . forces [ util . get_force ( player ). index ] 356for _ , tasks in pairs ( { 357force_table . completed_tasks , 358force_table . tasks , 359player_table . completed_tasks , 360player_table . tasks , 361} ) do 362for _ , task_id in pairs ( tasks ) do 363local Task =storage . tasks [ task_id ] 364if Task then 365self : add_task ( Task ) 366end 367end 368end 369end 370 371--- @param Gui TasksGui 372function index . load ( Gui ) 373setmetatable ( Gui , { __index =TasksGui } ) 374end 375 376return index