z_mirror/TaskList

git clone https://git.raiguard.me/z_mirror/TaskList

raiguardDon't close edit GUI if E to confirm failsc176be5

task-details-gui
9.7 KiB330 linesraw
1local gui = require("__flib__.gui")
2local table = require("__flib__.table")
3
4local constants = require("constants")
5
6local actions = require("actions")
7
8-- GUI
9
10--- @class EditTaskGuiRefs
11--- @field window LuaGuiElement
12--- @field titlebar_flow LuaGuiElement
13--- @field title_textfield LuaGuiElement
14--- @field description_textfield LuaGuiElement
15--- @field add_to_top_checkbox LuaGuiElement
16--- @field private_checkbox LuaGuiElement
17--- @field assignee_dropdown LuaGuiElement
18--- @field status_dropdown LuaGuiElement
19--- @field footer_flow LuaGuiElement
20
21--- @class EditTaskGui
22local EditTaskGui = {}
23
24EditTaskGui.actions = actions
25
26function EditTaskGui:destroy()
27  local window = self.refs.window
28  if window and window.valid then
29    self.refs.window.destroy()
30  end
31  self.player_table.guis.edit_task = nil
32
33  if self.parent and not self.parent.state.pinned then
34    self.player.opened = self.parent.refs.window --- @diagnostic disable-line
35  end
36
37  if self.state.standalone then
38    self.player.set_shortcut_toggled("tlst-new-task", false)
39  end
40end
41
42function EditTaskGui:dispatch(msg, e)
43  local transform = msg.transform
44  if transform then
45    if transform == "handle_titlebar_click" and e.button == defines.mouse_button_type.middle then
46      msg.action = "recenter"
47    end
48  end
49
50  if msg.action then
51    local handler = self.actions[msg.action]
52    if handler then
53      handler(self, msg or {}, e or {})
54    end
55  end
56end
57
58-- BOOTSTRAP
59
60local index = {}
61
62--- @class NewTaskOptions
63--- @field parent_gui LuaGuiElement|nil
64--- @field task Task|nil
65--- @field parent_task Task|nil
66--- @field set_private boolean
67--- @field standalone boolean
68
69--- @param player LuaPlayer
70--- @param player_table PlayerTable
71--- @param options NewTaskOptions
72function index.new(player, player_table, options)
73  options = options or {}
74  local Task = options.task
75  local Parent = options.parent_gui
76  local ParentTask = options.parent_task
77
78  local players = { { "gui.tlst-unassigned" } }
79  local force = player.force
80  local assignee_selection_index = 1
81  local player_selection_index = 0
82
83  local title_caption
84  if Task then
85    title_caption = { "gui.tlst-edit-task" }
86  else
87    title_caption = { "gui.tlst-new-task" }
88  end
89
90  Task = Task or {}
91
92  local assignable = true
93  local owner = Task.owner or ParentTask or {}
94  local assignee_index = 0
95  while owner.object_name == "Task" do
96    owner = owner.owner
97  end
98  if owner.object_name == "LuaPlayer" then
99    assignable = false
100    assignee_index = ParentTask and ParentTask.assignee.index or 0
101  else
102    assignee_index = Task.assignee and Task.assignee.index or 0
103  end
104
105  if assignable and not assignee_index and owner.assignee then
106    assignee_index = owner.assignee.index
107  end
108
109  for player_index, other_player in pairs(game.players) do
110    if other_player.force == force then
111      table.insert(players, other_player.name)
112      if player_index == player.index then
113        player_selection_index = #players
114      end
115      if assignee_index == player_index then
116        assignee_selection_index = #players
117      end
118    end
119  end
120
121  local status_items = {}
122  local selected_status_index = 1
123  for status_name, status_info in pairs(constants.task_status) do
124    if status_name == Task.status then
125      selected_status_index = status_info.index
126    end
127    table.insert(status_items, { "", "[img=flib_indicator_" .. status_info.color .. "]  ", status_info.label })
128  end
129
130  --- @type EditTaskGuiRefs
131  local refs = gui.build(player.gui.screen, {
132    {
133      type = "frame",
134      style_mods = { width = 448 },
135      direction = "vertical",
136      ref = { "window" },
137      actions = {
138        on_closed = { gui = "edit_task", action = "close" },
139      },
140      {
141        type = "flow",
142        style = "flib_titlebar_flow",
143        ref = { "titlebar_flow" },
144        actions = {
145          on_click = { gui = "edit_task", transform = "handle_titlebar_click" },
146        },
147        { type = "label", style = "frame_title", caption = title_caption, ignored_by_interaction = true },
148        { type = "empty-widget", style = "flib_dialog_titlebar_drag_handle", ignored_by_interaction = true },
149      },
150      {
151        type = "frame",
152        style = "inside_shallow_frame",
153        direction = "vertical",
154        {
155          type = "frame",
156          style = "subheader_frame",
157          style_mods = { horizontally_stretchable = true },
158          visible = ParentTask and true or false,
159          {
160            type = "label",
161            style = "bold_label",
162            style_mods = { left_margin = 8 },
163            caption = ParentTask and { "gui.tlst-subtask-of", ParentTask.title } or nil,
164          },
165        },
166        {
167          type = "flow",
168          style_mods = { padding = 12, vertical_spacing = 8 },
169          direction = "vertical",
170          { type = "label", caption = { "gui.tlst-title" } },
171          {
172            type = "textfield",
173            style = "flib_widthless_textfield",
174            style_mods = { horizontally_stretchable = true },
175            text = Task.title,
176            ref = { "title_textfield" },
177            actions = {
178              on_confirmed = { gui = "edit_task", action = "confirm" },
179            },
180          },
181          { type = "label", caption = { "gui.tlst-description" } },
182          {
183            type = "text-box",
184            style_mods = { height = 200, width = 400 },
185            text = Task.description,
186            elem_mods = { word_wrap = true },
187            ref = { "description_textfield" },
188            actions = {
189              on_confirmed = { gui = "edit_task", action = "confirm" },
190            },
191          },
192          {
193            type = "flow",
194            visible = not Task.title,
195            {
196              type = "checkbox",
197              caption = { "gui.tlst-add-to-top" },
198              state = false,
199              ref = { "add_to_top_checkbox" },
200            },
201            { type = "empty-widget", style = "flib_horizontal_pusher" },
202            {
203              type = "checkbox",
204              caption = { "gui.tlst-private" },
205              tooltip = { "gui.tlst-private-description" },
206              state = owner and owner.object_name == "LuaPlayer" or false,
207              enabled = not ParentTask,
208              ref = { "private_checkbox" },
209              actions = {
210                on_checked_state_changed = { gui = "edit_task", action = "update_assignee_dropdown" },
211              },
212            },
213          },
214          {
215            type = "flow",
216            style_mods = { vertical_align = "center" },
217            { type = "label", caption = { "gui.tlst-assignee" } },
218            { type = "empty-widget", style = "flib_horizontal_pusher" },
219            {
220              type = "drop-down",
221              items = players,
222              selected_index = assignee_selection_index,
223              enabled = assignable,
224              ref = { "assignee_dropdown" },
225            },
226          },
227          {
228            type = "flow",
229            style_mods = { vertical_align = "center" },
230            {
231              type = "label",
232              caption = { "", { "gui.tlst-status" }, " [img=info]" },
233              tooltip = { "gui.tlst-status-description" },
234            },
235            { type = "empty-widget", style = "flib_horizontal_pusher" },
236            {
237              type = "drop-down",
238              items = status_items,
239              selected_index = selected_status_index,
240              ref = { "status_dropdown" },
241            },
242          },
243        },
244      },
245      {
246        type = "flow",
247        style = "dialog_buttons_horizontal_flow",
248        actions = { on_click = { gui = "edit_task", transform = "handle_titlebar_click" } },
249        ref = { "footer_flow" },
250        {
251          type = "button",
252          style = "back_button",
253          caption = { "gui.cancel" },
254          actions = {
255            on_click = { gui = "edit_task", action = "close" },
256          },
257        },
258        { type = "empty-widget", style = "flib_dialog_footer_drag_handle", ignored_by_interaction = true },
259        Task.title and {
260          type = "button",
261          style = "tlst_red_dialog_button",
262          caption = { "gui.delete" },
263          actions = {
264            on_click = { gui = "edit_task", action = "delete" },
265          },
266        } or {},
267        Task.title and {
268          type = "empty-widget",
269          style = "flib_dialog_footer_drag_handle",
270          ignored_by_interaction = true,
271        } or {},
272        {
273          type = "button",
274          style = "confirm_button",
275          caption = { "gui.confirm" },
276          actions = {
277            on_click = { gui = "edit_task", action = "confirm" },
278          },
279        },
280      },
281    },
282  })
283
284  refs.window.force_auto_center()
285  refs.titlebar_flow.drag_target = refs.window
286  refs.footer_flow.drag_target = refs.window
287
288  if Parent and not Parent.state.pinned then
289    Parent.state.ignore_close = true
290    player.opened = refs.window
291  elseif options.standalone then
292    player.opened = refs.window
293    player.set_shortcut_toggled("tlst-new-task", true)
294  end
295
296  --- @type EditTaskGui
297  local self = {
298    parent = Parent,
299    player = player,
300    player_table = player_table,
301    refs = refs,
302    state = {
303      just_confirmed = false,
304      parent_task = ParentTask,
305      player_selection_index = player_selection_index,
306      standalone = options.standalone,
307      --- @type Task|nil
308      task = Task.title and Task or nil,
309    },
310  }
311
312  setmetatable(self, { __index = EditTaskGui })
313
314  player_table.guis.edit_task = self
315
316  if options.set_private then
317    self.refs.private_checkbox.state = true
318    self.actions.update_assignee_dropdown(self)
319  end
320
321  self.refs.title_textfield.select_all()
322  self.refs.title_textfield.focus()
323end
324
325--- @param Gui EditTaskGui
326function index.load(Gui)
327  setmetatable(Gui, { __index = EditTaskGui })
328end
329
330return index