mirror of
https://github.com/Citadel-Station-13/Citadel-Station-13-RP.git
synced 2026-08-18 13:16:38 +01:00
221 lines
6.7 KiB
Plaintext
221 lines
6.7 KiB
Plaintext
//* This file is explicitly licensed under the MIT license. *//
|
|
//* Copyright (c) 2023 Citadel Station developers. *//
|
|
|
|
// TODO: generalize this to a tgui helper / whatever, this shouldn't just be for dynamic input modal.
|
|
// this will be very useful for rigs & more.
|
|
|
|
/**
|
|
* Helper datum used to build a query for tgui_dynamic_input
|
|
* High overhead, technically not necessary, but, this is easy to use as an API.
|
|
*/
|
|
/datum/tgui_dynamic_query
|
|
/// options list
|
|
var/list/options = list()
|
|
|
|
/datum/tgui_dynamic_query/proc/string(key, name, desc, max_length = 512, multi_line = FALSE, default)
|
|
RETURN_TYPE(/datum/tgui_dynamic_query)
|
|
options[key] = list(
|
|
"name" = name,
|
|
"desc" = desc,
|
|
"default" = default,
|
|
"type" = TGUI_INPUT_DATATYPE_TEXT,
|
|
"constraints" = list(max_length),
|
|
)
|
|
return src
|
|
|
|
/datum/tgui_dynamic_query/proc/number(key, name, desc, min_value = -INFINITY, max_value = INFINITY, round_to, default)
|
|
RETURN_TYPE(/datum/tgui_dynamic_query)
|
|
options[key] = list(
|
|
"name" = name,
|
|
"desc" = desc,
|
|
"default" = default,
|
|
"type" = TGUI_INPUT_DATATYPE_NUM,
|
|
"constraints" = list(min_value, max_value, round_to),
|
|
)
|
|
return src
|
|
|
|
/datum/tgui_dynamic_query/proc/toggle(key, name, desc, default)
|
|
RETURN_TYPE(/datum/tgui_dynamic_query)
|
|
options[key] = list(
|
|
"name" = name,
|
|
"desc" = desc,
|
|
"default" = default,
|
|
"type" = TGUI_INPUT_DATATYPE_TOGGLE,
|
|
"constraints" = list(),
|
|
)
|
|
return src
|
|
|
|
/datum/tgui_dynamic_query/proc/pick_one(key, name, desc, list/choices = list(), default)
|
|
RETURN_TYPE(/datum/tgui_dynamic_query)
|
|
options[key] = list(
|
|
"name" = name,
|
|
"desc" = desc,
|
|
"default" = default,
|
|
"type" = TGUI_INPUT_DATATYPE_LIST_PICK,
|
|
"constraints" = choices,
|
|
)
|
|
return src
|
|
|
|
/**
|
|
* builds return list of results
|
|
*/
|
|
/datum/tgui_dynamic_query/proc/get_results(list/choices)
|
|
. = list()
|
|
var/got
|
|
for(var/key in options)
|
|
var/list/params = options[key]
|
|
var/val = choices[key]
|
|
switch(params[TGUI_INPUT_DATA_TYPE])
|
|
if(TGUI_INPUT_DATATYPE_TEXT)
|
|
got = isnull(val) ? params[TGUI_INPUT_DATA_DEFAULT] : val
|
|
if(!isnull(got))
|
|
if(length(got) > params[TGUI_INPUT_DATA_CONSTRAINTS][1])
|
|
got = copytext_char(got, 1, params[TGUI_INPUT_DATA_CONSTRAINTS][1] + 1)
|
|
.[key] = got
|
|
if(TGUI_INPUT_DATATYPE_NUM)
|
|
got = isnull(val) ? params[TGUI_INPUT_DATA_DEFAULT] : text2num(val)
|
|
if(!isnull(got))
|
|
got = clamp(got, params[TGUI_INPUT_DATA_CONSTRAINTS][1], params[TGUI_INPUT_DATA_CONSTRAINTS][2])
|
|
if(!isnull(params[TGUI_INPUT_DATA_CONSTRAINTS][3]))
|
|
got = round(got, params[TGUI_INPUT_DATA_CONSTRAINTS][3])
|
|
.[key] = got
|
|
if(TGUI_INPUT_DATATYPE_LIST_PICK)
|
|
got = isnull(val) ? params[TGUI_INPUT_DATA_DEFAULT] : val
|
|
if(!isnull(got))
|
|
if(!(got in params[TGUI_INPUT_DATA_CONSTRAINTS]))
|
|
if(length(params[TGUI_INPUT_DATA_CONSTRAINTS]))
|
|
got = params[TGUI_INPUT_DATA_CONSTRAINTS][1]
|
|
else
|
|
got = null
|
|
.[key] = got
|
|
if(TGUI_INPUT_DATATYPE_TOGGLE)
|
|
got = isnull(val) ? params[TGUI_INPUT_DATA_DEFAULT] : val
|
|
if(!isnull(got))
|
|
got = !!got
|
|
.[key] = got
|
|
|
|
/**
|
|
* returns list to be sent to UI
|
|
*/
|
|
/datum/tgui_dynamic_query/proc/get_query()
|
|
return options
|
|
|
|
/**
|
|
* Creates a TGUI input window and returns the user's response
|
|
*
|
|
* This is used to grab a set of responses to various datatypes.
|
|
* This proc blocks until finished.
|
|
*
|
|
* @params
|
|
* * user - who to send this to
|
|
* * message - description in interface
|
|
* * title - self explanatory
|
|
* * query - built query
|
|
* * timeout - timeout before menu closes. if it times out, choices will be null.
|
|
*
|
|
* @return list of key-value pairs (the TGUI_INPUT_DATA_KEY's you put in) associated to values
|
|
*/
|
|
/proc/tgui_dynamic_input(mob/user, message, title = "Input", datum/tgui_dynamic_query/query, timeout = 0)
|
|
var/datum/tgui_dynamic_input/modal = new(user, message, title, query, timeout)
|
|
modal.block_on_finished()
|
|
return modal.query.get_results(modal.choices)
|
|
|
|
/**
|
|
* Creates a TGUI input window and returns the user's response
|
|
*
|
|
* This is used to grab a set of responses to various datatypes.
|
|
* This proc immediately returns.
|
|
*
|
|
* @params
|
|
* * user - who to send this to
|
|
* * message - description in interface
|
|
* * title - self explanatory
|
|
* * query - built query
|
|
* * timeout - timeout before menu closes. if it times out, choices will be null.
|
|
* * callback - callback called with first arg being the picked list when we're done.
|
|
*
|
|
* @return the /datum/tgui_dynamic_input instance created. you should probably not touch this unless you know what you're doing.
|
|
*/
|
|
/proc/tgui_dynamic_input_async(mob/user, message, title = "Input", datum/tgui_dynamic_query/query, timeout = 0, datum/callback/callback)
|
|
return new /datum/tgui_dynamic_input(user, message, title, query, timeout, callback)
|
|
|
|
/datum/tgui_dynamic_input
|
|
/// title of the windo
|
|
var/title
|
|
/// message that appears inside the window
|
|
var/message
|
|
/// query datum
|
|
var/datum/tgui_dynamic_query/query
|
|
/// list of user's choices; null if they haven't picked yet
|
|
var/list/choices
|
|
/// when we were opened
|
|
var/opened_time
|
|
/// how long our timeout is; null for infinite
|
|
var/timeout
|
|
/// did user close us yet? also set to true if we're qdeleted
|
|
var/closed
|
|
/// callback to invoke on finish
|
|
var/datum/callback/callback
|
|
/// are we finished? set to true on close, here to prevent double close.
|
|
var/finished = FALSE
|
|
|
|
/datum/tgui_dynamic_input/New(mob/user, message, title, datum/tgui_dynamic_query/query, timeout, datum/callback/callback)
|
|
src.title = title
|
|
src.message = message
|
|
src.query = query
|
|
src.timeout = timeout
|
|
if(timeout)
|
|
QDEL_IN(src, timeout)
|
|
src.callback = callback
|
|
ui_interact(user)
|
|
|
|
/datum/tgui_dynamic_input/Destroy()
|
|
// 'choices' and 'query' intentionally kept
|
|
if(!finished)
|
|
finish(null)
|
|
closed = TRUE
|
|
return ..()
|
|
|
|
/datum/tgui_dynamic_input/ui_static_data(mob/user, datum/tgui/ui)
|
|
. = ..()
|
|
.["query"] = query.get_query()
|
|
.["title"] = title
|
|
.["message"] = message
|
|
.["timeout"] = timeout
|
|
|
|
/datum/tgui_dynamic_input/ui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
ui = new(user, src, "UIDynamicInputModal")
|
|
ui.set_autoupdate(FALSE)
|
|
ui.open()
|
|
|
|
/datum/tgui_dynamic_input/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state, datum/event_args/actor/actor)
|
|
. = ..()
|
|
if(.)
|
|
return
|
|
switch(action)
|
|
if("submit")
|
|
finish(params["choices"])
|
|
return TRUE
|
|
if("cancel")
|
|
closed = TRUE
|
|
SStgui.close_uis(src)
|
|
if(!finished)
|
|
finish(null)
|
|
return TRUE
|
|
|
|
/datum/tgui_dynamic_input/ui_state()
|
|
return GLOB.always_state
|
|
|
|
/datum/tgui_dynamic_input/proc/block_on_finished()
|
|
UNTIL(closed)
|
|
return choices
|
|
|
|
/datum/tgui_dynamic_input/proc/finish(list/choices)
|
|
finished = TRUE
|
|
choices = query.get_results(choices)
|
|
callback?.InvokeAsync(choices)
|
|
if(!QDESTROYING(src))
|
|
qdel(src)
|