[MIRROR] browse to browser part 1 (#11017)

Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
CHOMPStation2StaffMirrorBot
2025-06-06 07:18:23 -07:00
committed by GitHub
parent d7cd22d2d0
commit 0fc7bb29d1
36 changed files with 428 additions and 423 deletions

View File

@@ -1,40 +1,48 @@
/datum/browser
var/mob/user
var/title
var/window_id // window_id is used as the window name for browse and onclose
var/title = ""
/// window_id is used as the window name for browse and onclose
var/window_id
var/width = 0
var/height = 0
var/datum/weakref/ref = null
var/window_options = "can_close=1;can_minimize=1;can_maximize=0;can_resize=1;titlebar=1;" // window option is set using window_id
var/stylesheets[0]
var/scripts[0]
var/datum/weakref/source_ref = null
/// window option is set using window_id
var/window_options = "can_close=1;can_minimize=1;can_maximize=0;can_resize=1;titlebar=1;"
var/list/stylesheets = list()
var/list/scripts = list()
var/head_elements
var/body_elements
var/head_content = ""
var/content = ""
/datum/browser/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, atom/nref = null)
user = nuser
/datum/browser/New(mob/user, window_id, title = "", width = 0, height = 0, atom/source = null)
if(IS_CLIENT_OR_MOCK(user))
var/client/client_user = user
user = client_user.mob
src.user = user
RegisterSignal(user, COMSIG_PARENT_QDELETING, PROC_REF(user_deleted))
window_id = nwindow_id
if (ntitle)
title = format_text(ntitle)
if (nwidth)
width = nwidth
if (nheight)
height = nheight
if (nref)
ref = WEAKREF(nref)
src.window_id = window_id
if (title)
src.title = format_text(title)
if (width)
src.width = width
if (height)
src.height = height
if (source)
src.source_ref = WEAKREF(source)
/datum/browser/proc/user_deleted(datum/source)
SIGNAL_HANDLER
user = null
/datum/browser/proc/add_head_content(nhead_content)
head_content = nhead_content
/datum/browser/proc/add_head_content(head_content)
src.head_content += head_content
/datum/browser/proc/set_window_options(nwindow_options)
window_options = nwindow_options
/datum/browser/proc/set_head_content(head_content)
src.head_content = head_content
/datum/browser/proc/set_window_options(window_options)
src.window_options = window_options
/datum/browser/proc/add_stylesheet(name, file)
if (istype(name, /datum/asset/spritesheet))
@@ -55,24 +63,24 @@
scripts["[ckey(name)].js"] = file
SSassets.transport.register_asset("[ckey(name)].js", file)
/datum/browser/proc/set_content(ncontent)
content = ncontent
/datum/browser/proc/set_content(content)
src.content = content
/datum/browser/proc/add_content(ncontent)
content += ncontent
/datum/browser/proc/add_content(content)
src.content += content
/datum/browser/proc/get_header()
var/datum/asset/simple/namespaced/common/common_asset = get_asset_datum(/datum/asset/simple/namespaced/common)
var/file
var/list/new_head_content = list()
// If a client exists, but they have disabled fancy windowing, disable it!
if(user?.client?.prefs?.read_preference(/datum/preference/toggle/browser_style))
head_content += "<link rel='stylesheet' type='text/css' href='[common_asset.get_url_mappings()["common.css"]]'>"
for (file in stylesheets)
head_content += "<link rel='stylesheet' type='text/css' href='[SSassets.transport.get_asset_url(file)]'>"
new_head_content += "<link rel='stylesheet' type='text/css' href='[common_asset.get_url_mappings()["common.css"]]'>"
for (var/file in stylesheets)
new_head_content += "<link rel='stylesheet' type='text/css' href='[SSassets.transport.get_asset_url(file)]'>"
if(user.client?.window_scaling && user.client?.window_scaling != 1 && !user.client?.prefs.read_preference(/datum/preference/toggle/ui_scale) && width && height)
head_content += {"
new_head_content += {"
<style>
body {
zoom: [100 / user.client?.window_scaling]%;
@@ -80,9 +88,10 @@
</style>
"}
for (file in scripts)
head_content += "<script type='text/javascript' src='[SSassets.transport.get_asset_url(file)]'></script>"
for (var/file in scripts)
new_head_content += "<script type='text/javascript' src='[SSassets.transport.get_asset_url(file)]'></script>"
head_content += new_head_content.Join()
return {"<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
@@ -95,6 +104,7 @@
[title ? "<div class='uiTitleWrapper'><div class='uiTitle'><tt>[title]</tt></div></div>" : ""]
<div class='uiContent'>
"}
//" This is here because else the rest of the file looks like a string in notepad++.
/datum/browser/proc/get_footer()
return {"
@@ -105,16 +115,17 @@
/datum/browser/proc/get_content()
return {"
[get_header()]
[content]
[get_footer()]
[get_header()]
[content]
[get_footer()]
"}
/datum/browser/proc/open(use_onclose = TRUE)
/datum/browser/proc/open(use_on_close = TRUE)
if(isnull(window_id)) //null check because this can potentially nuke goonchat
WARNING("Browser [title] tried to open with a null ID")
to_chat(user, span_userdanger("The [title] browser you tried to open failed a sanity check! Please report this on GitHub!"))
return
var/window_size = ""
if(width && height)
if(user.client?.prefs?.read_preference(/datum/preference/toggle/ui_scale))
@@ -122,27 +133,28 @@
window_size = "size=[width * scaling]x[height * scaling];"
else
window_size = "size=[width]x[height];"
var/datum/asset/simple/namespaced/common/common_asset = get_asset_datum(/datum/asset/simple/namespaced/common)
common_asset.send(user)
if (stylesheets.len)
if (length(stylesheets))
SSassets.transport.send_assets(user, stylesheets)
if (scripts.len)
if (length(scripts))
SSassets.transport.send_assets(user, scripts)
user << browse(get_content(), "window=[window_id];[window_size][window_options]")
if (use_onclose)
DIRECT_OUTPUT(user, browse(get_content(), "window=[window_id];[window_size][window_options]"))
if (use_on_close)
setup_onclose()
/datum/browser/proc/setup_onclose()
set waitfor = 0 //winexists sleeps, so we don't need to.
for (var/i in 1 to 10)
if (user?.client && winexists(user, window_id))
var/atom/send_ref
if(ref)
send_ref = ref.resolve()
if(!send_ref)
ref = null
onclose(user, window_id, send_ref)
break
if (!user?.client || !winexists(user, window_id))
continue
var/atom/send_ref
if(source_ref)
send_ref = source_ref.resolve()
if(!send_ref)
source_ref = null
onclose(user, window_id, send_ref)
/datum/browser/proc/close()
if(!isnull(window_id))//null check because this can potentially nuke goonchat
@@ -150,106 +162,106 @@
else
WARNING("Browser [title] tried to close with a null ID")
/datum/browser/modal/alert/New(User,Message,Title,Button1="Ok",Button2,Button3,StealFocus = 1,Timeout=6000)
if (!User)
/datum/browser/modal/alert/New(user, message, title, button_1 = "Ok", button_2, button_3, steal_focus = TRUE, timeout = 600 SECONDS)
if (!user)
return
var/output = {"<center><b>[Message]</b></center><br />
var/list/display_list = list()
display_list += {"<center><b>[message]</b></center><br />
<div style="text-align:center">
<a style="font-size:large;float:[( Button2 ? "left" : "right" )]" href='byond://?src=[REF(src)];button=1'>[Button1]</a>"}
<a style="font-size:large;float:[( button_2 ? "left" : "right" )]" href='byond://?src=[REF(src)];button=1'>[button_1]</a>"}
if (Button2)
output += {"<a style="font-size:large;[( Button3 ? "" : "float:right" )]" href='byond://?src=[REF(src)];button=2'>[Button2]</a>"}
if (button_2)
display_list += {"<a style="font-size:large;[( button_3 ? "" : "float:right" )]" href='byond://?src=[REF(src)];button=2'>[button_2]</a>"}
if (Button3)
output += {"<a style="font-size:large;float:right" href='byond://?src=[REF(src)];button=3'>[Button3]</a>"}
if (button_3)
display_list += {"<a style="font-size:large;float:right" href='byond://?src=[REF(src)];button=3'>[button_3]</a>"}
output += {"</div>"}
display_list += {"</div>"}
..(User, ckey("[User]-[Message]-[Title]-[world.time]-[rand(1,10000)]"), Title, 350, 150, src, StealFocus, Timeout)
set_content(output)
..(user, ckey("[user]-[message]-[title]-[world.time]-[rand(1,10000)]"), title, 350, 150, src, steal_focus, timeout)
set_content(display_list.Join())
/datum/browser/modal/alert/Topic(href,href_list)
if (href_list["close"] || !user || !user.client)
opentime = 0
open_time = 0
return
if (href_list["button"])
var/button = text2num(href_list["button"])
if (button <= 3 && button >= 1)
selectedbutton = button
opentime = 0
selected_button = button
open_time = 0
close()
/**
* **DEPRECATED: USE tgui_alert(...) INSTEAD**
*
* Designed as a drop in replacement for alert(); functions the same. (outside of needing User specified)
* Designed as a drop in replacement for alert(); functions the same. (outside of needing user specified)
* Arguments:
* * User - The user to show the alert to.
* * Message - The textual body of the alert.
* * Title - The title of the alert's window.
* * Button1 - The first button option.
* * Button2 - The second button option.
* * Button3 - The third button option.
* * StealFocus - Boolean operator controlling if the alert will steal the user's window focus.
* * Timeout - The timeout of the window, after which no responses will be valid.
* * user - The user to show the alert to.
* * message - The textual body of the alert.
* * title - The title of the alert's window.
* * button_1 - The first button option.
* * button_2 - The second button option.
* * button_3 - The third button option.
* * steal_focus - Boolean operator controlling if the alert will steal the user's window focus.
* * timeout - The timeout of the window, after which no responses will be valid.
*/
/proc/tgalert(mob/User, Message, Title, Button1="Ok", Button2, Button3, StealFocus = TRUE, Timeout = 6000)
if (!User)
User = usr
if (!istype(User))
if (istype(User, /client))
var/client/client = User
User = client.mob
else
/proc/tg_alert(mob/user, message, title, button_1 = "Ok", button_2, button_3, steal_focus = TRUE, timeout = 600 SECONDS)
if (!user)
user = usr
if (!ismob(user))
if (!istype(user, /client))
return
var/client/user_client = user
user = user_client.mob
// Get user's response using a modal
var/datum/browser/modal/alert/A = new(User, Message, Title, Button1, Button2, Button3, StealFocus, Timeout)
A.open()
A.wait()
switch(A.selectedbutton)
var/datum/browser/modal/alert/window = new(user, message, title, button_1, button_2, button_3, steal_focus, timeout)
window.open()
window.wait()
switch(window.selected_button)
if (1)
return Button1
return button_1
if (2)
return Button2
return button_2
if (3)
return Button3
return button_3
/datum/browser/modal
var/opentime = 0
var/open_time = 0
var/timeout
var/selectedbutton = 0
var/stealfocus
var/selected_button = 0
var/steal_focus
/datum/browser/modal/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, atom/nref = null, StealFocus = 1, Timeout = 6000)
/datum/browser/modal/New(user, window_id, title = 0, width = 0, height = 0, atom/source = null, steal_focus = TRUE, timeout = 600 SECONDS)
..()
stealfocus = StealFocus
if (!StealFocus)
src.steal_focus = steal_focus
if (!src.steal_focus)
window_options += "focus=false;"
timeout = Timeout
src.timeout = timeout
/datum/browser/modal/close()
.=..()
opentime = 0
. = ..()
open_time = 0
/datum/browser/modal/open(use_onclose)
/datum/browser/modal/open(use_on_close)
set waitfor = FALSE
opentime = world.time
open_time = world.time
use_on_close = TRUE
if (stealfocus)
. = ..(use_onclose = 1)
if (steal_focus)
. = ..()
else
var/focusedwindow = winget(user, null, "focus")
. = ..(use_onclose = 1)
var/focused_window = winget(user, null, "focus")
. = ..()
//waits for the window to show up client side before attempting to un-focus it
//winexists sleeps until it gets a reply from the client, so we don't need to bother sleeping
for (var/i in 1 to 10)
if (user && winexists(user, window_id))
if (focusedwindow)
winset(user, focusedwindow, "focus=true")
if (focused_window)
winset(user, focused_window, "focus=true")
else
winset(user, "mapwindow", "focus=true")
break
@@ -257,126 +269,237 @@
addtimer(CALLBACK(src, PROC_REF(close)), timeout)
/datum/browser/modal/proc/wait()
while (opentime && selectedbutton <= 0 && (!timeout || opentime+timeout > world.time))
while (open_time && selected_button <= 0 && (!timeout || open_time + timeout > world.time))
stoplag(1)
/datum/browser/modal/listpicker
var/valueslist = list()
/datum/browser/modal/list_picker
var/values_list = list()
/datum/browser/modal/listpicker/New(User,Message,Title,Button1="Ok",Button2,Button3,StealFocus = 1, Timeout = FALSE,list/values,inputtype="checkbox", width, height, slidecolor)
if (!User)
/datum/browser/modal/list_picker/New(user, message, title, button_1 = "Ok", button_2, button_3, steal_focus = TRUE, timeout = FALSE, list/values, input_type = "checkbox", width, height, slide_color)
if (!user)
return
var/output = {"<form><input type="hidden" name="src" value="[REF(src)]"><ul class="sparse">"}
if (inputtype == "checkbox" || inputtype == "radio")
for (var/i in values)
var/div_slider = slidecolor
if(!i["allowed_edit"])
var/list/display_list = list()
display_list += {"<form><input type="hidden" name="src" value="[REF(src)]"><ul class="sparse">"}
if (input_type == "checkbox" || input_type == "radio")
for (var/option in values)
var/div_slider = slide_color
if(!option["allowed_edit"])
div_slider = "locked"
output += {"<li>
display_list += {"<li>
<label class="switch">
<input type="[inputtype]" value="1" name="[i["name"]]"[i["checked"] ? " checked" : ""][i["allowed_edit"] ? "" : " onclick='return false' onkeydown='return false'"]>
<input type="[input_type]" value="1" name="[option["name"]]"[option["checked"] ? " checked" : ""][option["allowed_edit"] ? "" : " onclick='return false' onkeydown='return false'"]>
<div class="slider [div_slider ? "[div_slider]" : ""]"></div>
<span>[i["name"]]</span>
<span>[option["name"]]</span>
</label>
</li>"}
else
for (var/i in values)
output += {"<li><input id="name="[i["name"]]"" style="width: 50px" type="[type]" name="[i["name"]]" value="[i["value"]]">
<label for="[i["name"]]">[i["name"]]</label></li>"}
output += {"</ul><div style="text-align:center">
<button type="submit" name="button" value="1" style="font-size:large;float:[( Button2 ? "left" : "right" )]">[Button1]</button>"}
for (var/option in values)
display_list += {"<li><input id="name="[option["name"]]"" style="width: 50px" type="[type]" name="[option["name"]]" value="[option["value"]]">
<label for="[option["name"]]">[option["name"]]</label></li>"}
display_list += {"</ul><div style="text-align:center">
<button type="submit" name="button" value="1" style="font-size:large;float:[( button_2 ? "left" : "right" )]">[button_1]</button>"}
if (Button2)
output += {"<button type="submit" name="button" value="2" style="font-size:large;[( Button3 ? "" : "float:right" )]">[Button2]</button>"}
if (button_2)
display_list += {"<button type="submit" name="button" value="2" style="font-size:large;[( button_3 ? "" : "float:right" )]">[button_2]</button>"}
if (Button3)
output += {"<button type="submit" name="button" value="3" style="font-size:large;float:right">[Button3]</button>"}
if (button_3)
display_list += {"<button type="submit" name="button" value="3" style="font-size:large;float:right">[button_3]</button>"}
output += {"</form></div>"}
..(User, ckey("[User]-[Message]-[Title]-[world.time]-[rand(1,10000)]"), Title, width, height, src, StealFocus, Timeout)
set_content(output)
display_list += {"</form></div>"}
..(user, ckey("[user]-[message]-[title]-[world.time]-[rand(1,10000)]"), title, width, height, src, steal_focus, timeout)
set_content(display_list.Join())
/datum/browser/modal/listpicker/Topic(href,href_list)
/datum/browser/modal/list_picker/Topic(href, list/href_list)
if (href_list["close"] || !user || !user.client)
opentime = 0
open_time = 0
return
if (href_list["button"])
var/button = text2num(href_list["button"])
if (button <= 3 && button >= 1)
selectedbutton = button
for (var/item in href_list)
switch(item)
if ("close", "button", "src")
continue
else
valueslist[item] = href_list[item]
opentime = 0
selected_button = button
values_list = href_list.Copy()
values_list -= list("close", "button", "src")
open_time = 0
close()
/proc/presentpicker(mob/User,Message, Title, Button1="Ok", Button2, Button3, StealFocus = 1,Timeout = 6000,list/values, inputtype = "checkbox", width, height, slidecolor)
if (!istype(User))
if (istype(User, /client/))
var/client/C = User
User = C.mob
else
/proc/present_picker(mob/user, message, title, button_1 = "Ok", button_2, button_3, steal_focus = TRUE, timeout = 600 SECONDS, list/values, input_type = "checkbox", width, height, slide_color)
if (!ismob(user))
if (!istype(user, /client))
return
var/datum/browser/modal/listpicker/A = new(User, Message, Title, Button1, Button2, Button3, StealFocus,Timeout, values, inputtype, width, height, slidecolor)
A.open()
A.wait()
if (A.selectedbutton)
return list("button" = A.selectedbutton, "values" = A.valueslist)
var/client/user_client = user
user = user_client.mob
var/datum/browser/modal/list_picker/window = new(user, message, title, button_1, button_2, button_3, steal_focus, timeout, values, input_type, width, height, slide_color)
window.open()
window.wait()
if (window.selected_button)
return list("button" = window.selected_button, "values" = window.values_list)
/proc/input_bitfield(var/mob/User, title, bitfield, current_value, nwidth = 350, nheight = 350, nslidecolor, allowed_edit_list = null)
if (!User || !(bitfield in GLOB.bitfields))
/proc/input_bitfield(mob/user, title, bitfield, current_value, width = 350, height = 350, slide_color, allowed_edit_field = ALL)
var/list/bitflags = get_valid_bitflags(bitfield)
if (!user || !length(bitflags))
return
var/list/pickerlist = list()
for (var/i in GLOB.bitfields[bitfield])
var/can_edit = 1
if(!isnull(allowed_edit_list) && !(allowed_edit_list & GLOB.bitfields[bitfield][i]))
can_edit = 0
if (current_value & GLOB.bitfields[bitfield][i])
pickerlist += list(list("checked" = 1, "value" = GLOB.bitfields[bitfield][i], "name" = i, "allowed_edit" = can_edit))
var/list/picker_list = list()
for (var/bit_name in bitflags)
var/bit_value = bitflags[bit_name]
// Gotta make it TRUE/FALSE sorry brother
var/can_edit = !!(allowed_edit_field & bit_value)
var/enabled = !!(current_value & bit_value)
picker_list += list(list("checked" = enabled, "value" = bit_value, "name" = bit_name, "allowed_edit" = can_edit))
var/list/result = present_picker(user, "", title, button_1 = "Save", button_2 = "Cancel", timeout = FALSE, values = picker_list, width = width, height = height, slide_color = slide_color)
if (!islist(result))
return
if (result["button"] == 2) // If the user pressed the cancel button
return
var/result_bitfield = NONE
for (var/flag_name in result["values"])
result_bitfield |= bitflags[flag_name]
return result_bitfield
/datum/browser/modal/pref_like_picker
var/settings = list()
var/icon/preview_icon = null
var/datum/callback/preview_update
/datum/browser/modal/pref_like_picker/New(mob/user, message, title, steal_focus = TRUE, timeout = 600 SECONDS, list/settings, width, height)
if (!user)
return
src.settings = settings
..(user, ckey("[user]-[message]-[title]-[world.time]-[rand(1,10000)]"), title, width, height, src, steal_focus, timeout)
set_content(show_choices(user))
/datum/browser/modal/pref_like_picker/proc/show_choices(mob/user)
if (settings["preview_callback"])
var/datum/callback/callback = settings["preview_callback"]
preview_icon = callback.Invoke(settings)
if (preview_icon)
user << browse_rsc(preview_icon, "previewicon.png")
var/list/display_list = list()
for (var/name in settings["mainsettings"])
var/setting = settings["mainsettings"][name]
if (setting["type"] == "datum")
if (setting["subtypesonly"])
display_list += "<b>[setting["desc"]]:</b> <a href='byond://?src=[REF(src)];setting=[name];task=input;subtypesonly=1;type=datum;path=[setting["path"]]'>[setting["value"]]</a><BR>"
else
display_list += "<b>[setting["desc"]]:</b> <a href='byond://?src=[REF(src)];setting=[name];task=input;type=datum;path=[setting["path"]]'>[setting["value"]]</a><BR>"
else
pickerlist += list(list("checked" = 0, "value" = GLOB.bitfields[bitfield][i], "name" = i, "allowed_edit" = can_edit))
var/list/result = presentpicker(User, "", title, Button1="Save", Button2 = "Cancel", Timeout=FALSE, values = pickerlist, width = nwidth, height = nheight, slidecolor = nslidecolor)
if (islist(result))
if (result["button"] == 2) // If the user pressed the cancel button
return
. = 0
for (var/flag in result["values"])
. |= GLOB.bitfields[bitfield][flag]
else
display_list += "<b>[setting["desc"]]:</b> <a href='byond://?src=[REF(src)];setting=[name];task=input;type=[setting["type"]]'>[setting["value"]]</a><BR>"
if (preview_icon)
display_list += "<td valign='center'>"
display_list += "<div class='statusDisplay'><center><img src=previewicon.png width=[preview_icon.Width()] height=[preview_icon.Height()]></center></div>"
display_list += "</td>"
display_list += "</tr></table>"
display_list += "<hr><center><a href='byond://?src=[REF(src)];button=1'>Ok</a> "
display_list += "</center>"
return display_list.Join()
/datum/browser/modal/pref_like_picker/Topic(href,href_list)
if (href_list["close"] || !user || !user.client)
open_time = 0
return
//
/proc/onclose(mob/user, windowid, atom/ref=null)
if (href_list["task"] == "input")
var/setting_key = href_list["setting"]
var/list/setting = settings["mainsettings"][setting_key]
switch (href_list["type"])
if ("datum")
var/parent_path = text2path(href_list["path"])
var/list/paths
if (href_list["subtypesonly"])
paths = subtypesof(parent_path)
else
paths = typesof(parent_path)
var/new_value = pick_closest_path(null, make_types_fancy(paths))
if (!isnull(new_value))
setting["value"] = new_value
if ("string")
setting["value"] = stripped_input(user, "Enter new value for [setting["desc"]]", "Enter new value for [setting["desc"]]", setting["value"])
if ("number")
setting["value"] = input(user, "Enter new value for [setting["desc"]]", "Enter new value for [setting["desc"]]") as num
if ("color")
setting["value"] = input(user, "Enter new value for [setting["desc"]]", "Enter new value for [setting["desc"]]", setting["value"]) as color
if ("boolean")
setting["value"] = (setting["value"] == "Yes") ? "No" : "Yes"
if ("ckey")
setting["value"] = input(user, "[setting["desc"]]?") in (list("none") + GLOB.directory)
if (setting["callback"])
var/datum/callback/callback = setting["callback"]
settings = callback.Invoke(settings)
if (href_list["button"])
var/button = text2num(href_list["button"])
if (button <= 3 && button >= 1)
selected_button = button
if (selected_button != 1)
set_content(show_choices(user))
open()
return
open_time = 0
close()
/proc/present_pref_like_picker(mob/user, message, title, steal_focus = TRUE, timeout = 600 SECONDS, list/settings, width, height)
if (!ismob(user))
if (!istype(user, /client))
return
var/client/user_client = user
user = user_client.mob
var/datum/browser/modal/pref_like_picker/window = new(user, message, title, steal_focus, timeout, settings, width, height)
window.open()
window.wait()
if (window.selected_button)
return list("button" = window.selected_button, "settings" = window.settings)
/// Registers the on-close verb for a browse window (client/verb/windowclose)
/// this will be called when the close-button of a window is pressed.
///
/// This is usually only needed for devices that regularly update the browse window,
/// e.g. canisters, timers, etc.
///
/// windowid should be the specified window name
/// e.g. code is : user << browse(text, "window=fred")
/// then use : onclose(user, "fred")
///
/// Optionally, specify the "source" parameter as the controlled atom (usually src)
// to pass a "close=1" parameter to the atom's Topic() proc for special handling.
/// Otherwise, the user mob's machine var will be reset directly.
///
/proc/onclose(mob/user, windowid, atom/source = null)
if(!user.client)
return
var/param = "null"
if(ref)
param = "[REF(ref)]"
if(source)
param = "[REF(source)]"
winset(user, windowid, "on-close=\".windowclose [param]\"")
// the on-close client verb
// called when a browser popup window is closed after registering with proc/onclose()
// if a valid atom reference is supplied, call the atom's Topic() with "close=1"
// otherwise, just reset the client mob's machine var.
//
/// the on-close client verb
/// called when a browser popup window is closed after registering with proc/onclose()
/// if a valid atom reference is supplied, call the atom's Topic() with "close=1"
/// otherwise, just reset the client mob's machine var.
/client/verb/windowclose(atomref as text)
set hidden = TRUE // hide this verb from the user's panel
set name = ".windowclose" // no autocomplete on cmd line
if(atomref != "null") // if passed a real atomref
var/hsrc = locate(atomref) // find the reffed atom
var/href = "close=1"
if(hsrc)
usr = src.mob
src.Topic(href, params2list(href), hsrc) // this will direct to the atom's
return // Topic() proc via client.Topic()
if(atomref == "null")
return
// if passed a real atomref
var/atom/hsrc = locate(atomref) // find the reffed atom
var/href = "close=1"
if(!hsrc)
return
usr = src.mob
src.Topic(href, params2list(href), hsrc) // this will direct to the atom's
/datum/browser/modal/color_matrix_picker
var/color_matrix
@@ -426,12 +549,12 @@
/datum/browser/modal/color_matrix_picker/Topic(href, list/href_list)
if(href_list["close"] || !user)
opentime = 0
open_time = 0
return
if(href_list["button"])
var/button = text2num(href_list["button"])
if(ISINRANGE(button, 1, 3))
selectedbutton = button
selected_button = button
var/list/cm = rgb_construct_color_matrix(
text2num(href_list["rr"]),
text2num(href_list["rg"]),
@@ -448,7 +571,7 @@
)
if(cm)
color_matrix = cm
opentime = 0
open_time = 0
close()
/proc/color_matrix_picker(mob/user, message, title, button1 = "Ok", button2, button3, stealfocus, timeout = 10 MINUTES, list/values)
@@ -461,4 +584,4 @@
var/datum/browser/modal/color_matrix_picker/B = new(user, message, title, button1, button2, button3, stealfocus, timeout, values)
B.open()
B.wait()
return list("button" = B.selectedbutton, "matrix" = B.color_matrix)
return list("button" = B.selected_button, "matrix" = B.color_matrix)

View File

@@ -114,7 +114,10 @@
if(ambitions)
output += "<HR><B>Ambitions:</B> [ambitions]<br>"
recipient << browse("<html>[output]</html>","window=memory")
var/datum/browser/popup = new(recipient, "memory", "Memory")
popup.set_content(output)
popup.open()
/datum/mind/proc/edit_memory()
if(!ticker || !ticker.mode)
@@ -149,7 +152,10 @@
out += "None."
out += "<br><a href='byond://?src=\ref[src];[HrefToken()];obj_add=1'>\[add\]</a><br><br>"
out += span_bold("Ambitions:") + " [ambitions ? ambitions : "None"] <a href='byond://?src=\ref[src];[HrefToken()];amb_edit=\ref[src]'>\[edit\]</a></br>"
usr << browse("<html>[out]</html>", "window=edit_memory[src]")
var/datum/browser/popup = new(usr, "edit_memory[src]", "Edit Memory")
popup.set_content(out)
popup.open()
/datum/mind/Topic(href, href_list)
if(!check_rights(R_ADMIN|R_FUN|R_EVENT)) return