mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2025-12-27 03:25:23 +09:00
Refactor task list (#414)
This commit is contained in:
@@ -24,7 +24,6 @@ return {
|
||||
--- GUI
|
||||
"modules.gui.readme",
|
||||
"modules.gui.rocket-info",
|
||||
"modules.gui.task-list",
|
||||
"modules.gui.warp-list",
|
||||
"modules.gui.player-list",
|
||||
"modules.gui.vlayer",
|
||||
|
||||
@@ -54,28 +54,6 @@ progress-caption=__1__%
|
||||
progress-tooltip=This silo has launched __1__ rockets
|
||||
launch-failed=Failed to launch rocket, please wait a few seconds and try again.
|
||||
|
||||
[task-list]
|
||||
main-caption=Task List [img=info]
|
||||
main-tooltip=Task List
|
||||
sub-tooltip=Tasks that remain to be done\n- You can use richtext to include images [img=utility/not_enough_repair_packs_icon] or [color=blue]color[/color] your tasks.
|
||||
no-tasks=No tasks found!
|
||||
no-tasks-tooltip=Click on the plus button to the top right of this window to add a new task!
|
||||
last-edit=Last edited by __1__ at __2__
|
||||
add-tooltip=Add new task
|
||||
confirm=Confirm
|
||||
confirm-tooltip=Save task (minimum of 5 characters long)
|
||||
discard=Discard
|
||||
discard-tooltip=Discard task/changes
|
||||
delete=Delete
|
||||
delete-tooltip=Delete task
|
||||
close-tooltip=Close task details
|
||||
edit=Edit task
|
||||
edit-tooltip=Currently being edited by: __1__
|
||||
edit-tooltip-none=Currently being edited by: Nobody
|
||||
create-footer-header=Create task
|
||||
edit-footer-header=Edit task
|
||||
view-footer-header=Task details
|
||||
|
||||
[warp-list]
|
||||
main-caption=Warp List [img=info]
|
||||
main-tooltip=Warp List
|
||||
|
||||
@@ -54,28 +54,6 @@ progress-caption=__1__ %
|
||||
progress-tooltip=該火箭發射井發射了 __1__ 次
|
||||
launch-failed=火箭發射失敗, 請過一會再試。
|
||||
|
||||
[task-list]
|
||||
main-caption=工作流程 [img=info]
|
||||
main-tooltip=工作流程
|
||||
sub-tooltip=需要完成的工作流程\n- 你可以用富文本來加上圖片 [img=utility/not_enough_repair_packs_icon] 或 [color=blue] 顏色[/color]。
|
||||
no-tasks=沒有工作流程
|
||||
no-tasks-tooltip=按加號加入工作流程
|
||||
last-edit=最後由 __1__ 在 __2__ 修改
|
||||
add-tooltip=加入工作流程
|
||||
confirm=確認
|
||||
confirm-tooltip=儲存工作流程 (最少要5個字長)
|
||||
discard=放棄
|
||||
discard-tooltip=放棄更改動
|
||||
delete=刪除
|
||||
delete-tooltip=刪除工作流程
|
||||
close-tooltip=關閉工作流程
|
||||
edit=修改工作流程
|
||||
edit-tooltip=現被 __1__ 修改中
|
||||
edit-tooltip-none=現沒有被人修改
|
||||
create-footer-header=加入工作流程
|
||||
edit-footer-header=修改工作流程
|
||||
view-footer-header=工作流程細節
|
||||
|
||||
[warp-list]
|
||||
main-caption=傳送陣清單 [img=info]
|
||||
main-tooltip=傳送陣清單
|
||||
|
||||
@@ -54,28 +54,6 @@ progress-caption=__1__ %
|
||||
progress-tooltip=該火箭發射井發射了 __1__ 次
|
||||
launch-failed=火箭發射失敗, 請過一會再試。
|
||||
|
||||
[task-list]
|
||||
main-caption=工作流程 [img=info]
|
||||
main-tooltip=工作流程
|
||||
sub-tooltip=需要完成的工作流程\n- 你可以用富文本來加上圖片 [img=utility/not_enough_repair_packs_icon] 或 [color=blue] 顏色[/color]。
|
||||
no-tasks=沒有工作流程
|
||||
no-tasks-tooltip=按加號加入工作流程
|
||||
last-edit=最後由 __1__ 在 __2__ 修改
|
||||
add-tooltip=加入工作流程
|
||||
confirm=確認
|
||||
confirm-tooltip=儲存工作流程 (最少要5個字長)
|
||||
discard=放棄
|
||||
discard-tooltip=放棄更改動
|
||||
delete=刪除
|
||||
delete-tooltip=刪除工作流程
|
||||
close-tooltip=關閉工作流程
|
||||
edit=修改工作流程
|
||||
edit-tooltip=現被 __1__ 修改中
|
||||
edit-tooltip-none=現沒有被人修改
|
||||
create-footer-header=加入工作流程
|
||||
edit-footer-header=修改工作流程
|
||||
view-footer-header=工作流程細節
|
||||
|
||||
[warp-list]
|
||||
main-caption=傳送陣清單 [img=info]
|
||||
main-tooltip=傳送陣清單
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
--[[-- Control Module - Tasks
|
||||
- Stores tasks for each force.
|
||||
@control Tasks
|
||||
@alias Tasks
|
||||
|
||||
@usage-- Making and then editing a new task
|
||||
local task_id = Tasks.add_task(game.player.force.name, nil, game.player.name)
|
||||
|
||||
Tasks.update_task(task_id, 'We need more iron!', game.player.name)
|
||||
|
||||
]]
|
||||
|
||||
local Datastore = require("modules.exp_legacy.expcore.datastore") --- @dep expcore.datastore
|
||||
local Storage = require("modules/exp_util/storage")
|
||||
|
||||
--- Stores all data for the warp gui
|
||||
local TaskData = Datastore.connect("TaskData")
|
||||
TaskData:set_serializer(function(raw_key) return raw_key.task_id end)
|
||||
|
||||
local Tasks = {}
|
||||
|
||||
-- Storage lookup table for force name to task ids
|
||||
local force_tasks = { _uid = 1 }
|
||||
Storage.register(force_tasks, function(tbl)
|
||||
force_tasks = tbl
|
||||
end)
|
||||
|
||||
--- Setters.
|
||||
-- functions used to created and alter tasks
|
||||
-- @section setters
|
||||
|
||||
--[[-- Add a new task for a force, the task can be placed into a certain position for that force
|
||||
@tparam string force_name the name of the force to add the task for
|
||||
@tparam[opt] string player_name the player who added this task, will cause them to be listed under editing
|
||||
@tparam[opt] string task_title the task title, if not given default is used
|
||||
@tparam[opt] string task_body the task body, if not given default is used
|
||||
@treturn string the uid of the task which was created
|
||||
|
||||
@usage-- Adding a new task for your force
|
||||
local task_id = Tasks.add_task(game.player.force.name, game.player.name, nil, nil)
|
||||
|
||||
]]
|
||||
function Tasks.add_task(force_name, player_name, task_title, task_body)
|
||||
-- Get a new task id
|
||||
local task_id = tostring(force_tasks._uid)
|
||||
force_tasks._uid = force_tasks._uid + 1
|
||||
|
||||
-- Get the existing tasks for this force
|
||||
local task_ids = force_tasks[force_name] --[[@as table?]]
|
||||
if not task_ids then
|
||||
task_ids = {}
|
||||
force_tasks[force_name] = task_ids --[[@as any]]
|
||||
end
|
||||
|
||||
-- Insert the task id into the forces tasks
|
||||
table.insert(task_ids, task_id)
|
||||
|
||||
-- Add the new task to the store
|
||||
TaskData:set(task_id, {
|
||||
task_id = task_id,
|
||||
force_name = force_name,
|
||||
title = task_title or "",
|
||||
body = task_body or "",
|
||||
last_edit_name = player_name or "<server>",
|
||||
last_edit_time = game.tick,
|
||||
currently_editing = {},
|
||||
})
|
||||
|
||||
return task_id
|
||||
end
|
||||
|
||||
--[[-- Removes a task and any data that is linked with it
|
||||
@tparam string task_id the uid of the task which you want to remove
|
||||
|
||||
@usage-- Removing a task
|
||||
Tasks.remove_task(task_id)
|
||||
|
||||
]]
|
||||
function Tasks.remove_task(task_id)
|
||||
local task = TaskData:get(task_id)
|
||||
local force_name = task.force_name
|
||||
table.remove_element(force_tasks[force_name], task_id)
|
||||
TaskData:remove(task_id)
|
||||
end
|
||||
|
||||
--[[-- Update the message and last edited information for a task
|
||||
@tparam string task_id the uid of the task to update
|
||||
@tparam string player_name the name of the player who made the edit
|
||||
@tparam string task_title the title of the task to update to
|
||||
@tparam string task_body the body of the task to update to
|
||||
|
||||
@usage-- Updating the message for on a task
|
||||
Task.update_task(task_id, game.player.name, 'We need more iron!', 'Build more iron outposts.')
|
||||
|
||||
]]
|
||||
function Tasks.update_task(task_id, player_name, task_title, task_body)
|
||||
TaskData:update(task_id, function(_, task)
|
||||
task.last_edit_name = player_name
|
||||
task.last_edit_time = game.tick
|
||||
task.title = task_title
|
||||
task.body = task_body
|
||||
end)
|
||||
end
|
||||
|
||||
--[[-- Set the editing state for a player, can be used as a warning or to display a text field
|
||||
@tparam string task_id the uid of the task that you want to effect
|
||||
@tparam string player_name the name of the player you want to set the state for
|
||||
@tparam boolean state the new state to set editing to
|
||||
|
||||
@usage-- Setting your editing state to true
|
||||
Tasks.set_editing(task_id, game.player.name, true)
|
||||
|
||||
]]
|
||||
function Tasks.set_editing(task_id, player_name, state)
|
||||
TaskData:update(task_id, function(_, task)
|
||||
task.currently_editing[player_name] = state
|
||||
end)
|
||||
end
|
||||
|
||||
--[[-- Adds an update handler for when a task is added, removed, or updated
|
||||
@tparam function handler the handler which is called when a task is updated
|
||||
|
||||
@usage-- Add a game print when a task is updated
|
||||
Tasks.on_update(function(task)
|
||||
game.print(task.force_name..' now has the task: '..task.message)
|
||||
end)
|
||||
|
||||
]]
|
||||
function Tasks.on_update(handler)
|
||||
TaskData:on_update(handler)
|
||||
end
|
||||
|
||||
--- Getters.
|
||||
-- function used to get information about tasks
|
||||
-- @section getters
|
||||
|
||||
--[[-- Gets the task information that is linked with this id
|
||||
@tparam string task_id the uid of the task you want to get
|
||||
@treturn table the task information
|
||||
|
||||
@usage-- Getting task information outside of on_update
|
||||
local task = Tasks.get_task(task_id)
|
||||
|
||||
]]
|
||||
function Tasks.get_task(task_id)
|
||||
return TaskData:get(task_id)
|
||||
end
|
||||
|
||||
--[[-- Gets all the task ids that a force has
|
||||
@tparam string force_name the name of the force that you want the task ids for
|
||||
@treturn table an array of all the task ids
|
||||
|
||||
@usage-- Getting the task ids for a force
|
||||
local task_ids = Tasks.get_force_task_ids(game.player.force.name)
|
||||
|
||||
]]
|
||||
function Tasks.get_force_task_ids(force_name)
|
||||
return force_tasks[force_name] or {}
|
||||
end
|
||||
|
||||
--[[-- Gets the editing state for a player
|
||||
@tparam string task_id the uid of the task you want to check
|
||||
@tparam string player_name the name of the player that you want to check
|
||||
@treturn boolean weather the player is currently editing this task
|
||||
|
||||
@usage-- Check if a player is editing a task or not
|
||||
local editing = Tasks.get_editing(task_id, game.player.name)
|
||||
|
||||
]]
|
||||
function Tasks.get_editing(task_id, player_name)
|
||||
local task = TaskData:get(task_id)
|
||||
return task.currently_editing[player_name]
|
||||
end
|
||||
|
||||
-- Module Return
|
||||
return Tasks
|
||||
@@ -1,794 +0,0 @@
|
||||
--[[-- Gui Module - Task List
|
||||
- Adds a task list to the game which players can add, remove and edit items on
|
||||
@gui Task-List
|
||||
@alias task_list
|
||||
]]
|
||||
|
||||
local ExpUtil = require("modules/exp_util")
|
||||
local Gui = require("modules/exp_gui")
|
||||
local Event = require("modules/exp_legacy/utils/event") --- @dep utils.event
|
||||
local Roles = require("modules.exp_legacy.expcore.roles") --- @dep expcore.roles
|
||||
local Datastore = require("modules.exp_legacy.expcore.datastore") --- @dep expcore.datastore
|
||||
local config = require("modules.exp_legacy.config.gui.tasks") --- @dep config.gui.tasks
|
||||
local Tasks = require("modules.exp_legacy.modules.control.tasks") --- @dep modules.control.tasks
|
||||
|
||||
local format_time = ExpUtil.format_time_factory_locale{ format = "short", hours = true, minutes = true }
|
||||
|
||||
--- Stores all data for the task gui by player
|
||||
local TaskGuiData = Datastore.connect("TaskGuiData")
|
||||
TaskGuiData:set_serializer(Datastore.name_serializer)
|
||||
local PlayerIsEditing = TaskGuiData:combine("PlayerIsEditing")
|
||||
PlayerIsEditing:set_default(false)
|
||||
local PlayerIsCreating = TaskGuiData:combine("PlayerIsCreating")
|
||||
PlayerIsCreating:set_default(false)
|
||||
local PlayerSelected = TaskGuiData:combine("PlayerSelected")
|
||||
PlayerSelected:set_default(nil)
|
||||
|
||||
-- Styles used for sprite buttons
|
||||
local Styles = {
|
||||
sprite22 = {
|
||||
height = 22,
|
||||
width = 22,
|
||||
padding = -2,
|
||||
},
|
||||
footer_button = {
|
||||
height = 29,
|
||||
maximal_width = 268,
|
||||
horizontally_stretchable = true,
|
||||
padding = -2,
|
||||
},
|
||||
}
|
||||
|
||||
--- If a player is allowed to use the edit buttons
|
||||
local function check_player_permissions(player, task)
|
||||
if task then
|
||||
-- When a task is given check if the player can edit it
|
||||
local allow_edit_task = config.allow_edit_task
|
||||
|
||||
-- Check if the player being the last to edit will override existing permisisons
|
||||
if config.user_can_edit_own_tasks and task.last_edit_name == player.name then
|
||||
return true
|
||||
end
|
||||
|
||||
-- Check player has permisison based on value in the config
|
||||
if allow_edit_task == "all" then
|
||||
return true
|
||||
elseif allow_edit_task == "admin" then
|
||||
return player.admin
|
||||
elseif allow_edit_task == "expcore.roles" then
|
||||
return Roles.player_allowed(player, config.expcore_roles_allow_edit_task)
|
||||
end
|
||||
|
||||
-- Return false as all other condidtions have not been met
|
||||
return false
|
||||
else
|
||||
-- When a task is not given check if the player can add a new task
|
||||
local allow_add_task = config.allow_add_task
|
||||
|
||||
-- Check player has permisison based on value in the config
|
||||
if allow_add_task == "all" then
|
||||
return true
|
||||
elseif allow_add_task == "admin" then
|
||||
return player.admin
|
||||
elseif allow_add_task == "expcore.roles" then
|
||||
return Roles.player_allowed(player, config.expcore_roles_allow_add_task)
|
||||
end
|
||||
|
||||
-- Return false as all other condidtions have not been met
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
--- Elements
|
||||
|
||||
--- Button displayed in the header bar, used to add a new task
|
||||
-- @element add_new_task
|
||||
local add_new_task = Gui.define("add_new_task")
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/add",
|
||||
tooltip = { "task-list.add-tooltip" },
|
||||
style = "tool_button",
|
||||
name = Gui.from_name,
|
||||
}
|
||||
:style(Styles.sprite22)
|
||||
:on_click(
|
||||
function(def, player, element)
|
||||
-- Disable editing
|
||||
PlayerIsEditing:set(player, false)
|
||||
-- Clear selected
|
||||
PlayerSelected:set(player, nil)
|
||||
-- Open task create footer
|
||||
PlayerIsCreating:set(player, true)
|
||||
end
|
||||
)
|
||||
|
||||
--- Header displayed when no tasks are in the task list
|
||||
-- @element no_tasks_found
|
||||
local no_tasks_found = Gui.define("no_tasks_found")
|
||||
:draw(
|
||||
function(_, parent)
|
||||
local header =
|
||||
parent.add{
|
||||
name = "no_tasks_found_element",
|
||||
type = "frame",
|
||||
style = "negative_subheader_frame",
|
||||
}
|
||||
header.style.horizontally_stretchable = true
|
||||
header.style.bottom_margin = 0
|
||||
-- Flow used for centering the content in the subheader
|
||||
local center =
|
||||
header.add{
|
||||
type = "flow",
|
||||
}
|
||||
center.style.vertical_align = "center"
|
||||
center.style.horizontal_align = "center"
|
||||
center.style.horizontally_stretchable = true
|
||||
center.add{
|
||||
name = "header_label",
|
||||
type = "label",
|
||||
style = "bold_label",
|
||||
caption = { "", "[img=utility/warning_white] ", { "task-list.no-tasks" } },
|
||||
tooltip = { "task-list.no-tasks-tooltip" },
|
||||
}
|
||||
return header
|
||||
end
|
||||
)
|
||||
|
||||
--- Frame element with the right styling
|
||||
-- @element subfooter_frame
|
||||
local subfooter_frame = Gui.define("task_list_subfooter_frame")
|
||||
:draw{
|
||||
type = "frame",
|
||||
name = Gui.from_argument(1),
|
||||
direction = "vertical",
|
||||
style = "subfooter_frame",
|
||||
}
|
||||
:style{
|
||||
height = 0,
|
||||
padding = 5,
|
||||
use_header_filler = false,
|
||||
}
|
||||
|
||||
|
||||
--- Label element preset
|
||||
-- @element subfooter_label
|
||||
local subfooter_label = Gui.define("task_list_subfooter_label")
|
||||
:draw{
|
||||
name = "footer_label",
|
||||
type = "label",
|
||||
style = "frame_title",
|
||||
caption = Gui.from_argument(1),
|
||||
}
|
||||
|
||||
--- Action flow that contains action buttons
|
||||
-- @element subfooter_actions
|
||||
local subfooter_actions = Gui.define("task_list_subfooter_actions")
|
||||
:draw{
|
||||
type = "flow",
|
||||
name = "actions",
|
||||
}
|
||||
|
||||
--- Button element with a flow around it to fix duplicate name inside of the scroll flow
|
||||
-- @element task_list_item
|
||||
local task_list_item = Gui.define("task_list_item")
|
||||
:draw(
|
||||
function(def, parent, task)
|
||||
local flow = parent.add{
|
||||
type = "flow",
|
||||
name = "task-" .. task.task_id,
|
||||
caption = task.task_id,
|
||||
}
|
||||
|
||||
flow.style.horizontally_stretchable = true
|
||||
|
||||
local button = flow.add{
|
||||
name = def.name,
|
||||
type = "button",
|
||||
style = "list_box_item",
|
||||
caption = task.title,
|
||||
tooltip = { "task-list.last-edit", task.last_edit_name, format_time(task.last_edit_time) },
|
||||
}
|
||||
|
||||
button.style.horizontally_stretchable = true
|
||||
button.style.horizontally_squashable = true
|
||||
|
||||
return button
|
||||
end
|
||||
)
|
||||
:on_click(
|
||||
function(def, player, element)
|
||||
local task_id = element.parent.caption
|
||||
PlayerSelected:set(player, task_id)
|
||||
end
|
||||
)
|
||||
|
||||
--- Scrollable list of all tasks
|
||||
-- @element task_list
|
||||
local task_list = Gui.define("task_list")
|
||||
:draw(
|
||||
function(_, parent)
|
||||
local scroll_pane =
|
||||
parent.add{
|
||||
name = "scroll",
|
||||
type = "scroll-pane",
|
||||
direction = "vertical",
|
||||
horizontal_scroll_policy = "never",
|
||||
vertical_scroll_policy = "auto",
|
||||
style = "scroll_pane_under_subheader",
|
||||
}
|
||||
scroll_pane.style.horizontally_stretchable = true
|
||||
scroll_pane.style.padding = 0
|
||||
scroll_pane.style.maximal_height = 224
|
||||
|
||||
local flow =
|
||||
scroll_pane.add{
|
||||
name = "task_list",
|
||||
type = "flow",
|
||||
direction = "vertical",
|
||||
}
|
||||
flow.style.vertical_spacing = 0
|
||||
flow.style.horizontally_stretchable = true
|
||||
|
||||
return flow
|
||||
end
|
||||
)
|
||||
|
||||
--- Button element inside the task view footer to start editing a task
|
||||
-- @element task_view_edit_button
|
||||
local task_view_edit_button = Gui.define("task_view_edit_button")
|
||||
:draw{
|
||||
type = "button",
|
||||
name = Gui.from_name,
|
||||
caption = { "", "[img=utility/rename_icon] ", { "task-list.edit" } },
|
||||
tooltip = { "task-list.edit-tooltip" },
|
||||
style = "shortcut_bar_button",
|
||||
}:style(Styles.footer_button):on_click(
|
||||
function(def, player, element)
|
||||
local selected = PlayerSelected:get(player)
|
||||
PlayerIsEditing:set(player, true)
|
||||
|
||||
Tasks.set_editing(selected, player.name, true)
|
||||
end
|
||||
)
|
||||
|
||||
--- Button to close the task view footer
|
||||
-- @element task_view_close_button
|
||||
local task_view_close_button = Gui.define("task_view_close_button")
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/collapse",
|
||||
style = "frame_action_button",
|
||||
tooltip = { "task-list.close-tooltip" },
|
||||
}
|
||||
:style(Styles.sprite22)
|
||||
:on_click(
|
||||
function(def, player, element)
|
||||
PlayerSelected:set(player, nil)
|
||||
end
|
||||
)
|
||||
|
||||
--- Button to delete the task inside the task view footer
|
||||
-- @element task_view_delete_button
|
||||
local task_view_delete_button = Gui.define("task_view_delete_button")
|
||||
:draw{
|
||||
type = "button",
|
||||
name = Gui.from_name,
|
||||
caption = { "", "[img=utility/trash] ", { "task-list.delete" } },
|
||||
tooltip = { "task-list.delete-tooltip" },
|
||||
style = "shortcut_bar_button_red",
|
||||
}
|
||||
:style(Styles.footer_button)
|
||||
:on_click(
|
||||
function(def, player, element)
|
||||
local selected = PlayerSelected:get(player)
|
||||
PlayerSelected:set(player, nil)
|
||||
Tasks.remove_task(selected)
|
||||
end
|
||||
)
|
||||
|
||||
--- Subfooter inside the tasklist container that holds all the elements for viewing a task
|
||||
-- @element task_view_footer
|
||||
local task_view_footer = Gui.define("task_view_footer")
|
||||
:draw(
|
||||
function(_, parent)
|
||||
local footer = subfooter_frame(parent, "view")
|
||||
local flow = footer.add{ type = "flow" }
|
||||
subfooter_label(flow, { "task-list.view-footer-header" })
|
||||
local alignment = Gui.elements.aligned_flow(flow)
|
||||
task_view_close_button(alignment)
|
||||
local title_label =
|
||||
footer.add{
|
||||
type = "label",
|
||||
name = "title",
|
||||
}
|
||||
title_label.style.padding = 4
|
||||
title_label.style.font = "default-bold"
|
||||
title_label.style.single_line = false
|
||||
local body_label =
|
||||
footer.add{
|
||||
type = "label",
|
||||
name = "body",
|
||||
}
|
||||
body_label.style.padding = 4
|
||||
body_label.style.single_line = false
|
||||
|
||||
local action_flow = subfooter_actions(footer)
|
||||
task_view_delete_button(action_flow)
|
||||
task_view_edit_button(action_flow)
|
||||
return footer
|
||||
end
|
||||
)
|
||||
|
||||
local message_pattern = "(.-)\n(.*)"
|
||||
|
||||
--- Parse a string into a message object with title and body
|
||||
-- @tparam string str message data
|
||||
local function parse_message(str)
|
||||
-- Trim the spaces of the string
|
||||
local trimmed = string.gsub(str, "^%s*(.-)%s*$", "%1")
|
||||
local message = { title = "", body = "" }
|
||||
local title, body = string.match(trimmed, message_pattern)
|
||||
if not title then
|
||||
-- If it doesn't match the pattern return the str as a title
|
||||
message.title = trimmed
|
||||
else
|
||||
message.title = title
|
||||
message.body = body
|
||||
end
|
||||
return message
|
||||
end
|
||||
|
||||
-- Button variable initialisation because it is used inside the textfield element events
|
||||
local task_edit_confirm_button
|
||||
local task_create_confirm_button
|
||||
|
||||
--- Textfield element used in both the task create and edit footers
|
||||
-- @element task_message_textfield
|
||||
local task_message_textfield = Gui.define("task_message_textfield")
|
||||
:draw{
|
||||
name = Gui.from_name,
|
||||
type = "text-box",
|
||||
text = "",
|
||||
}:style{
|
||||
maximal_width = 268,
|
||||
minimal_height = 100,
|
||||
horizontally_stretchable = true,
|
||||
}
|
||||
:on_text_changed(
|
||||
function(def, player, element)
|
||||
local is_editing = PlayerIsEditing:get(player)
|
||||
local is_creating = PlayerIsCreating:get(player)
|
||||
|
||||
local valid = string.len(element.text) > 5
|
||||
|
||||
if is_creating then
|
||||
element.parent.actions[task_create_confirm_button.name].enabled = valid
|
||||
elseif is_editing then
|
||||
element.parent.actions[task_edit_confirm_button.name].enabled = valid
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
--- Button to confirm the changes inside the task edit footer
|
||||
-- @element task_edit_confirm_button
|
||||
task_edit_confirm_button = Gui.define("task_edit_confirm_button")
|
||||
:draw{
|
||||
type = "button",
|
||||
name = Gui.from_name,
|
||||
caption = { "", "[img=utility/check_mark] ", { "task-list.confirm" } },
|
||||
tooltip = { "task-list.confirm-tooltip" },
|
||||
style = "shortcut_bar_button_green",
|
||||
}
|
||||
:style(Styles.footer_button)
|
||||
:on_click(
|
||||
function(def, player, element)
|
||||
local selected = PlayerSelected:get(player)
|
||||
PlayerIsEditing:set(player, false)
|
||||
local new_message = element.parent.parent[task_message_textfield.name].text
|
||||
local parsed = parse_message(new_message)
|
||||
Tasks.update_task(selected, player.name, parsed.title, parsed.body)
|
||||
Tasks.set_editing(selected, player.name, nil)
|
||||
end
|
||||
)
|
||||
|
||||
--- Button to discard the changes inside the task edit footer
|
||||
-- @element edit_task_discard_button
|
||||
local edit_task_discard_button = Gui.define("edit_task_discard_button")
|
||||
:draw{
|
||||
type = "button",
|
||||
caption = { "", "[img=utility/close_black] ", { "task-list.discard" } },
|
||||
tooltip = { "task-list.discard-tooltip" },
|
||||
style = "shortcut_bar_button_red",
|
||||
}
|
||||
:style(Styles.footer_button)
|
||||
:on_click(
|
||||
function(def, player, element)
|
||||
local selected = PlayerSelected:get(player)
|
||||
Tasks.set_editing(selected, player.name, nil)
|
||||
PlayerIsEditing:set(player, false)
|
||||
end
|
||||
)
|
||||
|
||||
--- Subfooter inside the tasklist container that holds all the elements for editing a task
|
||||
-- @element task_edit_footer
|
||||
local task_edit_footer = Gui.define("task_edit_footer")
|
||||
:draw(
|
||||
function(_, parent)
|
||||
local footer = subfooter_frame(parent, "edit")
|
||||
subfooter_label(footer, { "task-list.edit-footer-header" })
|
||||
|
||||
task_message_textfield(footer)
|
||||
|
||||
local action_flow = subfooter_actions(footer)
|
||||
|
||||
edit_task_discard_button(action_flow)
|
||||
task_edit_confirm_button(action_flow)
|
||||
|
||||
return footer
|
||||
end
|
||||
)
|
||||
|
||||
--- Button to confirm the changes inside the task create footer
|
||||
-- @element task_create_confirm_button
|
||||
task_create_confirm_button = Gui.define("task_create_confirm_button")
|
||||
:draw{
|
||||
type = "button",
|
||||
name = Gui.from_name,
|
||||
caption = { "", "[img=utility/check_mark] ", { "task-list.confirm" } },
|
||||
tooltip = { "task-list.confirm-tooltip" },
|
||||
style = "shortcut_bar_button_green",
|
||||
enabled = false,
|
||||
}
|
||||
:style(Styles.footer_button)
|
||||
:on_click(
|
||||
function(def, player, element)
|
||||
local message = element.parent.parent[task_message_textfield.name].text
|
||||
PlayerIsCreating:set(player, false)
|
||||
local parsed = parse_message(message)
|
||||
local task_id = Tasks.add_task(player.force.name, player.name, parsed.title, parsed.body)
|
||||
PlayerSelected:set(player, task_id)
|
||||
end
|
||||
)
|
||||
|
||||
--- Button to discard the changes inside the task create footer
|
||||
-- @element task_create_discard_button
|
||||
local task_create_discard_button = Gui.define("task_create_discard_button")
|
||||
:draw{
|
||||
type = "button",
|
||||
caption = { "", "[img=utility/close_black] ", { "task-list.discard" } },
|
||||
tooltip = { "task-list.discard-tooltip" },
|
||||
style = "shortcut_bar_button_red",
|
||||
}
|
||||
:style(Styles.footer_button)
|
||||
:on_click(
|
||||
function(def, player, element)
|
||||
PlayerIsCreating:set(player, false)
|
||||
end
|
||||
)
|
||||
|
||||
--- Subfooter inside the tasklist container that holds all the elements to create a new task
|
||||
-- @element task_create_footer
|
||||
local task_create_footer = Gui.define("task_create_footer")
|
||||
:draw(
|
||||
function(_, parent)
|
||||
local footer = subfooter_frame(parent, "create")
|
||||
subfooter_label(footer, { "task-list.create-footer-header" })
|
||||
|
||||
task_message_textfield(footer)
|
||||
|
||||
local action_flow = subfooter_actions(footer)
|
||||
|
||||
task_create_discard_button(action_flow)
|
||||
task_create_confirm_button(action_flow)
|
||||
|
||||
return footer
|
||||
end
|
||||
)
|
||||
|
||||
--- Clear and repopulate the task list with all current tasks
|
||||
local repopulate_task_list = function(task_list_element)
|
||||
local force = Gui.get_player(task_list_element).force
|
||||
local task_ids = Tasks.get_force_task_ids(force.name)
|
||||
task_list_element.clear()
|
||||
|
||||
-- Set visibility of the no_tasks_found element depending on the amount of tasks still in the task manager
|
||||
task_list_element.parent.parent.no_tasks_found_element.visible = #task_ids == 0
|
||||
|
||||
-- Add each task to the flow
|
||||
for _, task_id in ipairs(task_ids) do
|
||||
-- Add the task
|
||||
local task = Tasks.get_task(task_id)
|
||||
task_list_item(task_list_element, task)
|
||||
end
|
||||
end
|
||||
|
||||
--- Main task list container for the left flow
|
||||
-- @element task_list_container
|
||||
local task_list_container = Gui.define("task_list_container")
|
||||
:draw(
|
||||
function(def, parent)
|
||||
-- Draw the internal container
|
||||
local container = Gui.elements.container(parent, 268)
|
||||
container.style.maximal_width = 268
|
||||
|
||||
-- Draw the header
|
||||
local header = Gui.elements.header(container, {
|
||||
name = "header",
|
||||
caption = { "task-list.main-caption" },
|
||||
tooltip = { "task-list.sub-tooltip" },
|
||||
})
|
||||
|
||||
-- Draw the new task button
|
||||
local player = Gui.get_player(parent)
|
||||
local add_new_task_element = add_new_task(header)
|
||||
add_new_task_element.visible = check_player_permissions(player)
|
||||
|
||||
-- Draw no task found element
|
||||
no_tasks_found(container)
|
||||
|
||||
-- Draw task list element
|
||||
local task_list_element = task_list(container)
|
||||
repopulate_task_list(task_list_element)
|
||||
|
||||
local task_view_footer_element = task_view_footer(container)
|
||||
local task_edit_footer_element = task_edit_footer(container)
|
||||
local task_create_footer_element = task_create_footer(container)
|
||||
task_view_footer_element.visible = false
|
||||
task_edit_footer_element.visible = false
|
||||
task_create_footer_element.visible = false
|
||||
-- Return the external container
|
||||
return container.parent
|
||||
end
|
||||
)
|
||||
|
||||
--- Add the element to the left flow with a toolbar button
|
||||
Gui.add_left_element(task_list_container, function(player)
|
||||
local task_ids = Tasks.get_force_task_ids(player.force.name)
|
||||
return #task_ids > 0
|
||||
end)
|
||||
Gui.toolbar.create_button{
|
||||
name = "task_list_toggle",
|
||||
left_element = task_list_container,
|
||||
sprite = "utility/not_enough_repair_packs_icon",
|
||||
tooltip = { "task-list.main-tooltip" },
|
||||
visible = function(player, element)
|
||||
return Roles.player_allowed(player, "gui/task-list")
|
||||
end
|
||||
}
|
||||
|
||||
-- Function to update a single task and some of the elements inside the container
|
||||
local update_task = function(player, task_list_element, task_id)
|
||||
local task = Tasks.get_task(task_id)
|
||||
local task_ids = Tasks.get_force_task_ids(player.force.name)
|
||||
-- Set visibility of the no_tasks_found element depending on the amount of tasks still in the task manager
|
||||
task_list_element.parent.parent.no_tasks_found_element.visible = #task_ids == 0
|
||||
|
||||
-- Task no longer exists so should be removed from the list
|
||||
if not task then
|
||||
task_list_element["task-" .. task_id].destroy()
|
||||
return
|
||||
end
|
||||
|
||||
local flow = task_list_element["task-" .. task_id]
|
||||
if not flow then
|
||||
-- If task does not exist yet add it to the list
|
||||
task_list_item(task_list_element, task)
|
||||
else
|
||||
-- If the task exists update the caption and tooltip
|
||||
local button = flow[task_list_item.name]
|
||||
button.caption = task.title
|
||||
button.tooltip = { "task-list.last-edit", task.last_edit_name, format_time(task.last_edit_time) }
|
||||
end
|
||||
end
|
||||
|
||||
-- Update the footer task edit view
|
||||
local update_task_edit_footer = function(player, task_id)
|
||||
local task = Tasks.get_task(task_id)
|
||||
local container = Gui.get_left_element(task_list_container, player)
|
||||
local edit_flow = container.frame.edit
|
||||
|
||||
local message_element = edit_flow[task_message_textfield.name]
|
||||
|
||||
message_element.focus()
|
||||
message_element.text = task.title .. "\n" .. task.body
|
||||
end
|
||||
|
||||
-- Update the footer task view
|
||||
local update_task_view_footer = function(player, task_id)
|
||||
local task = Tasks.get_task(task_id)
|
||||
local container = Gui.get_left_element(task_list_container, player)
|
||||
local view_flow = container.frame.view
|
||||
local has_permission = check_player_permissions(player, task)
|
||||
|
||||
local title_element = view_flow.title
|
||||
local body_element = view_flow.body
|
||||
local edit_button_element = view_flow.actions[task_view_edit_button.name]
|
||||
local delete_button_element = view_flow.actions[task_view_delete_button.name]
|
||||
|
||||
edit_button_element.visible = has_permission
|
||||
delete_button_element.visible = has_permission
|
||||
title_element.caption = task.title
|
||||
body_element.caption = task.body
|
||||
|
||||
local players_editing = table.get_keys(task.currently_editing)
|
||||
if #players_editing > 0 then
|
||||
edit_button_element.tooltip = { "task-list.edit-tooltip", table.concat(players_editing, ", ") }
|
||||
else
|
||||
edit_button_element.tooltip = { "task-list.edit-tooltip-none" }
|
||||
end
|
||||
end
|
||||
|
||||
--- When a new task is added it will update the task list for everyone on that force
|
||||
--- Or when a task is updated it will update the specific task elements
|
||||
Tasks.on_update(
|
||||
function(task_id, curr_state, prev_state)
|
||||
-- Get the force to update, task is nil when removed
|
||||
local force
|
||||
if curr_state then
|
||||
force = game.forces[curr_state.force_name]
|
||||
else
|
||||
force = game.forces[prev_state.force_name]
|
||||
end
|
||||
|
||||
-- Update the task for all the players on the force
|
||||
for _, player in pairs(force.connected_players) do
|
||||
-- Update the task view elements if the player currently being looped over has this specific task selected
|
||||
local selected = PlayerSelected:get(player)
|
||||
if selected == task_id then
|
||||
if curr_state then
|
||||
update_task_view_footer(player, selected)
|
||||
else
|
||||
PlayerSelected:set(player, nil)
|
||||
end
|
||||
end
|
||||
|
||||
local container = Gui.get_left_element(task_list_container, player)
|
||||
local task_list_element = container.frame.scroll.task_list
|
||||
|
||||
-- Update the task that was changed
|
||||
update_task(player, task_list_element, task_id)
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
-- When a player is creating a new task.
|
||||
PlayerIsCreating:on_update(
|
||||
function(player_name, curr_state, _)
|
||||
local player = game.players[player_name]
|
||||
|
||||
local container = Gui.get_left_element(task_list_container, player)
|
||||
local create = container.frame.create
|
||||
|
||||
-- Clear the textfield
|
||||
local message_element = container.frame.create[task_message_textfield.name]
|
||||
local confirm_button_element = container.frame.create.actions[task_create_confirm_button.name]
|
||||
message_element.focus()
|
||||
message_element.text = ""
|
||||
confirm_button_element.enabled = false
|
||||
|
||||
if curr_state then
|
||||
create.visible = true
|
||||
else
|
||||
create.visible = false
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
-- When a player selects a different warp from the list
|
||||
PlayerSelected:on_update(
|
||||
function(player_name, curr_state, prev_state)
|
||||
local player = game.players[player_name]
|
||||
|
||||
local container = Gui.get_left_element(task_list_container, player)
|
||||
local task_list_element = container.frame.scroll.task_list
|
||||
local view_flow = container.frame.view
|
||||
local edit_flow = container.frame.edit
|
||||
local is_editing = PlayerIsEditing:get(player)
|
||||
local is_creating = PlayerIsCreating:get(player)
|
||||
|
||||
-- If the selection has an previous state re-enable the button list element
|
||||
if prev_state then
|
||||
task_list_element["task-" .. prev_state][task_list_item.name].enabled = true
|
||||
end
|
||||
|
||||
if curr_state then
|
||||
-- Disable the selected element
|
||||
task_list_element["task-" .. curr_state][task_list_item.name].enabled = false
|
||||
|
||||
-- Update the view footer
|
||||
update_task_view_footer(player, curr_state)
|
||||
|
||||
-- If a player is creating then remove the creation dialogue
|
||||
if is_creating then
|
||||
PlayerIsCreating:set(player, false)
|
||||
end
|
||||
|
||||
-- Depending on if the player is currently editing change the current task edit footer to the current task
|
||||
if is_editing then
|
||||
update_task_edit_footer(player, curr_state)
|
||||
Tasks.set_editing(prev_state, player.name, nil)
|
||||
Tasks.set_editing(curr_state, player.name, true)
|
||||
view_flow.visible = false
|
||||
edit_flow.visible = true
|
||||
else
|
||||
view_flow.visible = true
|
||||
edit_flow.visible = false
|
||||
end
|
||||
else
|
||||
-- If curr_state nil then hide footer elements and set editing to nil for prev_state
|
||||
if prev_state and Tasks.get_task(prev_state) then
|
||||
Tasks.set_editing(prev_state, player.name, nil)
|
||||
end
|
||||
view_flow.visible = false
|
||||
edit_flow.visible = false
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
-- When the edit view opens or closes
|
||||
PlayerIsEditing:on_update(
|
||||
function(player_name, curr_state, _)
|
||||
local player = game.players[player_name]
|
||||
|
||||
local container = Gui.get_left_element(task_list_container, player)
|
||||
local view_flow = container.frame.view
|
||||
local edit_flow = container.frame.edit
|
||||
|
||||
local selected = PlayerSelected:get(player)
|
||||
if curr_state then
|
||||
update_task_edit_footer(player, selected)
|
||||
view_flow.visible = false
|
||||
edit_flow.visible = true
|
||||
else
|
||||
view_flow.visible = true
|
||||
edit_flow.visible = false
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
--- Makes sure the right buttons are present when roles change
|
||||
local function role_update_event(event)
|
||||
local player = game.players[event.player_index]
|
||||
local frame = Gui.get_left_element(task_list_container, player).frame
|
||||
-- Update the view task
|
||||
local selected = PlayerSelected:get(player)
|
||||
if selected then
|
||||
update_task_view_footer(player, selected)
|
||||
PlayerSelected:set(player, selected)
|
||||
-- button to edit the task.
|
||||
-- Resetting the players selected task to make sure the player does not see an
|
||||
end
|
||||
|
||||
-- Update the new task button and create footer in case the user can now add them
|
||||
local has_permission = check_player_permissions(player)
|
||||
local add_new_task_element = frame.header[add_new_task.name]
|
||||
add_new_task_element.visible = has_permission
|
||||
local is_creating = PlayerIsCreating:get(player)
|
||||
if is_creating and not has_permission then
|
||||
PlayerIsCreating:set(player, false)
|
||||
end
|
||||
end
|
||||
|
||||
Event.add(Roles.events.on_role_assigned, role_update_event)
|
||||
Event.add(Roles.events.on_role_unassigned, role_update_event)
|
||||
|
||||
--- Redraw all tasks and clear editing/creating after joining or changing force
|
||||
local function reset_task_list(event)
|
||||
-- Repopulate the task list
|
||||
local player = game.players[event.player_index]
|
||||
local container = Gui.get_left_element(task_list_container, player)
|
||||
local task_list_element = container.frame.scroll.task_list
|
||||
repopulate_task_list(task_list_element)
|
||||
|
||||
-- Check if the selected task is still valid
|
||||
local selected = PlayerSelected:get(player)
|
||||
if selected and Tasks.get_task(selected) ~= nil then
|
||||
PlayerIsCreating:set(player, false)
|
||||
PlayerIsEditing:set(player, false)
|
||||
PlayerSelected:set(player, nil)
|
||||
end
|
||||
end
|
||||
|
||||
Event.add(defines.events.on_player_joined_game, reset_task_list)
|
||||
Event.add(defines.events.on_player_changed_force, reset_task_list)
|
||||
@@ -79,3 +79,4 @@ add(require("modules/exp_scenario/gui/quick_actions"))
|
||||
add(require("modules/exp_scenario/gui/research_milestones"))
|
||||
add(require("modules/exp_scenario/gui/science_production"))
|
||||
add(require("modules/exp_scenario/gui/surveillance"))
|
||||
add(require("modules/exp_scenario/gui/task_list"))
|
||||
|
||||
951
exp_scenario/module/gui/task_list.lua
Normal file
951
exp_scenario/module/gui/task_list.lua
Normal file
@@ -0,0 +1,951 @@
|
||||
--[[-- Gui - Task List
|
||||
Adds a task list to the game which players can add, remove and edit items on
|
||||
]]
|
||||
|
||||
local Gui = require("modules/exp_gui")
|
||||
local Roles = require("modules.exp_legacy.expcore.roles")
|
||||
local config = require("modules.exp_legacy.config.gui.tasks")
|
||||
|
||||
local ExpUtil = require("modules/exp_util")
|
||||
local format_time = ExpUtil.format_time_factory_locale{ format = "short", hours = true, minutes = true }
|
||||
|
||||
--- @class ExpGui_TaskList.elements
|
||||
local Elements = {}
|
||||
|
||||
local Styles = {
|
||||
sprite22 = Gui.styles.sprite{
|
||||
size = 22
|
||||
},
|
||||
footer_button = Gui.styles.sprite{
|
||||
height = 29,
|
||||
maximal_width = 268,
|
||||
horizontally_stretchable = true,
|
||||
},
|
||||
}
|
||||
|
||||
--- @class ExpGui_TaskList.Task
|
||||
--- @field id number
|
||||
--- @field last_user LuaPlayer
|
||||
--- @field last_edit_tick number
|
||||
--- @field editing table<number, string>
|
||||
--- @field title string
|
||||
--- @field body string
|
||||
--- @field new boolean?
|
||||
--- @field deleted boolean?
|
||||
|
||||
--- Check if a player can create a new task
|
||||
--- @param player LuaPlayer
|
||||
--- @return boolean
|
||||
local function has_permission_create_task(player)
|
||||
local allow_add_task = config.allow_add_task
|
||||
|
||||
if allow_add_task == "all" then
|
||||
return true
|
||||
elseif allow_add_task == "admin" then
|
||||
return player.admin
|
||||
elseif allow_add_task == "expcore.roles" then
|
||||
return Roles.player_allowed(player, config.expcore_roles_allow_add_task)
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
--- Check if a player can edit an existing task
|
||||
--- @param player LuaPlayer
|
||||
--- @param task ExpGui_TaskList.Task
|
||||
--- @return boolean
|
||||
local function has_permission_edit_task(player, task)
|
||||
local allow_edit_task = config.allow_edit_task
|
||||
|
||||
-- Check if editing your own task allows bypassing other permissions
|
||||
if config.user_can_edit_own_tasks and task.last_user.index == player.index then
|
||||
return true
|
||||
end
|
||||
|
||||
-- Check player has permission based on value in the config
|
||||
if allow_edit_task == "all" then
|
||||
return true
|
||||
elseif allow_edit_task == "admin" then
|
||||
return player.admin
|
||||
elseif allow_edit_task == "expcore.roles" then
|
||||
return Roles.player_allowed(player, config.expcore_roles_allow_edit_task)
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
--- @class ExpGui_TaskList.element.new_task_button.elements
|
||||
--- @field container LuaGuiElement
|
||||
|
||||
--- Button displayed in the header bar, used to add a new task
|
||||
--- @class ExpGui_TaskList.element.new_task_button: ExpElement
|
||||
--- @field data table<LuaGuiElement, ExpGui_TaskList.element.new_task_button.elements>
|
||||
--- @overload fun(parent: LuaGuiElement, container: LuaGuiElement): LuaGuiElement
|
||||
Elements.new_task_button = Gui.define("task_list/new_task_button")
|
||||
:track_all_elements()
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/add",
|
||||
tooltip = { "exp-gui_task-list.tooltip-new" },
|
||||
style = "tool_button",
|
||||
}
|
||||
:style(Styles.sprite22)
|
||||
:element_data{
|
||||
container = Gui.from_argument(1)
|
||||
}
|
||||
:on_click(function(def, player, new_task_button)
|
||||
--- @cast def ExpGui_TaskList.element.new_task_button
|
||||
local container = def.data[new_task_button].container
|
||||
Elements.container.open_edit_task(container, {
|
||||
id = Elements.container.next_task_id(),
|
||||
last_edit_tick = game.tick,
|
||||
last_user = player,
|
||||
editing = {},
|
||||
title = "",
|
||||
body = "",
|
||||
new = true,
|
||||
})
|
||||
end) --[[ @as any ]]
|
||||
|
||||
--- Refresh the visibility based on player permissions
|
||||
--- @param new_task_button LuaGuiElement
|
||||
function Elements.new_task_button.refresh(new_task_button)
|
||||
local player = Gui.get_player(new_task_button)
|
||||
new_task_button.visible = has_permission_create_task(player)
|
||||
end
|
||||
|
||||
--- Refresh the visibility based on player permissions
|
||||
--- @param player LuaPlayer
|
||||
function Elements.new_task_button.refresh_player(player)
|
||||
local visible = has_permission_create_task(player)
|
||||
for _, new_task_button in Elements.new_task_button:tracked_elements(player) do
|
||||
new_task_button.visible = visible
|
||||
end
|
||||
end
|
||||
|
||||
--- @class ExpGui_TaskList.elements.view_task_button.elements
|
||||
--- @field task ExpGui_TaskList.Task
|
||||
--- @field container LuaGuiElement
|
||||
|
||||
--- Button used to view a task details, the caption is the task title
|
||||
--- @class ExpGui_TaskList.element.view_task_button: ExpElement
|
||||
--- @field data table<LuaGuiElement, ExpGui_TaskList.elements.view_task_button.elements>
|
||||
--- @overload fun(parent: LuaGuiElement, task: ExpGui_TaskList.Task, container: LuaGuiElement): LuaGuiElement
|
||||
Elements.view_task_button = Gui.define("task_list/view_task_button")
|
||||
:draw(function(def, parent, task)
|
||||
--- @cast def ExpGui_TaskList.element.view_task_button
|
||||
--- @cast task ExpGui_TaskList.Task
|
||||
return parent.add{
|
||||
type = "button",
|
||||
style = "list_box_item",
|
||||
caption = task.title,
|
||||
tooltip = { "exp-gui_task-list.tooltip-last-edit", task.last_user.name, format_time(task.last_edit_tick) },
|
||||
}
|
||||
end)
|
||||
:style{
|
||||
width = 268,
|
||||
horizontally_stretchable = true,
|
||||
}
|
||||
:element_data{
|
||||
task = Gui.from_argument(1),
|
||||
container = Gui.from_argument(2),
|
||||
}
|
||||
:on_click(function(def, player, view_task_button)
|
||||
--- @cast def ExpGui_TaskList.element.view_task_button
|
||||
local elements = def.data[view_task_button]
|
||||
Elements.container.open_view_task(elements.container, elements.task)
|
||||
end) --[[ @as any ]]
|
||||
|
||||
--- Refresh the title and tooltip of the view task button
|
||||
--- @param view_task_button LuaGuiElement
|
||||
--- @param task ExpGui_TaskList.Task
|
||||
function Elements.view_task_button.refresh(view_task_button, task)
|
||||
view_task_button.caption = task.title
|
||||
view_task_button.tooltip = { "exp-gui_task-list.tooltip-last-edit", task.last_user.name, format_time(task.last_edit_tick) }
|
||||
end
|
||||
|
||||
--- Label used to signal that no tasks are open
|
||||
--- @class ExpGui_TaskList.elements.no_tasks_header: ExpElement
|
||||
--- @overload fun(parent: LuaGuiElement): LuaGuiElement
|
||||
Elements.no_tasks_header = Gui.define("task_list/no_tasks_header")
|
||||
:track_all_elements()
|
||||
:draw(function(def, parent, ...)
|
||||
local subheader = Gui.elements.subframe_base(parent, "negative_subheader_frame")
|
||||
|
||||
local label = subheader.add{
|
||||
type = "label",
|
||||
style = "bold_label",
|
||||
caption = { "exp-gui_task-list.caption-no-tasks" },
|
||||
tooltip = { "exp-gui_task-list.tooltip-no-tasks" },
|
||||
}
|
||||
|
||||
label.style.width = 268
|
||||
label.style.horizontal_align = "center"
|
||||
|
||||
return subheader
|
||||
end)
|
||||
:style{
|
||||
padding = { 2, 0 },
|
||||
bottom_margin = 0,
|
||||
} --[[ @as any ]]
|
||||
|
||||
--- Refresh the visibility of the no tasks label
|
||||
--- @param no_tasks_header LuaGuiElement
|
||||
function Elements.no_tasks_header.refresh(no_tasks_header)
|
||||
local force = Gui.get_player(no_tasks_header).force --[[ @as LuaForce ]]
|
||||
no_tasks_header.visible = not Elements.container.has_tasks(force)
|
||||
end
|
||||
|
||||
--- Refresh the visibility of the no tasks label
|
||||
--- @param player LuaPlayer
|
||||
function Elements.no_tasks_header.refresh_player(player)
|
||||
local visible = not Elements.container.has_tasks(player.force --[[ @as LuaForce ]])
|
||||
for _, no_tasks_header in Elements.no_tasks_header:tracked_elements(player) do
|
||||
no_tasks_header.visible = visible
|
||||
end
|
||||
end
|
||||
|
||||
--- Refresh the visibility of the no tasks label
|
||||
--- @param force LuaForce
|
||||
function Elements.no_tasks_header.refresh_force_online(force)
|
||||
local visible = not Elements.container.has_tasks(force)
|
||||
for _, no_tasks_header in Elements.no_tasks_header:online_elements(force) do
|
||||
no_tasks_header.visible = visible
|
||||
end
|
||||
end
|
||||
|
||||
--- A table containing all of the current tasks
|
||||
--- @class ExpGui_TaskList.elements.task_table: ExpElement
|
||||
--- @field data table<LuaGuiElement, LuaGuiElement[]>
|
||||
--- @overload fun(parent: LuaGuiElement): LuaGuiElement
|
||||
Elements.task_list = Gui.define("task_list/task_list")
|
||||
:draw(function(_, parent)
|
||||
local task_list = parent.add{
|
||||
type = "scroll-pane",
|
||||
vertical_scroll_policy = "auto",
|
||||
horizontal_scroll_policy = "never",
|
||||
style = "scroll_pane_under_subheader",
|
||||
}
|
||||
|
||||
local task_list_style = task_list.style
|
||||
task_list_style.horizontally_stretchable = true
|
||||
task_list_style.maximal_height = 224
|
||||
task_list_style.padding = 0
|
||||
|
||||
-- Cant modify vertical spacing on scroll pane style so need a sub flow
|
||||
task_list = task_list.add{ type = "flow", direction = "vertical" }
|
||||
|
||||
task_list_style = task_list.style
|
||||
task_list_style.horizontally_stretchable = true
|
||||
task_list_style.vertical_spacing = 0
|
||||
task_list_style.padding = 0
|
||||
|
||||
-- Add the no tasks header
|
||||
local no_tasks_header = Elements.no_tasks_header(task_list)
|
||||
Elements.no_tasks_header.refresh(no_tasks_header)
|
||||
|
||||
return task_list
|
||||
end)
|
||||
:element_data{} --[[ @as any ]]
|
||||
|
||||
--- Adds a task to the task list
|
||||
--- @param task_list LuaGuiElement
|
||||
--- @param task ExpGui_TaskList.Task
|
||||
function Elements.task_list.add_task(task_list, task)
|
||||
local container = assert(task_list.parent.parent.parent)
|
||||
local view_task_buttons = Elements.task_list.data[task_list]
|
||||
view_task_buttons[task.id] = Elements.view_task_button(task_list, task, container)
|
||||
end
|
||||
|
||||
--- Remove a task from the task list
|
||||
--- @param task_list LuaGuiElement
|
||||
--- @param task ExpGui_TaskList.Task
|
||||
function Elements.task_list.remove_task(task_list, task)
|
||||
local view_task_buttons = Elements.task_list.data[task_list]
|
||||
Gui.destroy_if_valid(view_task_buttons[task.id])
|
||||
view_task_buttons[task.id] = nil
|
||||
end
|
||||
|
||||
--- Refresh a task on the list
|
||||
--- @param task_list LuaGuiElement
|
||||
--- @param task ExpGui_TaskList.Task
|
||||
function Elements.task_list.refresh_task(task_list, task)
|
||||
local view_task_buttons = Elements.task_list.data[task_list]
|
||||
Elements.view_task_button.refresh(view_task_buttons[task.id], task)
|
||||
end
|
||||
|
||||
--- Refresh all tasks on the list
|
||||
--- @param task_list LuaGuiElement
|
||||
--- @param tasks ExpGui_TaskList.Task[]
|
||||
function Elements.task_list.refresh_tasks(task_list, tasks)
|
||||
local view_task_buttons = Elements.task_list.data[task_list]
|
||||
local done = {}
|
||||
|
||||
-- Refresh all valid tasks
|
||||
for _, task in ipairs(tasks) do
|
||||
done[task.id] = true
|
||||
local view_task_button = view_task_buttons[task.id]
|
||||
if view_task_button then
|
||||
Elements.view_task_button.refresh(view_task_button, task)
|
||||
else
|
||||
Elements.task_list.add_task(task_list, task)
|
||||
end
|
||||
end
|
||||
|
||||
-- Remove tasks buttons that are no longer required
|
||||
for id, view_task_button in pairs(view_task_buttons) do
|
||||
if not done[id] then
|
||||
view_task_button.destroy()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Select a task button, if nil then all buttons are reset
|
||||
--- @param task_list LuaGuiElement
|
||||
--- @param task ExpGui_TaskList.Task?
|
||||
function Elements.task_list.select_task_button(task_list, task)
|
||||
local view_task_buttons = Elements.task_list.data[task_list]
|
||||
local task_button = task and view_task_buttons[task.id]
|
||||
if task_button and not task_button.enabled then
|
||||
return
|
||||
end
|
||||
for _, view_task_button in pairs(view_task_buttons) do
|
||||
view_task_button.enabled = true
|
||||
end
|
||||
if task_button then
|
||||
task_button.enabled = false
|
||||
end
|
||||
end
|
||||
|
||||
--- The base footer used for view and edit
|
||||
--- @class ExpGui_TaskList.elements.task_footer: ExpElement
|
||||
--- @overload fun(parent: LuaGuiElement): LuaGuiElement
|
||||
Elements.task_footer = Gui.define("task_list/task_footer")
|
||||
:draw{
|
||||
type = "frame",
|
||||
direction = "vertical",
|
||||
style = "subfooter_frame",
|
||||
}
|
||||
:style{
|
||||
height = 0,
|
||||
padding = 5,
|
||||
use_header_filler = false,
|
||||
} --[[ @as any ]]
|
||||
|
||||
--- @class ExpGui_TaskList.elements.close_task_button.elements
|
||||
--- @field container LuaGuiElement
|
||||
|
||||
--- Button used to close an open task details
|
||||
--- @class ExpGui_TaskList.element.close_task_button: ExpElement
|
||||
--- @field data table<LuaGuiElement, ExpGui_TaskList.elements.close_task_button.elements>
|
||||
--- @overload fun(parent: LuaGuiElement, container: LuaGuiElement): LuaGuiElement
|
||||
Elements.close_task_button = Gui.define("task_list/close_task_button")
|
||||
:draw{
|
||||
type = "sprite-button",
|
||||
sprite = "utility/collapse",
|
||||
style = "frame_action_button",
|
||||
tooltip = { "exp-gui_task-list.tooltip-close" },
|
||||
}
|
||||
:style(Styles.sprite22)
|
||||
:element_data{
|
||||
container = Gui.from_argument(1),
|
||||
}
|
||||
:on_click(function(def, player, close_task_button)
|
||||
--- @cast def ExpGui_TaskList.element.close_task_button
|
||||
local elements = def.data[close_task_button]
|
||||
Elements.container.close_footers(elements.container)
|
||||
end) --[[ @as any ]]
|
||||
|
||||
--- @class ExpGui_TaskList.elements.task_button.elements
|
||||
--- @field task ExpGui_TaskList.Task?
|
||||
--- @field container LuaGuiElement
|
||||
|
||||
--- Button used to edit a task
|
||||
--- @class ExpGui_TaskList.element.edit_task_button: ExpElement
|
||||
--- @field data table<LuaGuiElement, ExpGui_TaskList.elements.task_button.elements>
|
||||
--- @overload fun(parent: LuaGuiElement, container: LuaGuiElement): LuaGuiElement
|
||||
Elements.edit_task_button = Gui.define("task_list/edit_task_button")
|
||||
:draw{
|
||||
type = "button",
|
||||
caption = { "exp-gui_task-list.caption-edit" },
|
||||
tooltip = { "exp-gui_task-list.tooltip-edit" },
|
||||
style = "shortcut_bar_button",
|
||||
}
|
||||
:style(Styles.footer_button)
|
||||
:element_data{
|
||||
container = Gui.from_argument(1),
|
||||
}
|
||||
:on_click(function(def, player, edit_task_button)
|
||||
--- @cast def ExpGui_TaskList.element.edit_task_button
|
||||
local elements = def.data[edit_task_button]
|
||||
Elements.container.open_edit_task(elements.container, assert(elements.task))
|
||||
end) --[[ @as any ]]
|
||||
|
||||
--- Refresh the edit button
|
||||
--- @param edit_task_button LuaGuiElement
|
||||
--- @param task ExpGui_TaskList.Task
|
||||
function Elements.edit_task_button.refresh(edit_task_button, task)
|
||||
local player = Gui.get_player(edit_task_button)
|
||||
Elements.edit_task_button.data[edit_task_button].task = task
|
||||
edit_task_button.visible = has_permission_edit_task(player, task)
|
||||
|
||||
if next(task.editing) then
|
||||
local player_names = table.get_values(task.editing)
|
||||
edit_task_button.tooltip = { "exp-gui_task-list.tooltip-edit", table.concat(player_names, ", ") }
|
||||
else
|
||||
edit_task_button.tooltip = { "exp-gui_task-list.tooltip-edit-none" }
|
||||
end
|
||||
end
|
||||
|
||||
--- Button used to delete a task
|
||||
--- @class ExpGui_TaskList.element.delete_task_button: ExpElement
|
||||
--- @field data table<LuaGuiElement, ExpGui_TaskList.elements.task_button.elements>
|
||||
--- @overload fun(parent: LuaGuiElement, container: LuaGuiElement): LuaGuiElement
|
||||
Elements.delete_task_button = Gui.define("task_list/delete_task_button")
|
||||
:draw{
|
||||
type = "button",
|
||||
caption = { "exp-gui_task-list.caption-delete" },
|
||||
tooltip = { "exp-gui_task-list.tooltip-delete" },
|
||||
style = "shortcut_bar_button_red",
|
||||
}
|
||||
:style(Styles.footer_button)
|
||||
:element_data{
|
||||
container = Gui.from_argument(1),
|
||||
}
|
||||
:on_click(function(def, player, delete_task_button)
|
||||
--- @cast def ExpGui_TaskList.element.delete_task_button
|
||||
local elements = def.data[delete_task_button]
|
||||
Elements.container.remove_task(player.force --[[ @as LuaForce ]], elements.task)
|
||||
Elements.container.close_footers(elements.container)
|
||||
end) --[[ @as any ]]
|
||||
|
||||
--- Refresh the delete button
|
||||
--- @param delete_task_button LuaGuiElement
|
||||
--- @param task ExpGui_TaskList.Task
|
||||
function Elements.delete_task_button.refresh(delete_task_button, task)
|
||||
local player = Gui.get_player(delete_task_button)
|
||||
Elements.delete_task_button.data[delete_task_button].task = task
|
||||
delete_task_button.visible = has_permission_edit_task(player, task)
|
||||
end
|
||||
|
||||
--- @class ExpGui_TaskList.elements.view_task_footer.elements
|
||||
--- @field task ExpGui_TaskList.Task?
|
||||
--- @field body_label LuaGuiElement
|
||||
--- @field title_label LuaGuiElement
|
||||
--- @field delete_task_button LuaGuiElement
|
||||
--- @field edit_task_button LuaGuiElement
|
||||
|
||||
--- The view footer used for view task details
|
||||
--- @class ExpGui_TaskList.elements.view_task_footer: ExpElement
|
||||
--- @field data table<LuaGuiElement, ExpGui_TaskList.elements.view_task_footer.elements>
|
||||
--- @overload fun(parent: LuaGuiElement, container: LuaGuiElement): LuaGuiElement
|
||||
Elements.view_task_footer = Gui.define("task_list/view_task_footer")
|
||||
:draw(function(def, parent, container)
|
||||
--- @cast def ExpGui_TaskList.elements.view_task_footer
|
||||
local view_task_footer = Elements.task_footer(parent)
|
||||
|
||||
local header_flow = view_task_footer.add{ type = "flow" }
|
||||
header_flow.add{
|
||||
type = "label",
|
||||
style = "frame_title",
|
||||
caption = { "exp-gui_task-list.caption-view-footer" },
|
||||
}
|
||||
header_flow.style.right_padding = 1
|
||||
header_flow.add{ type = "empty-widget" }.style.horizontally_stretchable = true
|
||||
Elements.close_task_button(header_flow, container)
|
||||
|
||||
local title_label = view_task_footer.add{ type = "label" }
|
||||
local title_label_style = title_label.style
|
||||
title_label_style.font = "default-bold"
|
||||
title_label_style.single_line = false
|
||||
title_label_style.padding = 4
|
||||
|
||||
local body_label = view_task_footer.add{ type = "label" }
|
||||
body_label.style.single_line = false
|
||||
body_label.style.padding = 4
|
||||
|
||||
local action_flow = view_task_footer.add{ type = "flow" }
|
||||
local delete_task_button = Elements.delete_task_button(action_flow, container)
|
||||
local edit_task_button = Elements.edit_task_button(action_flow, container)
|
||||
|
||||
def.data[view_task_footer] = {
|
||||
task = nil,
|
||||
body_label = body_label,
|
||||
title_label = title_label,
|
||||
delete_task_button = delete_task_button,
|
||||
edit_task_button = edit_task_button,
|
||||
}
|
||||
|
||||
return view_task_footer
|
||||
end) --[[ @as any ]]
|
||||
|
||||
--- Refresh the view task with new task details
|
||||
--- @param view_task_footer LuaGuiElement
|
||||
--- @param task ExpGui_TaskList.Task
|
||||
function Elements.view_task_footer.refresh(view_task_footer, task)
|
||||
local elements = Elements.view_task_footer.data[view_task_footer]
|
||||
Elements.delete_task_button.refresh(elements.delete_task_button, task)
|
||||
Elements.edit_task_button.refresh(elements.edit_task_button, task)
|
||||
elements.title_label.caption = task.title
|
||||
elements.body_label.caption = task.body
|
||||
elements.task = task
|
||||
end
|
||||
|
||||
--- Refresh the view task with previously selected task
|
||||
--- If task is provided, then will only update if task is the selected task
|
||||
--- @param view_task_footer LuaGuiElement
|
||||
--- @param task ExpGui_TaskList.Task?
|
||||
function Elements.view_task_footer.update(view_task_footer, task)
|
||||
local elements = Elements.view_task_footer.data[view_task_footer]
|
||||
if elements.task and (task == nil or task == elements.task) then
|
||||
Elements.view_task_footer.refresh(view_task_footer, elements.task)
|
||||
end
|
||||
end
|
||||
|
||||
--- Refresh the view task with the previously selected task
|
||||
--- @param player LuaPlayer
|
||||
function Elements.view_task_footer.update_player(player)
|
||||
for _, view_task_footer in Elements.view_task_footer:tracked_elements(player) do
|
||||
Elements.view_task_footer.update(view_task_footer)
|
||||
end
|
||||
end
|
||||
|
||||
--- @class ExpGui_TaskList.elements.task_message_textfield.elements
|
||||
--- @field confirm_task_button LuaGuiElement?
|
||||
|
||||
--- Textfield element used in both the task create and edit footers
|
||||
--- @class ExpGui_TaskList.elements.task_message_textfield: ExpElement
|
||||
--- @field data table<LuaGuiElement, ExpGui_TaskList.elements.task_message_textfield.elements>
|
||||
--- @overload fun(parent: LuaGuiElement, confirm_task_button: LuaGuiElement?): LuaGuiElement
|
||||
Elements.task_message_textfield = Gui.define("task_list/task_message_textfield")
|
||||
:draw{
|
||||
type = "text-box",
|
||||
text = "",
|
||||
}
|
||||
:style{
|
||||
maximal_width = 268,
|
||||
minimal_height = 100,
|
||||
horizontally_stretchable = true,
|
||||
}
|
||||
:element_data{
|
||||
confirm_task_button = Gui.from_argument(1),
|
||||
}
|
||||
:on_text_changed(function(def, player, task_message_textfield)
|
||||
--- @cast def ExpGui_TaskList.elements.task_message_textfield
|
||||
local confirm_task_button = def.data[task_message_textfield].confirm_task_button
|
||||
confirm_task_button.enabled = string.len(task_message_textfield.text) > 5
|
||||
end) --[[ @as any ]]
|
||||
|
||||
--- Set the confirm task button to update on text changed
|
||||
--- @param task_message_textfield LuaGuiElement
|
||||
--- @param confirm_task_button LuaGuiElement
|
||||
function Elements.task_message_textfield.set_confirm_task_button(task_message_textfield, confirm_task_button)
|
||||
Elements.task_message_textfield.data[task_message_textfield].confirm_task_button = confirm_task_button
|
||||
end
|
||||
|
||||
--- Refresh the task message field
|
||||
--- @param task_message_textfield LuaGuiElement
|
||||
--- @param task ExpGui_TaskList.Task
|
||||
function Elements.task_message_textfield.refresh(task_message_textfield, task)
|
||||
local elements = Elements.task_message_textfield.data[task_message_textfield]
|
||||
local message = task.new and "" or task.title .. "\n" .. task.body
|
||||
elements.confirm_task_button.enabled = string.len(message) > 5
|
||||
task_message_textfield.text = message
|
||||
task_message_textfield.focus()
|
||||
end
|
||||
|
||||
--- @class ExpGui_TaskList.elements.confirm_task_button.elements
|
||||
--- @field task ExpGui_TaskList.Task?
|
||||
--- @field task_message_textfield LuaGuiElement
|
||||
--- @field container LuaGuiElement
|
||||
|
||||
--- Textfield element used in both the task create and edit footers
|
||||
--- @class ExpGui_TaskList.elements.confirm_task_button: ExpElement
|
||||
--- @field data table<LuaGuiElement, ExpGui_TaskList.elements.confirm_task_button.elements>
|
||||
--- @overload fun(parent: LuaGuiElement, task_message_textfield: LuaGuiElement, container: LuaGuiElement): LuaGuiElement
|
||||
Elements.confirm_task_button = Gui.define("task_list/confirm_task_button")
|
||||
:draw{
|
||||
type = "button",
|
||||
name = Gui.from_name,
|
||||
caption = { "exp-gui_task-list.caption-confirm" },
|
||||
tooltip = { "exp-gui_task-list.tooltip-confirm" },
|
||||
style = "shortcut_bar_button_green",
|
||||
}
|
||||
:style(Styles.footer_button)
|
||||
:element_data{
|
||||
task_message_textfield = Gui.from_argument(1),
|
||||
container = Gui.from_argument(2),
|
||||
}
|
||||
:on_click(function(def, player, confirm_task_button)
|
||||
--- @cast def ExpGui_TaskList.elements.confirm_task_button
|
||||
local elements = def.data[confirm_task_button]
|
||||
local task_message_textfield = elements.task_message_textfield
|
||||
local task = assert(elements.task)
|
||||
|
||||
local parsed = Elements.confirm_task_button.parse(task_message_textfield.text)
|
||||
task.last_edit_tick = game.tick
|
||||
task.last_user = player
|
||||
task.title = parsed.title
|
||||
task.body = parsed.body
|
||||
|
||||
Elements.container.close_footers(elements.container)
|
||||
|
||||
local force = player.force --[[ @as LuaForce ]]
|
||||
if task.new then
|
||||
Elements.container.add_task(force, task)
|
||||
else
|
||||
Elements.container.refresh_force_online(force, task)
|
||||
end
|
||||
end) --[[ @as any ]]
|
||||
|
||||
--- Refresh the confirm task button
|
||||
--- @param confirm_task_button LuaGuiElement
|
||||
--- @param task ExpGui_TaskList.Task
|
||||
function Elements.confirm_task_button.refresh(confirm_task_button, task)
|
||||
Elements.confirm_task_button.data[confirm_task_button].task = task
|
||||
end
|
||||
|
||||
--- Parse a task message into its two parts
|
||||
--- @param message string
|
||||
--- @return { title: string, body: string }
|
||||
function Elements.confirm_task_button.parse(message)
|
||||
-- Trim the spaces of the string
|
||||
local trimmed = string.gsub(message, "^%s*(.-)%s*$", "%1")
|
||||
local title, body = string.match(trimmed, "(.-)\n(.*)")
|
||||
local parsed = { title = title, body = body }
|
||||
if not title then
|
||||
-- If it doesn't match the pattern return the str as a title
|
||||
parsed.title = trimmed
|
||||
parsed.body = ""
|
||||
end
|
||||
return parsed
|
||||
end
|
||||
|
||||
--- @class ExpGui_TaskList.elements.discard_task_button.elements
|
||||
--- @field task ExpGui_TaskList.Task?
|
||||
--- @field container LuaGuiElement
|
||||
|
||||
--- Button used to close an open task details
|
||||
--- @class ExpGui_TaskList.element.discard_task_button: ExpElement
|
||||
--- @field data table<LuaGuiElement, ExpGui_TaskList.elements.discard_task_button.elements>
|
||||
--- @overload fun(parent: LuaGuiElement, container: LuaGuiElement): LuaGuiElement
|
||||
Elements.discard_task_button = Gui.define("task_list/discard_task_button")
|
||||
:draw{
|
||||
type = "button",
|
||||
caption = { "exp-gui_task-list.caption-discard" },
|
||||
tooltip = { "exp-gui_task-list.tooltip-discard" },
|
||||
style = "shortcut_bar_button_red",
|
||||
}
|
||||
:style(Styles.footer_button)
|
||||
:element_data{
|
||||
container = Gui.from_argument(1),
|
||||
}
|
||||
:on_click(function(def, player, discard_task_button)
|
||||
--- @cast def ExpGui_TaskList.element.discard_task_button
|
||||
local elements = def.data[discard_task_button]
|
||||
local task = assert(elements.task)
|
||||
if task.new then
|
||||
Elements.container.close_footers(elements.container)
|
||||
else
|
||||
Elements.container.open_view_task(elements.container, task)
|
||||
end
|
||||
end) --[[ @as any ]]
|
||||
|
||||
--- Refresh the discard task button
|
||||
--- @param discard_task_button LuaGuiElement
|
||||
--- @param task ExpGui_TaskList.Task
|
||||
function Elements.discard_task_button.refresh(discard_task_button, task)
|
||||
Elements.discard_task_button.data[discard_task_button].task = task
|
||||
end
|
||||
|
||||
--- @class ExpGui_TaskList.elements.edit_task_footer.elements
|
||||
--- @field task ExpGui_TaskList.Task?
|
||||
--- @field header LuaGuiElement
|
||||
--- @field task_message_textfield LuaGuiElement
|
||||
--- @field discard_task_button LuaGuiElement
|
||||
--- @field confirm_task_button LuaGuiElement
|
||||
|
||||
--- The view footer used for view task details
|
||||
--- @class ExpGui_TaskList.elements.edit_task_footer: ExpElement
|
||||
--- @field data table<LuaGuiElement, ExpGui_TaskList.elements.edit_task_footer.elements>
|
||||
--- @overload fun(parent: LuaGuiElement, container: LuaGuiElement): LuaGuiElement
|
||||
Elements.edit_task_footer = Gui.define("task_list/edit_task_footer")
|
||||
:draw(function(def, parent, container)
|
||||
--- @cast def ExpGui_TaskList.elements.edit_task_footer
|
||||
local edit_task_footer = Elements.task_footer(parent)
|
||||
|
||||
local header = edit_task_footer.add{
|
||||
type = "label",
|
||||
style = "frame_title",
|
||||
caption = { "exp-gui_task-list.caption-edit-footer" },
|
||||
}
|
||||
|
||||
local task_message_textfield = Elements.task_message_textfield(edit_task_footer)
|
||||
|
||||
local action_flow = edit_task_footer.add{ type = "flow" }
|
||||
local discard_task_button = Elements.discard_task_button(action_flow, container)
|
||||
local confirm_task_button = Elements.confirm_task_button(action_flow, task_message_textfield, container)
|
||||
Elements.task_message_textfield.set_confirm_task_button(task_message_textfield, confirm_task_button)
|
||||
|
||||
def.data[edit_task_footer] = {
|
||||
task = nil,
|
||||
header = header,
|
||||
task_message_textfield = task_message_textfield,
|
||||
discard_task_button = discard_task_button,
|
||||
confirm_task_button = confirm_task_button,
|
||||
}
|
||||
|
||||
return edit_task_footer
|
||||
end) --[[ @as any ]]
|
||||
|
||||
--- Refresh the view task with new task details
|
||||
--- @param edit_task_footer LuaGuiElement
|
||||
--- @param task ExpGui_TaskList.Task
|
||||
function Elements.edit_task_footer.refresh(edit_task_footer, task)
|
||||
local player = Gui.get_player(edit_task_footer)
|
||||
local elements = Elements.edit_task_footer.data[edit_task_footer]
|
||||
task.editing[player.index] = player.name
|
||||
|
||||
if elements.task and elements.task ~= task then
|
||||
elements.task.editing[player.index] = nil
|
||||
end
|
||||
|
||||
elements.header.caption = {
|
||||
task.new and "exp-gui_task-list.caption-create-footer" or "exp-gui_task-list.caption-edit-footer"
|
||||
}
|
||||
|
||||
Elements.task_message_textfield.refresh(elements.task_message_textfield, task)
|
||||
Elements.confirm_task_button.refresh(elements.confirm_task_button, task)
|
||||
Elements.discard_task_button.refresh(elements.discard_task_button, task)
|
||||
elements.task = task
|
||||
end
|
||||
|
||||
--- Refresh the view task with previously selected task
|
||||
--- If task is provided, then will only update if task is the selected task
|
||||
--- @param edit_task_footer LuaGuiElement
|
||||
--- @param task ExpGui_TaskList.Task?
|
||||
function Elements.edit_task_footer.update(edit_task_footer, task)
|
||||
local elements = Elements.edit_task_footer.data[edit_task_footer]
|
||||
if elements.task and (task == nil or task == elements.task) then
|
||||
Elements.edit_task_footer.refresh(edit_task_footer, elements.task)
|
||||
end
|
||||
end
|
||||
|
||||
--- Refresh the view task with the previously selected task
|
||||
--- @param player LuaPlayer
|
||||
function Elements.edit_task_footer.update_player(player)
|
||||
for _, edit_task_footer in Elements.edit_task_footer:tracked_elements(player) do
|
||||
Elements.edit_task_footer.update(edit_task_footer)
|
||||
end
|
||||
end
|
||||
|
||||
--- Clear the previously edited task
|
||||
--- @param edit_task_footer LuaGuiElement
|
||||
function Elements.edit_task_footer.clear(edit_task_footer)
|
||||
local elements = Elements.edit_task_footer.data[edit_task_footer]
|
||||
if elements.task then
|
||||
local player = Gui.get_player(edit_task_footer)
|
||||
elements.task.editing[player.index] = nil
|
||||
elements.task = nil
|
||||
end
|
||||
end
|
||||
|
||||
--- @class ExpGui_TaskList.elements.container.elements
|
||||
--- @field task_list LuaGuiElement
|
||||
--- @field view_task_footer LuaGuiElement
|
||||
--- @field edit_task_footer LuaGuiElement
|
||||
|
||||
--- Container added to the left gui flow
|
||||
--- @class ExpGui_TaskList.elements.container: ExpElement
|
||||
--- @field data table<LuaForce, ExpGui_TaskList.Task[]> | table<LuaGuiElement, ExpGui_TaskList.elements.container.elements> | table<"global_data", { next_task_id: number }>
|
||||
Elements.container = Gui.define("task_list/container")
|
||||
:track_all_elements()
|
||||
:draw(function(def, parent)
|
||||
--- @cast def ExpGui_TaskList.elements.container
|
||||
local container = Gui.elements.container(parent) -- width 268
|
||||
local root = Gui.elements.container.get_root_element(container)
|
||||
local elements = {}
|
||||
|
||||
-- Add the header
|
||||
local header = Gui.elements.header(container, {
|
||||
caption = { "exp-gui_task-list.caption-main" },
|
||||
tooltip = { "exp-gui_task-list.tooltip-sub" },
|
||||
})
|
||||
|
||||
-- Add buttons to the header
|
||||
local new_task_button = Elements.new_task_button(header, root)
|
||||
Elements.new_task_button.refresh(new_task_button)
|
||||
|
||||
-- Add the task table and footers
|
||||
elements.task_list = Elements.task_list(container)
|
||||
|
||||
-- Add tasks to the list if there are any
|
||||
local player = Gui.get_player(parent)
|
||||
local force = player.force --[[ @as LuaForce ]]
|
||||
local tasks = def.data[force]
|
||||
if tasks then
|
||||
for _, task in ipairs(tasks) do
|
||||
Elements.task_list.add_task(elements.task_list, task)
|
||||
end
|
||||
end
|
||||
|
||||
-- Add the footers
|
||||
elements.view_task_footer = Elements.view_task_footer(container, root)
|
||||
elements.edit_task_footer = Elements.edit_task_footer(container, root)
|
||||
elements.view_task_footer.visible = false
|
||||
elements.edit_task_footer.visible = false
|
||||
|
||||
-- Set the data and return
|
||||
def.data[root] = elements --[[ @as any ]]
|
||||
return root
|
||||
end)
|
||||
:global_data{ next_task_id = 1 }
|
||||
:force_data{} --[[ @as any ]]
|
||||
|
||||
--- Check if a force has tasks
|
||||
--- @param force LuaForce
|
||||
--- @return boolean
|
||||
function Elements.container.has_tasks(force)
|
||||
local tasks = Elements.container.data[force]
|
||||
return tasks and #tasks > 0
|
||||
end
|
||||
|
||||
--- Get the next task id
|
||||
--- @return number
|
||||
function Elements.container.next_task_id()
|
||||
local next_task_id = Elements.container.data.global_data.next_task_id
|
||||
Elements.container.data.global_data.next_task_id = next_task_id + 1
|
||||
return next_task_id
|
||||
end
|
||||
|
||||
--- Add a new task for a force
|
||||
--- @param force LuaForce
|
||||
--- @param task ExpGui_TaskList.Task
|
||||
function Elements.container.add_task(force, task)
|
||||
local tasks = Elements.container.data[force]
|
||||
tasks[#tasks + 1] = task
|
||||
task.deleted = nil
|
||||
task.new = nil
|
||||
|
||||
Elements.no_tasks_header.refresh_force_online(force)
|
||||
for _, container in Elements.container:online_elements(force) do
|
||||
local task_list = Elements.container.data[container].task_list
|
||||
Elements.task_list.add_task(task_list, task)
|
||||
end
|
||||
end
|
||||
|
||||
--- Remove a task from a force
|
||||
--- @param force LuaForce
|
||||
--- @param task ExpGui_TaskList.Task
|
||||
function Elements.container.remove_task(force, task)
|
||||
local tasks = Elements.container.data[force]
|
||||
table.remove_element(tasks, task)
|
||||
task.deleted = true
|
||||
|
||||
Elements.no_tasks_header.refresh_force_online(force)
|
||||
for _, container in Elements.container:online_elements(force) do
|
||||
local task_list = Elements.container.data[container].task_list
|
||||
Elements.task_list.remove_task(task_list, task)
|
||||
end
|
||||
end
|
||||
|
||||
--- Open the view footer
|
||||
--- @param container LuaGuiElement
|
||||
--- @param task ExpGui_TaskList.Task
|
||||
function Elements.container.open_view_task(container, task)
|
||||
local elements = Elements.container.data[container]
|
||||
Elements.view_task_footer.refresh(elements.view_task_footer, task)
|
||||
Elements.edit_task_footer.clear(elements.edit_task_footer)
|
||||
Elements.task_list.select_task_button(elements.task_list, task)
|
||||
elements.view_task_footer.visible = true
|
||||
elements.edit_task_footer.visible = false
|
||||
end
|
||||
|
||||
--- Open the edit footer
|
||||
--- @param container LuaGuiElement
|
||||
--- @param task ExpGui_TaskList.Task
|
||||
function Elements.container.open_edit_task(container, task)
|
||||
local elements = Elements.container.data[container]
|
||||
Elements.edit_task_footer.refresh(elements.edit_task_footer, task)
|
||||
Elements.task_list.select_task_button(elements.task_list, task)
|
||||
elements.edit_task_footer.visible = true
|
||||
elements.view_task_footer.visible = false
|
||||
end
|
||||
|
||||
--- Close the footers
|
||||
--- @param container LuaGuiElement
|
||||
function Elements.container.close_footers(container)
|
||||
local elements = Elements.container.data[container]
|
||||
Elements.edit_task_footer.clear(elements.edit_task_footer)
|
||||
Elements.task_list.select_task_button(elements.task_list)
|
||||
elements.view_task_footer.visible = false
|
||||
elements.edit_task_footer.visible = false
|
||||
end
|
||||
|
||||
--- Refresh all tasks for a player
|
||||
--- @param player LuaPlayer
|
||||
function Elements.container.refresh_player(player)
|
||||
local tasks = Elements.container.data[ player.force --[[ @as LuaForce ]] ]
|
||||
for _, container in Elements.container:tracked_elements(player) do
|
||||
local elements = Elements.container.data[container]
|
||||
Elements.task_list.refresh_tasks(elements.task_list, tasks)
|
||||
Elements.view_task_footer.update(elements.view_task_footer)
|
||||
Elements.edit_task_footer.update(elements.edit_task_footer)
|
||||
end
|
||||
end
|
||||
|
||||
--- Refresh a tasks for a force
|
||||
--- @param force LuaForce
|
||||
--- @param task ExpGui_TaskList.Task
|
||||
function Elements.container.refresh_force_online(force, task)
|
||||
for _, container in Elements.container:online_elements(force) do
|
||||
local elements = Elements.container.data[container]
|
||||
Elements.task_list.refresh_task(elements.task_list, task)
|
||||
Elements.view_task_footer.update(elements.view_task_footer, task)
|
||||
Elements.edit_task_footer.update(elements.edit_task_footer, task)
|
||||
end
|
||||
end
|
||||
|
||||
--- Add the element to the left flow with a toolbar button
|
||||
Gui.add_left_element(Elements.container, function(player)
|
||||
return Elements.container.has_tasks(player.force --[[ @as LuaForce ]])
|
||||
end)
|
||||
|
||||
Gui.toolbar.create_button{
|
||||
name = "toggle_task_list",
|
||||
left_element = Elements.container,
|
||||
sprite = "utility/not_enough_repair_packs_icon",
|
||||
tooltip = { "exp-gui_task-list.tooltip-main" },
|
||||
visible = function(player, element)
|
||||
return Roles.player_allowed(player, "gui/task-list")
|
||||
end
|
||||
}
|
||||
|
||||
--- Update the gui when the player joins because it is likely to be outdated
|
||||
--- @param event EventData.on_player_joined_game
|
||||
local function refresh_player_tasks(event)
|
||||
local player = Gui.get_player(event)
|
||||
Elements.container.refresh_player(player)
|
||||
Elements.no_tasks_header.refresh_player(player)
|
||||
end
|
||||
|
||||
--- Update the gui when the player joins because it is likely to be outdated
|
||||
--- @param event EventData.on_player_joined_game
|
||||
local function refresh_player_permissions(event)
|
||||
local player = Gui.get_player(event)
|
||||
Elements.new_task_button.refresh_player(player)
|
||||
Elements.view_task_footer.update_player(player)
|
||||
Elements.edit_task_footer.update_player(player)
|
||||
end
|
||||
|
||||
local e = defines.events
|
||||
|
||||
return {
|
||||
elements = Elements,
|
||||
events = {
|
||||
[e.on_player_joined_game] = refresh_player_tasks,
|
||||
[e.on_player_changed_force] = refresh_player_tasks,
|
||||
[Roles.events.on_role_assigned] = refresh_player_permissions,
|
||||
[Roles.events.on_role_unassigned] = refresh_player_permissions,
|
||||
}
|
||||
}
|
||||
@@ -376,6 +376,28 @@ type-player=Player
|
||||
type-static=Static
|
||||
type-loop=Loop
|
||||
|
||||
[exp-gui_task-list]
|
||||
caption-main=Task List [img=info]
|
||||
tooltip-main=Task List
|
||||
tooltip-sub=Tasks that remain to be done\n- You can use richtext to include images [img=utility/not_enough_repair_packs_icon] or [color=blue]color[/color] your tasks.
|
||||
caption-no-tasks=No tasks found!
|
||||
tooltip-no-tasks=Click on the plus button to the top right of this window to add a new task!
|
||||
tooltip-last-edit=Last edited by __1__ at __2__
|
||||
tooltip-close=Close task details
|
||||
tooltip-new=Add new task
|
||||
caption-confirm=[img=utility/check_mark] Confirm
|
||||
tooltip-confirm=Save changes (minimum of 5 characters long)
|
||||
caption-discard=[img=utility/close_black] Discard
|
||||
tooltip-discard=Discard changes
|
||||
caption-delete=[img=utility/trash] Delete
|
||||
tooltip-delete=Delete task
|
||||
caption-edit=[img=utility/rename_icon] Edit
|
||||
tooltip-edit=Currently being edited by: __1__
|
||||
tooltip-edit-none=Currently being edited by: Nobody
|
||||
caption-create-footer=Create task
|
||||
caption-edit-footer=Edit task
|
||||
caption-view-footer=Task details
|
||||
|
||||
[exp_afk-kick]
|
||||
kick-message=All players were kicked because everyone was AFK.
|
||||
|
||||
|
||||
@@ -376,6 +376,28 @@ type-player=用戶
|
||||
type-static=靜態
|
||||
type-loop=循環
|
||||
|
||||
[exp-gui_task-list]
|
||||
caption-main=工作流程 [img=info]
|
||||
tooltip-main=工作流程
|
||||
tooltip-sub=需要完成的工作流程\n- 你可以用富文本來加上圖片 [img=utility/not_enough_repair_packs_icon] 或 [color=blue] 顏色[/color]。
|
||||
caption-no-tasks=沒有工作流程
|
||||
tooltip-no-tasks=按加號加入工作流程
|
||||
tooltip-last-edit=最後由 __1__ 在 __2__ 修改
|
||||
tooltip-close=關閉工作流程
|
||||
tooltip-new=加入工作流程
|
||||
caption-confirm=[img=utility/check_mark] 確認
|
||||
confirm-tooltip=儲存工作流程 (最少要5個字長)
|
||||
caption-discard=[img=utility/close_black] 放棄
|
||||
tooltip-discard=放棄更改動
|
||||
caption-delete=[img=utility/trash] 刪除
|
||||
tooltip-delete=刪除工作流程
|
||||
caption-edit=[img=utility/rename_icon] 修改工作流程
|
||||
tooltip-edit=現被 __1__ 修改中
|
||||
tooltip-edit-none=現沒有被人修改
|
||||
caption-create-footer=加入工作流程
|
||||
caption-edit-footer=修改工作流程
|
||||
caption-view-footer=工作流程細節
|
||||
|
||||
[exp_afk-kick]
|
||||
kick-message=因地圖中沒有活躍玩家,所以所有人都已被請離。
|
||||
|
||||
|
||||
@@ -376,6 +376,28 @@ type-player=用戶
|
||||
type-static=靜態
|
||||
type-loop=循環
|
||||
|
||||
[exp-gui_task-list]
|
||||
caption-main=工作流程 [img=info]
|
||||
tooltip-main=工作流程
|
||||
tooltip-sub=需要完成的工作流程\n- 你可以用富文本來加上圖片 [img=utility/not_enough_repair_packs_icon] 或 [color=blue] 顏色[/color]。
|
||||
caption-no-tasks=沒有工作流程
|
||||
tooltip-no-tasks=按加號加入工作流程
|
||||
tooltip-last-edit=最後由 __1__ 在 __2__ 修改
|
||||
tooltip-close=關閉工作流程
|
||||
tooltip-new=加入工作流程
|
||||
caption-confirm=[img=utility/check_mark] 確認
|
||||
confirm-tooltip=儲存工作流程 (最少要5個字長)
|
||||
caption-discard=[img=utility/close_black] 放棄
|
||||
tooltip-discard=放棄更改動
|
||||
caption-delete=[img=utility/trash] 刪除
|
||||
tooltip-delete=刪除工作流程
|
||||
caption-edit=[img=utility/rename_icon] 修改工作流程
|
||||
tooltip-edit=現被 __1__ 修改中
|
||||
tooltip-edit-none=現沒有被人修改
|
||||
caption-create-footer=加入工作流程
|
||||
caption-edit-footer=修改工作流程
|
||||
caption-view-footer=工作流程細節
|
||||
|
||||
[exp_afk-kick]
|
||||
kick-message=因地圖中沒有活躍玩家,所以所有人都已被請離。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user