merge oracle ui from kepler
This commit is contained in:
@@ -6,7 +6,17 @@ SUBSYSTEM_DEF(assets)
|
||||
var/list/preload = list()
|
||||
|
||||
/datum/controller/subsystem/assets/Initialize(timeofday)
|
||||
for(var/type in typesof(/datum/asset))
|
||||
|
||||
var/list/priority_assets = list(
|
||||
/datum/asset/simple/oui_theme_nano,
|
||||
/datum/asset/simple/goonchat
|
||||
)
|
||||
|
||||
for(var/type in priority_assets)
|
||||
var/datum/asset/A = new type()
|
||||
A.register()
|
||||
|
||||
for(var/type in typesof(/datum/asset) - (priority_assets | list(/datum/asset, /datum/asset/simple)))
|
||||
var/datum/asset/A = type
|
||||
if (type != initial(A._abstract))
|
||||
get_asset_datum(type)
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
var/spam_flag = 0
|
||||
var/contact_poison // Reagent ID to transfer on contact
|
||||
var/contact_poison_volume = 0
|
||||
var/datum/oracle_ui/ui = null
|
||||
|
||||
|
||||
/obj/item/paper/pickup(user)
|
||||
@@ -40,16 +41,40 @@
|
||||
if(!istype(G) || G.transfer_prints)
|
||||
H.reagents.add_reagent(contact_poison,contact_poison_volume)
|
||||
contact_poison = null
|
||||
ui.check_view_all()
|
||||
..()
|
||||
|
||||
/obj/item/paper/dropped(mob/user)
|
||||
ui.check_view(user)
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/item/paper/Initialize()
|
||||
. = ..()
|
||||
pixel_y = rand(-8, 8)
|
||||
pixel_x = rand(-9, 9)
|
||||
ui = new /datum/oracle_ui(src, 420, 600, get_asset_datum(/datum/asset/spritesheet/simple/paper))
|
||||
ui.can_resize = FALSE
|
||||
update_icon()
|
||||
updateinfolinks()
|
||||
|
||||
/obj/item/paper/oui_getcontent(mob/target)
|
||||
if(!target.is_literate())
|
||||
return "<HTML><HEAD><TITLE>[name]</TITLE></HEAD><BODY>[stars(info)]<HR>[stamps]</BODY></HTML>"
|
||||
else if(istype(target.get_active_held_item(), /obj/item/pen) | istype(target.get_active_held_item(), /obj/item/toy/crayon))
|
||||
return "<HTML><HEAD><TITLE>[name]</TITLE></HEAD><BODY>[info_links]<HR>[stamps]</BODY></HTML>"
|
||||
else
|
||||
return "<HTML><HEAD><TITLE>[name]</TITLE></HEAD><BODY>[info]<HR>[stamps]</BODY></HTML>"
|
||||
|
||||
/obj/item/paper/oui_canview(mob/target)
|
||||
if(check_rights_for(target.client, R_FUN)) //Allows admins to view faxes
|
||||
return TRUE
|
||||
if(isAI(target))
|
||||
var/mob/living/silicon/ai/ai = target
|
||||
return get_dist(src, ai.current) < 2
|
||||
if(iscyborg(target))
|
||||
return get_dist(src, target) < 2
|
||||
return ..()
|
||||
|
||||
/obj/item/paper/update_icon()
|
||||
|
||||
@@ -65,20 +90,13 @@
|
||||
/obj/item/paper/examine(mob/user)
|
||||
..()
|
||||
to_chat(user, "<span class='notice'>Alt-click to fold it.</span>")
|
||||
|
||||
var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/simple/paper)
|
||||
assets.send(user)
|
||||
|
||||
if(in_range(user, src) || isobserver(user))
|
||||
if(user.is_literate())
|
||||
user << browse("<HTML><HEAD><TITLE>[name]</TITLE></HEAD><BODY>[info]<HR>[stamps]</BODY></HTML>", "window=[name]")
|
||||
onclose(user, "[name]")
|
||||
else
|
||||
user << browse("<HTML><HEAD><TITLE>[name]</TITLE></HEAD><BODY>[stars(info)]<HR>[stamps]</BODY></HTML>", "window=[name]")
|
||||
onclose(user, "[name]")
|
||||
if(oui_canview(user))
|
||||
ui.render(user)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You're too far away to read it!</span>")
|
||||
|
||||
/obj/item/paper/proc/show_content(mob/user)
|
||||
user.examinate(src)
|
||||
|
||||
/obj/item/paper/verb/rename()
|
||||
set name = "Rename paper"
|
||||
@@ -98,7 +116,7 @@
|
||||
if((loc == usr && usr.stat == CONSCIOUS))
|
||||
name = "paper[(n_name ? text("- '[n_name]'") : null)]"
|
||||
add_fingerprint(usr)
|
||||
|
||||
ui.render_all()
|
||||
|
||||
/obj/item/paper/suicide_act(mob/user)
|
||||
user.visible_message("<span class='suicide'>[user] scratches a grid on [user.p_their()] wrist with the paper! It looks like [user.p_theyre()] trying to commit sudoku...</span>")
|
||||
@@ -108,7 +126,7 @@
|
||||
spam_flag = FALSE
|
||||
|
||||
/obj/item/paper/attack_self(mob/user)
|
||||
user.examinate(src)
|
||||
show_content(user)
|
||||
if(rigged && (SSevents.holidays && SSevents.holidays[APRIL_FOOLS]))
|
||||
if(!spam_flag)
|
||||
spam_flag = TRUE
|
||||
@@ -123,11 +141,9 @@
|
||||
else //cyborg or AI not seeing through a camera
|
||||
dist = get_dist(src, user)
|
||||
if(dist < 2)
|
||||
usr << browse("<HTML><HEAD><TITLE>[name]</TITLE></HEAD><BODY>[info]<HR>[stamps]</BODY></HTML>", "window=[name]")
|
||||
onclose(usr, "[name]")
|
||||
show_content(user)
|
||||
else
|
||||
usr << browse("<HTML><HEAD><TITLE>[name]</TITLE></HEAD><BODY>[stars(info)]<HR>[stamps]</BODY></HTML>", "window=[name]")
|
||||
onclose(usr, "[name]")
|
||||
to_chat(user, "<span class='notice'>You can't quite see it.</span>")
|
||||
|
||||
|
||||
/obj/item/paper/proc/addtofield(id, text, links = 0)
|
||||
@@ -173,6 +189,7 @@
|
||||
for(var/i in 1 to min(fields, 15))
|
||||
addtofield(i, "<font face=\"[PEN_FONT]\"><A href='?src=[REF(src)];write=[i]'>write</A></font>", 1)
|
||||
info_links = info_links + "<font face=\"[PEN_FONT]\"><A href='?src=[REF(src)];write=end'>write</A></font>"
|
||||
ui.render_all()
|
||||
|
||||
|
||||
/obj/item/paper/proc/clearpaper()
|
||||
@@ -289,7 +306,7 @@
|
||||
|
||||
if(istype(P, /obj/item/pen) || istype(P, /obj/item/toy/crayon))
|
||||
if(user.is_literate())
|
||||
user << browse("<HTML><HEAD><TITLE>[name]</TITLE></HEAD><BODY>[info_links]<HR>[stamps]</BODY><div align='right'style='position:fixed;bottom:0;font-style:bold;'><A href='?src=[REF(src)];help=1'>\[?\]</A></div></HTML>", "window=[name]")
|
||||
show_content(user)
|
||||
return
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You don't know how to read or write.</span>")
|
||||
@@ -312,6 +329,7 @@
|
||||
add_overlay(stampoverlay)
|
||||
|
||||
to_chat(user, "<span class='notice'>You stamp the paper with your rubber stamp.</span>")
|
||||
ui.render_all()
|
||||
|
||||
if(P.is_hot())
|
||||
if(HAS_TRAIT(user, TRAIT_CLUMSY) && prob(10))
|
||||
|
||||
@@ -264,6 +264,13 @@
|
||||
name = "disposal unit"
|
||||
desc = "A pneumatic waste disposal unit."
|
||||
icon_state = "disposal"
|
||||
var/datum/oracle_ui/themed/nano/ui
|
||||
|
||||
/obj/machinery/disposal/bin/Initialize(mapload, obj/structure/disposalconstruct/make_from)
|
||||
. = ..()
|
||||
ui = new /datum/oracle_ui/themed/nano(src, 330, 190, "disposal_bin")
|
||||
ui.auto_refresh = TRUE
|
||||
ui.can_resize = FALSE
|
||||
|
||||
// attack by item places it in to disposal
|
||||
/obj/machinery/disposal/bin/attackby(obj/item/I, mob/user, params)
|
||||
@@ -275,32 +282,43 @@
|
||||
STR.remove_from_storage(O,src)
|
||||
T.update_icon()
|
||||
update_icon()
|
||||
ui.soft_update_fields()
|
||||
else
|
||||
ui.soft_update_fields()
|
||||
return ..()
|
||||
|
||||
// handle machine interaction
|
||||
|
||||
/obj/machinery/disposal/bin/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
|
||||
/obj/machinery/disposal/bin/ui_interact(mob/user, state)
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "disposal_unit", name, 300, 200, master_ui, state)
|
||||
ui.open()
|
||||
if(user.loc == src)
|
||||
to_chat(user, "<span class='warning'>You cannot reach the controls from inside!</span>")
|
||||
return
|
||||
ui.render(user)
|
||||
|
||||
/obj/machinery/disposal/bin/ui_data(mob/user)
|
||||
/obj/machinery/disposal/bin/oui_canview(mob/user)
|
||||
if(user.loc == src)
|
||||
return FALSE
|
||||
if(stat & BROKEN)
|
||||
return FALSE
|
||||
if(Adjacent(user))
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/machinery/disposal/bin/oui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["flush"] = flush
|
||||
data["full_pressure"] = full_pressure
|
||||
data["pressure_charging"] = pressure_charging
|
||||
data["panel_open"] = panel_open
|
||||
var/per = CLAMP(100* air_contents.return_pressure() / (SEND_PRESSURE), 0, 100)
|
||||
data["per"] = round(per, 1)
|
||||
data["flush"] = flush ? ui.act("Disengage", user, "handle-0", class="active") : ui.act("Engage", user, "handle-1")
|
||||
data["full_pressure"] = full_pressure ? "Ready" : (pressure_charging ? "Pressurizing" : "Off")
|
||||
data["pressure_charging"] = pressure_charging ? ui.act("Turn Off", user, "pump-0", class="active", disabled=full_pressure) : ui.act("Turn On", user, "pump-1", disabled=full_pressure)
|
||||
var/per = full_pressure ? 100 : CLAMP(100* air_contents.return_pressure() / (SEND_PRESSURE), 0, 99)
|
||||
data["per"] = "[round(per, 1)]%"
|
||||
data["contents"] = ui.act("Eject Contents", user, "eject", disabled=contents.len < 1)
|
||||
data["isai"] = isAI(user)
|
||||
return data
|
||||
|
||||
/obj/machinery/disposal/bin/ui_act(action, params)
|
||||
/obj/machinery/disposal/bin/oui_act(mob/user, action, list/params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
@@ -327,6 +345,7 @@
|
||||
if("eject")
|
||||
eject()
|
||||
. = TRUE
|
||||
ui.soft_update_fields()
|
||||
|
||||
|
||||
/obj/machinery/disposal/bin/hitby(atom/movable/AM)
|
||||
@@ -346,6 +365,7 @@
|
||||
full_pressure = FALSE
|
||||
pressure_charging = TRUE
|
||||
update_icon()
|
||||
ui.soft_update_fields()
|
||||
|
||||
/obj/machinery/disposal/bin/update_icon()
|
||||
cut_overlays()
|
||||
@@ -389,7 +409,7 @@
|
||||
do_flush()
|
||||
flush_count = 0
|
||||
|
||||
updateDialog()
|
||||
ui.soft_update_fields()
|
||||
|
||||
if(flush && air_contents.return_pressure() >= SEND_PRESSURE) // flush can happen even without power
|
||||
do_flush()
|
||||
|
||||
233
modular_kepler/code/modules/oracle_ui/README.md
Normal file
233
modular_kepler/code/modules/oracle_ui/README.md
Normal file
@@ -0,0 +1,233 @@
|
||||
# `/datum/oracle_ui`
|
||||
|
||||
This datum is a replacement for tgui which does not use any Node.js dependencies, and works entirely through raw HTML, JS and CSS. It's designed to be reasonably easy to port something from tgui to oracle_ui.
|
||||
|
||||
### How to create a UI
|
||||
|
||||
For this example, we're going to port the disposals bin from tgui to oracle_ui.
|
||||
|
||||
#### Step 1
|
||||
|
||||
In order to create a UI, you will first need to create an instance of `/datum/oracle_ui` or one of its subclasses, in this case `/datum/oracle_ui/themed/nano`.
|
||||
|
||||
You need to pass in `src`, the width of the window, the height of the window, and the template to render from. You can optionally set some flags to disallow window resizing and whether to automatically refresh the UI.
|
||||
|
||||
`code/modules/recycling/disposal-unit.dm`
|
||||
```dm
|
||||
/obj/machinery/disposal/bin/Initialize(mapload, obj/structure/disposalconstruct/make_from)
|
||||
. = ..()
|
||||
ui = new /datum/oracle_ui/themed/nano(src, 330, 190, "disposal_bin")
|
||||
ui.auto_refresh = TRUE
|
||||
ui.can_resize = FALSE
|
||||
```
|
||||
|
||||
#### Step 2
|
||||
|
||||
You will now need to make a template in `modular_kepler/html/oracle_ui/content/{template_name}`.
|
||||
|
||||
Values defined as `@{value}` will get replaced at runtime by oracle_ui.
|
||||
|
||||
`modular_kepler/html/oracle_ui/content/disposal_bin/index.html`
|
||||
```html
|
||||
<div class='display'>
|
||||
<section>
|
||||
<span class='label'>State:</span>
|
||||
<div class='content' id="full_pressure">@{full_pressure}</div>
|
||||
</section>
|
||||
<section>
|
||||
<span class='label'>Pressure:</span>
|
||||
<div class='content'>
|
||||
<div class='progressBar' id='per'>
|
||||
<div class='progressFill' style="width: @{per}"></div>
|
||||
<div class='progressLabel'>@{per}</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section>
|
||||
<span class='label'>Handle:</span>
|
||||
<div class='content' id="flush">@{flush}</div>
|
||||
</section>
|
||||
<section>
|
||||
<span class='label'>Eject:</span>
|
||||
<div class='content' id="contents">@{contents}</div>
|
||||
</section>
|
||||
<section>
|
||||
<span class='label'>Compressor:</span>
|
||||
<div class='content' id="pressure_charging">@{pressure_charging}</div>
|
||||
</section>
|
||||
</div>
|
||||
```
|
||||
|
||||
#### Step 3
|
||||
|
||||
Now you need to implement the methods that provide data to oracle_ui. `oui_data` can be adapted from the `ui_data` proc that tgui uses.
|
||||
|
||||
The `act` proc generates a hyperlink that will result in `oui_act` getting called on your object when clicked. The `class` argument defines a css class to be added to the hyperlink, and disabled determines whether the hyperlink will be disabled or not.
|
||||
|
||||
Calling `soft_update_fields` will result in the UI being updated on all clients, which is useful when the object changes state.
|
||||
|
||||
`code/modules/recycling/disposal-unit.dm`
|
||||
```dm
|
||||
/obj/machinery/disposal/bin/oui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["flush"] = flush ? ui.act("Disengage", user, "handle-0", class="active") : ui.act("Engage", user, "handle-1")
|
||||
data["full_pressure"] = full_pressure ? "Ready" : (pressure_charging ? "Pressurizing" : "Off")
|
||||
data["pressure_charging"] = pressure_charging ? ui.act("Turn Off", user, "pump-0", class="active", disabled=full_pressure) : ui.act("Turn On", user, "pump-1", disabled=full_pressure)
|
||||
var/per = full_pressure ? 100 : Clamp(100* air_contents.return_pressure() / (SEND_PRESSURE), 0, 99)
|
||||
data["per"] = "[round(per, 1)]%"
|
||||
data["contents"] = ui.act("Eject Contents", user, "eject", disabled=contents.len < 1)
|
||||
data["isai"] = isAI(user)
|
||||
return data
|
||||
/obj/machinery/disposal/bin/oui_act(mob/user, action, list/params)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("handle-0")
|
||||
flush = FALSE
|
||||
update_icon()
|
||||
. = TRUE
|
||||
if("handle-1")
|
||||
if(!panel_open)
|
||||
flush = TRUE
|
||||
update_icon()
|
||||
. = TRUE
|
||||
if("pump-0")
|
||||
if(pressure_charging)
|
||||
pressure_charging = FALSE
|
||||
update_icon()
|
||||
. = TRUE
|
||||
if("pump-1")
|
||||
if(!pressure_charging)
|
||||
pressure_charging = TRUE
|
||||
update_icon()
|
||||
. = TRUE
|
||||
if("eject")
|
||||
eject()
|
||||
. = TRUE
|
||||
ui.soft_update_fields()
|
||||
```
|
||||
|
||||
#### Step 4
|
||||
|
||||
You now need to hook in and ensure oracle_ui is invoked upon clicking. `render` should be used to open the UI for a user, typically on click.
|
||||
|
||||
`code/modules/recycling/disposal-unit.dm`
|
||||
```dm
|
||||
/obj/machinery/disposal/bin/ui_interact(mob/user, state)
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
if(user.loc == src)
|
||||
to_chat(user, "<span class='warning'>You cannot reach the controls from inside!</span>")
|
||||
return
|
||||
ui.render(user)
|
||||
```
|
||||
|
||||
#### Done
|
||||
|
||||

|
||||
|
||||
You should have a functional UI at this point. Some additional odds and ends can be discovered throughout `code/modules/recycling/disposal-unit.dm`. For a full diff of the changes made to it, refer to [the original pull request on GitHub](https://github.com/OracleStation/OracleStation/pull/702/files#diff-4b6c20ec7d37222630e7524d9577e230).
|
||||
|
||||
### API Reference
|
||||
|
||||
#### `/datum/oracle_ui`
|
||||
|
||||
The main datum which handles the UI.
|
||||
|
||||
##### `get_content(mob/target)`
|
||||
Returns the HTML that should be displayed for a specified target mob. Calls `oui_getcontent` on the datasource to get the return value. *This proc is not used in the themed subclass.*
|
||||
|
||||
##### `can_view(mob/target)`
|
||||
Returns whether the specified target mob can view the UI. Calls `oui_canview` on the datasource to get the return value.
|
||||
|
||||
##### `test_viewer(mob/target, updating)`
|
||||
Tests whether the client is valid and can view the UI. If updating is TRUE, checks to see if they still have the UI window open.
|
||||
|
||||
##### `render(mob/target, updating = FALSE)`
|
||||
Opens the UI for a target mob, sending HTML. If updating is TRUE, will only do it to clients which still have the window open.
|
||||
|
||||
##### `render_all()`
|
||||
Does the above, but for all viewers and with updating set to TRUE.
|
||||
|
||||
##### `close(mob/target)`
|
||||
Closes the UI for the specified target mob.
|
||||
|
||||
##### `close_all()`
|
||||
Does the above, but for all viewers.
|
||||
|
||||
##### `check_view(mob/target)`
|
||||
Checks if the specified target mob can view the UI, and if they can't closes their UI
|
||||
|
||||
##### `check_view_all()`
|
||||
Does the above, but for all viewers.
|
||||
|
||||
##### `call_js(mob/target, js_func, list/parameters = list())`
|
||||
Invokes `js_func` in the UI of the specified target mob with the specified parameters.
|
||||
|
||||
##### `call_js_all(js_func, list/parameters = list()))`
|
||||
Does the above, but for all viewers.
|
||||
|
||||
##### `steal_focus(mob/target)`
|
||||
Causes the UI to steal focus for the specified target mob.
|
||||
|
||||
##### `steal_focus_all()`
|
||||
Does the above, but for all viewers.
|
||||
|
||||
##### `flash(mob/target, times = -1)`
|
||||
Causes the UI to flash for the specified target mob the specified number of times, the default keeps the element flashing until focused.
|
||||
|
||||
##### `flash_all()`
|
||||
Does the above, but for all viewers.
|
||||
|
||||
##### `href(mob/user, action, list/parameters = list())`
|
||||
Generates a href for the specified user which will invoke `oui_act` on the datasource with the specified action and parameters.
|
||||
|
||||
#### `/datum/oracle_ui/themed`
|
||||
|
||||
A subclass which supports templating and theming.
|
||||
|
||||
##### `get_file(path)`
|
||||
Loads a file from disk and returns the contents. Caches files loaded from disk for you.
|
||||
|
||||
##### `get_content_file(filename)`
|
||||
Loads a file from the current content folder and returns the contents.
|
||||
|
||||
##### `get_themed_file(filename)`
|
||||
Loads a file from the current theme folder and returns the contents.
|
||||
|
||||
##### `process_template(template, variables)`
|
||||
Processes a template and populates it with the provided variables.
|
||||
|
||||
##### `get_inner_content(mob/target)`
|
||||
Returns the templated content to be inserted into the main template for the specified target mob.
|
||||
|
||||
##### `soft_update_fields()`
|
||||
For all viewers, updates the fields in the template via the `updateFields` javaScript function.
|
||||
|
||||
##### `soft_update_all()`
|
||||
For all viewers, updates the content body in the template via the `replaceContent` javaScript function.
|
||||
|
||||
##### `change_page(var/newpage)`
|
||||
Changes the template to use to draw the page and forces an update to all viewers
|
||||
|
||||
##### `act(label, mob/user, action, list/parameters = list(), class = "", disabled = FALSE`
|
||||
Returns a fully formatted hyperlink for the specified user. `label` will be the hyperlink label, `action` and `parameters` are what will be passed to `oui_act`, `class` is any CSS classes to apply to the hyperlink and `disabled` will disable the hyperlink.
|
||||
|
||||
#### `/datum`
|
||||
|
||||
Functions built into all objects to support oracle_ui. There are default implementations for most major superclasses.
|
||||
|
||||
##### `oui_canview(mob/user)`
|
||||
Returns whether the specified user view the UI at this time.
|
||||
|
||||
##### `oui_getcontent(mob/user)`
|
||||
Returns the raw HTML to be sent to the specified user. *This proc is not used in the themed subclass of oracle_ui.*
|
||||
|
||||
##### `oui_data(mob/user)`
|
||||
Returns templating data for the specified user. *This proc is only used in the themed subclass of oracle_ui.*
|
||||
|
||||
##### `oui_data_debug(mob/user)`
|
||||
Returns the above, but JSON-encoded and escaped, for copy pasting into the web IDE. *This proc is only used for debugging purposes.*
|
||||
|
||||
##### `oui_act(mob/user, action, list/params)`
|
||||
Called when a hyperlink is clicked in the UI.
|
||||
9
modular_kepler/code/modules/oracle_ui/assets.dm
Normal file
9
modular_kepler/code/modules/oracle_ui/assets.dm
Normal file
@@ -0,0 +1,9 @@
|
||||
/datum/asset/simple/oui_theme_nano
|
||||
assets = list(
|
||||
// JavaScript
|
||||
"sui-nano-common.js" = 'modular_kepler/html/oracle_ui/themes/nano/sui-nano-common.js',
|
||||
"sui-nano-jquery.min.js" = 'modular_kepler/html/oracle_ui/themes/nano/sui-nano-jquery.min.js',
|
||||
// Stylesheets
|
||||
"sui-nano-common.css" = 'modular_kepler/html/oracle_ui/themes/nano/sui-nano-common.css',
|
||||
)
|
||||
|
||||
44
modular_kepler/code/modules/oracle_ui/hookup_procs.dm
Normal file
44
modular_kepler/code/modules/oracle_ui/hookup_procs.dm
Normal file
@@ -0,0 +1,44 @@
|
||||
/datum/proc/oui_canview(mob/user)
|
||||
return TRUE
|
||||
|
||||
/datum/proc/oui_getcontent(mob/user)
|
||||
return "Default Implementation"
|
||||
|
||||
/datum/proc/oui_canuse(mob/user)
|
||||
if(isobserver(user) && !user.has_unlimited_silicon_privilege)
|
||||
return FALSE
|
||||
return oui_canview(user)
|
||||
|
||||
/datum/proc/oui_data(mob/user)
|
||||
return list()
|
||||
|
||||
/datum/proc/oui_data_debug(mob/user)
|
||||
return html_encode(json_encode(oui_data(user)))
|
||||
|
||||
/datum/proc/oui_act(mob/user, action, list/params)
|
||||
// No Implementation
|
||||
|
||||
/atom/oui_canview(mob/user)
|
||||
if(isobserver(user))
|
||||
return TRUE
|
||||
if(user.incapacitated())
|
||||
return FALSE
|
||||
if(isturf(src.loc) && Adjacent(user))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/oui_canview(mob/user)
|
||||
if(src.loc == user)
|
||||
return src in user.held_items
|
||||
return ..()
|
||||
|
||||
/obj/machinery/oui_canview(mob/user)
|
||||
if(user.has_unlimited_silicon_privilege)
|
||||
return TRUE
|
||||
if(!can_interact())
|
||||
return FALSE
|
||||
if(iscyborg(user))
|
||||
return can_see(user, src, 7)
|
||||
if(isAI(user))
|
||||
return GLOB.cameranet.checkTurfVis(get_turf_pixel(src))
|
||||
return ..()
|
||||
134
modular_kepler/code/modules/oracle_ui/oracle_ui.dm
Normal file
134
modular_kepler/code/modules/oracle_ui/oracle_ui.dm
Normal file
@@ -0,0 +1,134 @@
|
||||
/datum/oracle_ui
|
||||
var/width = 512
|
||||
var/height = 512
|
||||
var/can_close = TRUE
|
||||
var/can_minimize = FALSE
|
||||
var/can_resize = TRUE
|
||||
var/titlebar = TRUE
|
||||
var/window_id = null
|
||||
var/viewers[0]
|
||||
var/auto_check_view = TRUE
|
||||
var/auto_refresh = FALSE
|
||||
var/atom/datasource = null
|
||||
var/datum/asset/assets = null
|
||||
|
||||
/datum/oracle_ui/New(atom/n_datasource, n_width = 512, n_height = 512, n_assets = null)
|
||||
datasource = n_datasource
|
||||
window_id = REF(src)
|
||||
width = n_width
|
||||
height = n_height
|
||||
|
||||
/datum/oracle_ui/Destroy()
|
||||
close_all()
|
||||
if(src.datum_flags & DF_ISPROCESSING)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/datum/oracle_ui/process()
|
||||
if(auto_check_view)
|
||||
check_view_all()
|
||||
if(auto_refresh)
|
||||
render_all()
|
||||
|
||||
/datum/oracle_ui/proc/get_content(mob/target)
|
||||
return call(datasource, "oui_getcontent")(target)
|
||||
|
||||
/datum/oracle_ui/proc/can_view(mob/target)
|
||||
return call(datasource, "oui_canview")(target)
|
||||
|
||||
/datum/oracle_ui/proc/test_viewer(mob/target, updating)
|
||||
//If the target is null or does not have a client, remove from viewers and return
|
||||
if(!target | !target.client | !can_view(target))
|
||||
viewers -= target
|
||||
if(viewers.len < 1 && (src.datum_flags & DF_ISPROCESSING))
|
||||
STOP_PROCESSING(SSobj, src) //No more viewers, stop polling
|
||||
close(target)
|
||||
return FALSE
|
||||
//If this is an update, and they have closed the window, remove from viewers and return
|
||||
if(updating && winget(target, window_id, "is-visible") != "true")
|
||||
viewers -= target
|
||||
if(viewers.len < 1 && (src.datum_flags & DF_ISPROCESSING))
|
||||
STOP_PROCESSING(SSobj, src) //No more viewers, stop polling
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/oracle_ui/proc/render(mob/target, updating = FALSE)
|
||||
set waitfor = FALSE //Makes this an async call
|
||||
if(!can_view(target))
|
||||
return
|
||||
//Check to see if they have the window open still if updating
|
||||
if(updating && !test_viewer(target, updating))
|
||||
return
|
||||
//Send assets
|
||||
if(!updating && assets)
|
||||
assets.send(target)
|
||||
//Add them to the viewers if they aren't there already
|
||||
viewers |= target
|
||||
if(!(src.datum_flags & DF_ISPROCESSING) && (auto_refresh | auto_check_view))
|
||||
START_PROCESSING(SSobj, src) //Start processing to poll for viewability
|
||||
//Send the content
|
||||
if(updating)
|
||||
target << output(get_content(target), "[window_id].browser")
|
||||
else
|
||||
target << browse(get_content(target), "window=[window_id];size=[width]x[height];can_close=[can_close];can_minimize=[can_minimize];can_resize=[can_resize];titlebar=[titlebar];focus=false;")
|
||||
steal_focus(target)
|
||||
|
||||
/datum/oracle_ui/proc/render_all()
|
||||
for(var/viewer in viewers)
|
||||
render(viewer, TRUE)
|
||||
|
||||
/datum/oracle_ui/proc/close(mob/target)
|
||||
if(target && target.client)
|
||||
target << browse(null, "window=[window_id]")
|
||||
|
||||
/datum/oracle_ui/proc/close_all()
|
||||
for(var/viewer in viewers)
|
||||
close(viewer)
|
||||
viewers = list()
|
||||
|
||||
/datum/oracle_ui/proc/check_view_all()
|
||||
for(var/viewer in viewers)
|
||||
check_view(viewer)
|
||||
|
||||
/datum/oracle_ui/proc/check_view(mob/target)
|
||||
set waitfor = FALSE //Makes this an async call
|
||||
if(!test_viewer(target, TRUE))
|
||||
close(target)
|
||||
|
||||
/datum/oracle_ui/proc/call_js(mob/target, js_func, list/parameters = list())
|
||||
set waitfor = FALSE //Makes this an async call
|
||||
if(!test_viewer(target, TRUE))
|
||||
return
|
||||
target << output(list2params(parameters),"[window_id].browser:[js_func]")
|
||||
|
||||
/datum/oracle_ui/proc/call_js_all(js_func, list/parameters = list())
|
||||
for(var/viewer in viewers)
|
||||
call_js(viewer, js_func, parameters)
|
||||
|
||||
/datum/oracle_ui/proc/steal_focus(mob/target)
|
||||
set waitfor = FALSE //Makes this an async call
|
||||
winset(target, "[window_id]","focus=true")
|
||||
|
||||
/datum/oracle_ui/proc/steal_focus_all()
|
||||
for(var/viewer in viewers)
|
||||
steal_focus(viewer)
|
||||
|
||||
/datum/oracle_ui/proc/flash(mob/target, times = -1)
|
||||
set waitfor = FALSE //Makes this an async call
|
||||
winset(target, "[window_id]","flash=[times]")
|
||||
|
||||
/datum/oracle_ui/proc/flash_all(times = -1)
|
||||
for(var/viewer in viewers)
|
||||
flash(viewer, times)
|
||||
|
||||
/datum/oracle_ui/proc/href(mob/user, action, list/parameters = list())
|
||||
var/params_string = replacetext(list2params(parameters),"&",";")
|
||||
return "?src=[REF(src)];sui_action=[action];sui_user=[REF(user)];[params_string]"
|
||||
|
||||
/datum/oracle_ui/Topic(href, parameters)
|
||||
var/action = parameters["sui_action"]
|
||||
var/mob/current_user = locate(parameters["sui_user"])
|
||||
if(!call(datasource, "oui_canuse")(current_user))
|
||||
return
|
||||
if(datasource)
|
||||
call(datasource, "oui_act")(current_user, action, parameters);
|
||||
82
modular_kepler/code/modules/oracle_ui/themed.dm
Normal file
82
modular_kepler/code/modules/oracle_ui/themed.dm
Normal file
@@ -0,0 +1,82 @@
|
||||
/datum/oracle_ui/themed
|
||||
var/theme = ""
|
||||
var/content_root = ""
|
||||
var/current_page = "index.html"
|
||||
var/root_template = ""
|
||||
|
||||
/datum/oracle_ui/themed/New(atom/n_datasource, n_width = 512, n_height = 512, n_content_root = "")
|
||||
root_template = get_themed_file("index.html")
|
||||
content_root = n_content_root
|
||||
return ..(n_datasource, n_width, n_height, get_asset_datum(/datum/asset/simple/oui_theme_nano))
|
||||
|
||||
/datum/oracle_ui/themed/process()
|
||||
if(auto_check_view)
|
||||
check_view_all()
|
||||
if(auto_refresh)
|
||||
soft_update_fields()
|
||||
|
||||
GLOBAL_LIST_EMPTY(oui_template_variables)
|
||||
GLOBAL_LIST_EMPTY(oui_file_cache)
|
||||
|
||||
/datum/oracle_ui/themed/proc/get_file(path)
|
||||
if(GLOB.oui_file_cache[path])
|
||||
return GLOB.oui_file_cache[path]
|
||||
else if(fexists(path))
|
||||
var/data = file2text(path)
|
||||
GLOB.oui_file_cache[path] = data
|
||||
return data
|
||||
else
|
||||
var/errormsg = "MISSING PATH '[path]'"
|
||||
#ifndef UNIT_TESTS
|
||||
log_world(errormsg) //Because Travis absolutely hates these procs
|
||||
#endif
|
||||
return errormsg
|
||||
|
||||
/datum/oracle_ui/themed/proc/get_content_file(filename)
|
||||
return get_file("./modular_kepler/html/oracle_ui/content/[content_root]/[filename]")
|
||||
|
||||
/datum/oracle_ui/themed/proc/get_themed_file(filename)
|
||||
return get_file("./modular_kepler/html/oracle_ui/themes/[theme]/[filename]")
|
||||
|
||||
/datum/oracle_ui/themed/proc/process_template(template, variables)
|
||||
var/regex/pattern = regex("\\@\\{(\\w+)\\}","gi")
|
||||
GLOB.oui_template_variables = variables
|
||||
var/replaced = pattern.Replace(template, /proc/oui_process_template_replace)
|
||||
GLOB.oui_template_variables = null
|
||||
return replaced
|
||||
|
||||
/proc/oui_process_template_replace(match, group1)
|
||||
var/value = GLOB.oui_template_variables[group1]
|
||||
return "[value]"
|
||||
|
||||
/datum/oracle_ui/themed/proc/get_inner_content(mob/target)
|
||||
var/list/data = call(datasource, "oui_data")(target)
|
||||
return process_template(get_content_file(current_page), data)
|
||||
|
||||
/datum/oracle_ui/themed/get_content(mob/target)
|
||||
var/list/template_data = list("title" = datasource.name, "body" = get_inner_content(target))
|
||||
return process_template(root_template, template_data)
|
||||
|
||||
/datum/oracle_ui/themed/proc/soft_update_fields()
|
||||
for(var/viewer in viewers)
|
||||
var/json = json_encode(call(datasource, "oui_data")(viewer))
|
||||
call_js(viewer, "updateFields", list(json))
|
||||
|
||||
/datum/oracle_ui/themed/proc/soft_update_all()
|
||||
for(var/viewer in viewers)
|
||||
call_js(viewer, "replaceContent", list(get_inner_content(viewer)))
|
||||
|
||||
/datum/oracle_ui/themed/proc/change_page(newpage)
|
||||
if(newpage == current_page)
|
||||
return
|
||||
current_page = newpage
|
||||
render_all()
|
||||
|
||||
/datum/oracle_ui/themed/proc/act(label, mob/user, action, list/parameters = list(), class = "", disabled = FALSE)
|
||||
if(disabled)
|
||||
return "<a class=\"disabled\">[label]</a>"
|
||||
else
|
||||
return "<a class=\"[class]\" href=\"" + href(user, action, parameters) + "\">[label]</a>"
|
||||
|
||||
/datum/oracle_ui/themed/nano
|
||||
theme = "nano"
|
||||
@@ -0,0 +1,27 @@
|
||||
<div class='display'>
|
||||
<section>
|
||||
<span class='label'>State:</span>
|
||||
<div class='content' id="full_pressure">@{full_pressure}</div>
|
||||
</section>
|
||||
<section>
|
||||
<span class='label'>Pressure:</span>
|
||||
<div class='content'>
|
||||
<div class='progressBar' id='per'>
|
||||
<div class='progressFill' style="width: @{per}"></div>
|
||||
<div class='progressLabel'>@{per}</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section>
|
||||
<span class='label'>Handle:</span>
|
||||
<div class='content' id="flush">@{flush}</div>
|
||||
</section>
|
||||
<section>
|
||||
<span class='label'>Eject:</span>
|
||||
<div class='content' id="contents">@{contents}</div>
|
||||
</section>
|
||||
<section>
|
||||
<span class='label'>Compressor:</span>
|
||||
<div class='content' id="pressure_charging">@{pressure_charging}</div>
|
||||
</section>
|
||||
</div>
|
||||
103
modular_kepler/html/oracle_ui/editor_tool.html
Normal file
103
modular_kepler/html/oracle_ui/editor_tool.html
Normal file
@@ -0,0 +1,103 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>OracleUI IDE</title>
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
}
|
||||
h1 {
|
||||
margin: 5px;
|
||||
}
|
||||
#template_src_container {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: 0px;
|
||||
width: 50%;
|
||||
height: 75%;
|
||||
}
|
||||
#template_src {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
height: calc(100% - 60px);
|
||||
}
|
||||
#data_src_container {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: 75%;
|
||||
width: 50%;
|
||||
height: calc(25% - 20px);
|
||||
}
|
||||
#data_src {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
height: calc(100% - 50px);
|
||||
}
|
||||
#output_container {
|
||||
position: absolute;
|
||||
left: calc(50% + 20px);
|
||||
top: 0%;
|
||||
width: calc(50% - 50px);
|
||||
height: calc(100% - 20px);
|
||||
}
|
||||
#output_frame {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
left: 10px;
|
||||
width: 100%;
|
||||
height: calc(100% - 50px);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="template_src_container">
|
||||
<h1>Content Template:</h1>
|
||||
<textarea id="template_src" onchange="updateBody();" onkeyup="updateBody();" onpaste="updateBody();">
|
||||
<div class='display'>
|
||||
<section>
|
||||
<span class='label'>Key:</span>
|
||||
<div class='content' id="key">@{key}</div>
|
||||
</section>
|
||||
</div>
|
||||
</textarea>
|
||||
</div>
|
||||
<div id="data_src_container">
|
||||
<h1>Data:</h1>
|
||||
<textarea id="data_src" onchange="updateData();" onkeyup="updateData();" onpaste="updateData();">{"key":"value"}</textarea>
|
||||
</div>
|
||||
<div id="output_container">
|
||||
<h1>Output:</h1>
|
||||
<iframe name="output_frame" id="output_frame" onload="updateBody();"></iframe>
|
||||
</div>
|
||||
</body>
|
||||
<script type="text/javascript">
|
||||
function updateBody() {
|
||||
var body = document.getElementById('template_src').value
|
||||
var fields = JSON.parse(document.getElementById('data_src').value);
|
||||
for (var key in fields) {
|
||||
let value = fields[key];
|
||||
body = body.replace("@{" + key + "}", value)
|
||||
}
|
||||
var targetFrame = document.getElementById('output_frame')
|
||||
targetFrame.contentWindow.replaceContent(body);
|
||||
updateData();
|
||||
}
|
||||
function updateData() {
|
||||
var targetFrame = document.getElementById('output_frame');
|
||||
var json = document.getElementById('data_src').value;
|
||||
if(JSON.parse(json)) {
|
||||
targetFrame.contentWindow.updateFields(json);
|
||||
}
|
||||
}
|
||||
var url = document.URL,
|
||||
shortUrl=url.substring(0,url.lastIndexOf("/"));
|
||||
window.open(shortUrl + "/themes/nano/index.html", "output_frame");
|
||||
</script>
|
||||
</html>
|
||||
19
modular_kepler/html/oracle_ui/themes/nano/index.html
Normal file
19
modular_kepler/html/oracle_ui/themes/nano/index.html
Normal file
@@ -0,0 +1,19 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<head>
|
||||
<title>@{title}</title>
|
||||
<script src="sui-nano-jquery.min.js"></script>
|
||||
<script src="sui-nano-common.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="sui-nano-common.css">
|
||||
</head>
|
||||
<body scroll=auto>
|
||||
<div class='uiWrapper'>
|
||||
<div class='uiTitleWrapper'><div class='uiTitle'><tt>@{title}</tt></div></div>
|
||||
<div class='uiContent' id='maincontent'>
|
||||
@{body}
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
353
modular_kepler/html/oracle_ui/themes/nano/sui-nano-common.css
Normal file
353
modular_kepler/html/oracle_ui/themes/nano/sui-nano-common.css
Normal file
@@ -0,0 +1,353 @@
|
||||
body
|
||||
{
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background-color: #272727;
|
||||
font-size: 12px;
|
||||
color: #ffffff;
|
||||
line-height: 170%;
|
||||
cursor: default;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
|
||||
hr
|
||||
{
|
||||
background-color: #40628a;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
a, a:link, a:visited, a:active, .linkOn, .linkOff
|
||||
{
|
||||
color: #ffffff;
|
||||
text-decoration: none;
|
||||
background: #40628a;
|
||||
border: 1px solid #161616;
|
||||
padding: 1px 4px 1px 4px;
|
||||
margin: 0 2px 0 0;
|
||||
cursor:default;
|
||||
}
|
||||
|
||||
a:hover
|
||||
{
|
||||
color: #40628a;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
a.white, a.white:link, a.white:visited, a.white:active
|
||||
{
|
||||
color: #40628a;
|
||||
text-decoration: none;
|
||||
background: #ffffff;
|
||||
border: 1px solid #161616;
|
||||
padding: 1px 4px 1px 4px;
|
||||
margin: 0 2px 0 0;
|
||||
cursor:default;
|
||||
}
|
||||
|
||||
a.white:hover
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #40628a;
|
||||
}
|
||||
|
||||
.active, a.active:link, a.active:visited, a.active:active, a.active:hover
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #2f943c;
|
||||
border-color: #24722e;
|
||||
}
|
||||
|
||||
.disabled, a.disabled:link, a.disabled:visited, a.disabled:active, a.disabled:hover
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #999999;
|
||||
border-color: #666666;
|
||||
}
|
||||
|
||||
a.icon, .linkOn.icon, .linkOff.icon
|
||||
{
|
||||
position: relative;
|
||||
padding: 1px 4px 2px 20px;
|
||||
}
|
||||
|
||||
a.icon img, .linkOn.icon img
|
||||
{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
ul
|
||||
{
|
||||
padding: 4px 0 0 10px;
|
||||
margin: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
li
|
||||
{
|
||||
padding: 0 0 2px 0;
|
||||
}
|
||||
|
||||
img, a img
|
||||
{
|
||||
border-style:none;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6
|
||||
{
|
||||
margin: 0;
|
||||
padding: 16px 0 8px 0;
|
||||
color: #517087;
|
||||
}
|
||||
|
||||
h1
|
||||
{
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
h2
|
||||
{
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
h3
|
||||
{
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
h4
|
||||
{
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.uiWrapper
|
||||
{
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.uiTitle
|
||||
{
|
||||
clear: both;
|
||||
padding: 6px 8px 6px 8px;
|
||||
border-bottom: 2px solid #161616;
|
||||
background: #383838;
|
||||
color: #98B0C3;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.uiTitle.icon
|
||||
{
|
||||
padding: 6px 8px 6px 42px;
|
||||
background-position: 2px 50%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.uiContent
|
||||
{
|
||||
clear: both;
|
||||
padding: 8px;
|
||||
font-family: Verdana, Geneva, sans-serif;
|
||||
}
|
||||
|
||||
.good
|
||||
{
|
||||
color: #00ff00;
|
||||
}
|
||||
|
||||
.average
|
||||
{
|
||||
color: #d09000;
|
||||
}
|
||||
|
||||
.bad
|
||||
{
|
||||
color: #ff0000;
|
||||
}
|
||||
|
||||
.highlight
|
||||
{
|
||||
color: #8BA5C4;
|
||||
}
|
||||
|
||||
.dark
|
||||
{
|
||||
color: #272727;
|
||||
}
|
||||
|
||||
.notice
|
||||
{
|
||||
position: relative;
|
||||
background: #E9C183;
|
||||
color: #15345A;
|
||||
font-size: 10px;
|
||||
font-style: italic;
|
||||
padding: 2px 4px 0 4px;
|
||||
margin: 4px;
|
||||
}
|
||||
|
||||
.notice.icon
|
||||
{
|
||||
padding: 2px 4px 0 20px;
|
||||
}
|
||||
|
||||
.notice img
|
||||
{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
div.notice
|
||||
{
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.statusDisplay
|
||||
{
|
||||
background: #000000;
|
||||
color: #ffffff;
|
||||
border: 1px solid #40628a;
|
||||
padding: 4px;
|
||||
margin: 3px 0;
|
||||
}
|
||||
|
||||
.statusLabel
|
||||
{
|
||||
width: 138px;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
color: #98B0C3;
|
||||
}
|
||||
|
||||
.statusValue
|
||||
{
|
||||
float: left;
|
||||
}
|
||||
|
||||
.block
|
||||
{
|
||||
padding: 8px;
|
||||
margin: 10px 4px 4px 4px;
|
||||
border: 1px solid #40628a;
|
||||
background-color: #202020;
|
||||
}
|
||||
|
||||
.block h3
|
||||
{
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.progressBar
|
||||
{
|
||||
position: relative;
|
||||
width: 185px;
|
||||
height: 14px;
|
||||
border: 1px solid #666666;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.progressLabel
|
||||
{
|
||||
top: -2px;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.progressFill
|
||||
{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #40628a;
|
||||
overflow: hidden;
|
||||
transition: width 2.2s linear;
|
||||
}
|
||||
|
||||
.progressFill.good
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #00ff00;
|
||||
}
|
||||
|
||||
.progressFill.average
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #d09000;
|
||||
}
|
||||
|
||||
.progressFill.bad
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #ff0000;
|
||||
}
|
||||
|
||||
.progressFill.highlight
|
||||
{
|
||||
color: #ffffff;
|
||||
background: #8BA5C4;
|
||||
}
|
||||
|
||||
.clearBoth
|
||||
{
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.clearLeft
|
||||
{
|
||||
clear: left;
|
||||
}
|
||||
|
||||
.clearRight
|
||||
{
|
||||
clear: right;
|
||||
}
|
||||
|
||||
.line
|
||||
{
|
||||
width: 100%;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
section .label, section .content
|
||||
{
|
||||
display: table-cell;
|
||||
margin: 0;
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
padding: 3px 2px
|
||||
}
|
||||
|
||||
section .label
|
||||
{
|
||||
width: 1%;
|
||||
padding-right: 32px;
|
||||
white-space: nowrap;
|
||||
color: #8ba5c4;
|
||||
}
|
||||
|
||||
section
|
||||
{
|
||||
display: table-row;
|
||||
width: 100%
|
||||
}
|
||||
|
||||
.display {
|
||||
width: calc(100% - 8px);
|
||||
padding: 4px;
|
||||
background-color: #000;
|
||||
background-color: rgba(0, 0, 0, .33);
|
||||
box-shadow: inset 0 0 5px rgba(0, 0, 0, .5);
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr=#54000000,endColorStr=#54000000)";
|
||||
filter: progid: DXImageTransform.Microsoft.gradient(startColorStr=#54000000, endColorStr=#54000000);
|
||||
}
|
||||
47
modular_kepler/html/oracle_ui/themes/nano/sui-nano-common.js
Normal file
47
modular_kepler/html/oracle_ui/themes/nano/sui-nano-common.js
Normal file
@@ -0,0 +1,47 @@
|
||||
function replaceContent(body) {
|
||||
var maincontent = document.getElementById('maincontent');
|
||||
if(maincontent) {
|
||||
maincontent.innerHTML = body;
|
||||
}
|
||||
}
|
||||
|
||||
function updateProgressLabels() {
|
||||
var progressBars = document.getElementsByClassName("progressBar");
|
||||
for(var i = 0; i < progressBars.length; i++) {
|
||||
var progressBar = progressBars[i];
|
||||
if(!progressBar)
|
||||
continue;
|
||||
var progressFill = progressBar.getElementsByClassName("progressFill")[0];
|
||||
if(!progressFill)
|
||||
continue;
|
||||
var width = parseInt(getComputedStyle(progressFill).width);
|
||||
var maxWidth = parseInt(getComputedStyle(progressBar).width);
|
||||
var progressLabel = progressBar.getElementsByClassName("progressLabel")[0];
|
||||
if(progressLabel)
|
||||
progressLabel.innerHTML = Math.round((width / maxWidth) * 100) + '%';
|
||||
}
|
||||
}
|
||||
|
||||
if(getComputedStyle) { setInterval(updateProgressLabels, 50); } //Fallback
|
||||
|
||||
function updateFields(json) {
|
||||
var fields = JSON.parse(json);
|
||||
for (var key in fields) {
|
||||
let value = fields[key];
|
||||
var element = document.getElementById(key);
|
||||
if(element == null) {
|
||||
continue;
|
||||
} else if(element.classList.contains('progressBar')) {
|
||||
var progressFill = element.getElementsByClassName("progressFill")[0];
|
||||
if(progressFill)
|
||||
progressFill.style["width"] = value;
|
||||
if(!getComputedStyle) { //Fallback
|
||||
var progressLabel = element.getElementsByClassName("progressLabel")[0];
|
||||
if(progressLabel)
|
||||
progressLabel.innerHTML = value;
|
||||
}
|
||||
} else {
|
||||
element.innerHTML = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
4
modular_kepler/html/oracle_ui/themes/nano/sui-nano-jquery.min.js
vendored
Normal file
4
modular_kepler/html/oracle_ui/themes/nano/sui-nano-jquery.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -3077,4 +3077,8 @@
|
||||
#include "modular_citadel\code\modules\vore\eating\voreitems.dm"
|
||||
#include "modular_citadel\code\modules\vore\eating\vorepanel_vr.dm"
|
||||
#include "modular_citadel\interface\skin.dmf"
|
||||
#include "modular_kepler\code\modules\oracle_ui\assets.dm"
|
||||
#include "modular_kepler\code\modules\oracle_ui\hookup_procs.dm"
|
||||
#include "modular_kepler\code\modules\oracle_ui\oracle_ui.dm"
|
||||
#include "modular_kepler\code\modules\oracle_ui\themed.dm"
|
||||
// END_INCLUDE
|
||||
|
||||
Reference in New Issue
Block a user