Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- widgets = {}
- lastSessionWidgets = {}
- tabs = {}
- lastSessionTabs = {}
- tabsPage = {}
- activeTab = 0
- oldActiveTabData = {}
- activeTabData = {}
- activeTabPage = 1
- textboxGroup = {}
- bRun = true
- bDialogRunning = false
- bCanButtonAnim = true
- --[[
- Events :
- "button_clicked" : string button_name, number mouse_button, number mouse_x, number mouse_y
- "button_close_clicked" : -
- "textbox_text" : string textbox_name, string new_value, boolean return_key_used
- "switch_state" : string switch_name, boolean new_state, number mouse_button, number mouse_x, number mouse_y
- "numeric_value" : string value_name, number new_value, number mouse_button, number mouse_x, number mouse_y
- "list_selected" : string list_name, string new_value, number mouse_button, number mouse_x, number mouse_y
- "numericslider_value" : string numericslider_name, number new_value, number mouse_button, number mouse_x, number mouse_y
- "tab_changed" : string tab_id, number mouse_button, number mouse_x, number mouse_y
- "auto_tab_changed" : string tab_id
- Parallel functions :
- parallel.waitForAll(arcui.eventHandler, arcui.marqueeAnim)
- --> Main loop
- eventHandler : Make buttons, textboxes and sliders work
- --> Required animations
- marqueeAnim : Enable animation for widget_progress_marquee
- --> Optional animations
- progressAnim : Enable animation for widget_progress (still in beta)
- buttonAnim : Enable animation for widget_button (still in beta)
- listAnim : Enable animation for widget_list (still in beta)
- Functions :
- --> Window
- drawWindow(string window_title, boolean show_close_button, boolean skip_animation, number title_bar_color, number background_color, boolean show_tabs_bottom) : Draw an arcUI window
- redrawWindow() : Quickly redraw the window and it's contents
- closeWindow(boolean skip_animation) : Close the window, to use before closing the app
- openDialog(string dialog_id, string dialog_title, string dialog_message[, string left_button_text, string right_button_text, number background_color, number text_color, number left_button_color, number right_button_color, number left_button_text_color, number right_button_text_color, boolean hide_left_button]) : Open an interactive dialog (WARN: Use only when a window is opened)
- --> Widgets (Every draw() function has a corresponding create() function)
- deleteWidget(string widget_id) : Disable and delete a widget
- deleteAllWidgets() : Delete all the widgets in the screen
- widgetUpdate(string widget_id) : Redraw a widget
- getWidgetList() : Returns a list of widget with their types
- getWidgetListByType(string widget_type) : Returns a list of widgets filtered by the type
- setProperty(string widget_id, string value_index, string value) : Change a property of a widget
- setProperties(string widget_id, string first_value_index, string first_value, ...) : Change multiple properties of a widget
- getProperty(string widget_id, string value_index) : Get a property of a widget
- drawButton(string widget_id, number start_x, number start_y, number end_x, number end_y, string button_text[, number button_color, boolean enable_animation]) : Add an interactive button to the screen
- drawProgress(string widget_id, number start_x, number y, number end_x, number max_value, number value) : Add a progress bar to the screen
- drawMarqueeProgress(string widget_id, number start_x, number y, number end_x) : Add a progress bar with an undetermined value to the screen
- drawLabel(string widget_id, number x, number y, string label_text[, number background_color, number text_color]) : Add an editable label to the screen
- drawTextbox(string widget_id, number start_x, number y, number end_x[, string textbox_placeholder, string char_replace, boolean enable_history, table history, table auto_completion, number inactive_background_color, number active_background_color, number inactive_text_color, number active_text_color, boolean numeric_values_only]) : Add a flexible textbox to the screen
- drawSwitch(string widget_id, number x, number y, string slider_text[, boolean default_state]) : Add a 4x1 switch to the screen
- drawNumeric(string widget_id, number start_x, number y, number end_x, number default_value, number min_value, number max_value[, number incrementation]) : Add a NumericUpDown to the screen
- drawList(string widget_id, number start_x, number start_y, number end_x, number end_y, table values[, number selected_color, number text_color, number background_color, number second_background_color]) : Add a ListBox to the screen
- drawNumericSlider(string widget_id, number start_x, number y, number end_x[, number default_value, number min_value, number max_value, number slider_color]) : Add a numeric slider to the screen
- drawScrollManager(string widget_id, number start_x, number start_y, number end_x, number end_y, boolean auto_resize, number size) : Add a ScrollManager to the screen
- --> Tabs
- addTab(string tab_id, string tab_name[, number tab_position]) : Add a tab to the tab manager
- removeTab(string tab_id) : Remove a tab from the tab manager
- linkToTab(string tab_id, table widget) : Link a widget to a tab (widget is like linkToScrollManager())
- unlinkFromTab(string widget_id) : Unlink a widget from it's tab
- getTabCount() : Returns the tab count
- getTabPageCount() : Return the tab page count
- getTabPageCountBeforeActive() : Return the number of tabs before the active page
- --> ScrollManager
- linkToScrollManager(string scrollmanager_id, table widget) : Manage a widget with a ScrollManager
- autoResizeScrollManager(string scrollmanager_id) : Resize automatically a ScrollManager
- scrollScrollManager(number relative_scroll, string scrollmanager_id) : Scroll a ScrollManager relatively
- scrollScrollManagerTo(number absolute_scroll, string scrollmanager_id) : Scroll a ScrollManager with an absolute value
- Ex: arcui.linkToScrollManager("scrlmanid", arcui.createNumericSlider("numslid", 2, 2, 20, 50))
- --> Textbox groups
- createTextboxGroup(string group_id) : Create a new textbox group
- removeTextboxGroup(string group_id) : Remove a textbox group
- getTextboxGroup(string group_id) : Get the textbox(es) in a group
- addTextboxToGroup(string group_id, string textbox_id) : Add a textbox to a group
- addTextboxesToGroup(string group_id, string first_textbox_id, ...) : Add multiple textboxes to a group
- --> Utils
- columnFormatter(string first_column, number first_column_length, ...) : Format a string to mimic columns (Each column must have a length of 4 chars minimum)
- writeFormatted("string formatted_string") : Write a text with dynamic color changes (See "String formatting" section)
- String formatting :
- Every string in arcUI can be formatted to change the text and background color dynamically.
- Example: arcui.writeFormatted("$1Text $3Background$r&rReset")
- '$x' will change the text color, with 'x' a valid color or r to reset
- '&x' will change the background color, with 'x' a valid color or r to reset
- Credits :
- Made by Kuruyia (formerly known as arc13)
- The MIT License (MIT)
- Copyright (c) 2017-2018 Kuruyia
- Permission is hereby granted, free of charge, to any person obtaining a copy of
- this software and associated documentation files (the "Software"), to deal in
- the Software without restriction, including without limitation the rights to
- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- the Software, and to permit persons to whom the Software is furnished to do so,
- subject to the following conditions:
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- ]]
- local function debugPrint(sToPrint)
- local curX, curY = term.getCursorPos()
- local monX, monY = term.getSize()
- local bgColor = term.getBackgroundColor()
- local textColor = term.getTextColor()
- term.setCursorPos(1, monY)
- term.setTextColor(colors.black)
- term.setBackgroundColor(colors.white)
- term.clearLine()
- term.write(tostring(sToPrint))
- term.setCursorPos(curX, curY)
- term.setBackgroundColor(bgColor)
- term.setTextColor(textColor)
- end
- local function custRead(nSize, _sReplaceChar, _tHistory, _fnComplete, sWidget)
- term.setCursorBlink( true )
- local sLine = ""
- local nHistoryPos
- local nPos = 0
- local nLastUsedKey = 0
- local bNumericOnly = false
- if _sReplaceChar then
- _sReplaceChar = string.sub( _sReplaceChar, 1, 1 )
- end
- if sWidget and widgets[sWidget] then
- local widgetValue = tostring(widgets[sWidget]["value"])
- if widgetValue then
- sLine = widgetValue
- nPos = sLine:len()
- end
- if widgets[sWidget]["numericOnly"] then
- bNumericOnly = true
- end
- end
- local tCompletions
- local nCompletion
- local function recomplete()
- if _fnComplete and nPos == string.len(sLine) then
- tCompletions = _fnComplete( sLine , sWidget)
- if tCompletions and #tCompletions > 0 then
- nCompletion = 1
- else
- nCompletion = nil
- end
- else
- tCompletions = nil
- nCompletion = nil
- end
- end
- local function uncomplete()
- tCompletions = nil
- nCompletion = nil
- end
- local w,monHeight = term.getSize()
- local sx = term.getCursorPos()
- w = nSize
- local function redraw( _bClear )
- local nScroll = 0
- if sx + nPos >= w then
- nScroll = (sx + nPos) - w
- end
- term.setBackgroundColor(widgets[sWidget]["activeColor"])
- local cx,cy = term.getCursorPos()
- term.setCursorPos( sx, cy )
- local sReplace = (_bClear and " ") or _sReplaceChar
- if sReplace then
- term.write( string.rep( sReplace, math.max( string.len(sLine) - nScroll, 0 ) ) )
- else
- term.write( string.sub( sLine, nScroll + 1 ) )
- end
- if nCompletion then
- local sCompletion = tCompletions[ nCompletion ]
- local oldText, oldBg
- if not _bClear then
- oldText = term.getTextColor()
- oldBg = term.getBackgroundColor()
- term.setTextColor( colors.white )
- term.setBackgroundColor( colors.lightBlue )
- end
- if sReplace then
- term.write( string.rep( sReplace, string.len( sCompletion ) ) )
- else
- term.write( sCompletion )
- end
- if not _bClear then
- term.setTextColor( oldText )
- term.setBackgroundColor( oldBg )
- end
- end
- term.setCursorPos( sx + nPos - nScroll, cy )
- end
- local function clear()
- redraw( true )
- end
- recomplete()
- redraw()
- local function acceptCompletion()
- if nCompletion then
- -- Clear
- clear()
- -- Find the common prefix of all the other suggestions which start with the same letter as the current one
- local sCompletion = tCompletions[ nCompletion ]
- local sFirstLetter = string.sub( sCompletion, 1, 1 )
- local sCommonPrefix = sCompletion
- for n=1,#tCompletions do
- local sResult = tCompletions[n]
- if n ~= nCompletion and string.find( sResult, sFirstLetter, 1, true ) == 1 then
- while #sCommonPrefix > 1 do
- if string.find( sResult, sCommonPrefix, 1, true ) == 1 then
- break
- else
- sCommonPrefix = string.sub( sCommonPrefix, 1, #sCommonPrefix - 1 )
- end
- end
- end
- end
- -- Append this string
- sLine = sLine .. sCommonPrefix
- nPos = string.len( sLine )
- else
- return false
- end
- recomplete()
- redraw()
- return true
- end
- while true do
- local sEvent, param, a2, a3 = os.pullEvent()
- if sEvent == "char" then
- -- Typed key
- if not bNumericOnly or (bNumericOnly and tonumber(param)) then
- clear()
- sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 )
- nPos = nPos + 1
- recomplete()
- redraw()
- end
- elseif sEvent == "paste" then
- -- Pasted text
- if not bNumericOnly or (bNumericOnly and tonumber(param)) then
- clear()
- sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 )
- nPos = nPos + string.len( param )
- recomplete()
- redraw()
- end
- elseif sEvent == "key" then
- nLastUsedKey = param
- if param == keys.enter then
- -- Enter
- if nCompletion then
- clear()
- uncomplete()
- redraw()
- end
- break
- elseif param == keys.left then
- -- Left
- if nPos > 0 then
- clear()
- nPos = nPos - 1
- recomplete()
- redraw()
- end
- elseif param == keys.right then
- -- Right
- if nPos < string.len(sLine) then
- -- Move right
- clear()
- nPos = nPos + 1
- recomplete()
- redraw()
- else
- -- Accept autocomplete
- acceptCompletion()
- end
- elseif param == keys.up or param == keys.down then
- -- Up or down
- if nCompletion then
- -- Cycle completions
- clear()
- if param == keys.up then
- nCompletion = nCompletion - 1
- if nCompletion < 1 then
- nCompletion = #tCompletions
- end
- elseif param == keys.down then
- nCompletion = nCompletion + 1
- if nCompletion > #tCompletions then
- nCompletion = 1
- end
- end
- redraw()
- elseif _tHistory then
- -- Cycle history
- clear()
- if param == keys.up then
- -- Up
- if nHistoryPos == nil then
- if #_tHistory > 0 then
- nHistoryPos = #_tHistory
- end
- elseif nHistoryPos > 1 then
- nHistoryPos = nHistoryPos - 1
- end
- else
- -- Down
- if nHistoryPos == #_tHistory then
- nHistoryPos = nil
- elseif nHistoryPos ~= nil then
- nHistoryPos = nHistoryPos + 1
- end
- end
- if nHistoryPos then
- sLine = _tHistory[nHistoryPos]
- nPos = string.len( sLine )
- else
- sLine = ""
- nPos = 0
- end
- uncomplete()
- redraw()
- end
- elseif param == keys.backspace then
- -- Backspace
- if nPos > 0 then
- clear()
- sLine = string.sub( sLine, 1, nPos - 1 ) .. string.sub( sLine, nPos + 1 )
- nPos = nPos - 1
- recomplete()
- redraw()
- end
- elseif param == keys.home then
- -- Home
- if nPos > 0 then
- clear()
- nPos = 0
- recomplete()
- redraw()
- end
- elseif param == keys.delete then
- -- Delete
- if nPos < string.len(sLine) then
- clear()
- sLine = string.sub( sLine, 1, nPos ) .. string.sub( sLine, nPos + 2 )
- recomplete()
- redraw()
- end
- elseif param == keys["end"] then
- -- End
- if nPos < string.len(sLine ) then
- clear()
- nPos = string.len(sLine)
- recomplete()
- redraw()
- end
- elseif param == keys.tab then
- -- Tab (accept autocomplete)
- if not acceptCompletion() and widgets[sWidget]["group"] then
- break
- end
- end
- elseif sEvent == "term_resize" then
- -- Terminal resized
- w,monHeight = term.getSize()
- w = nSize
- redraw()
- elseif sEvent == "mouse_click" or (sEvent == "monitor_touch" and w ~= 51 and monHeight ~= 19) then
- -- Someone clicked somewhere, act as enter key and queueing event
- if nCompletion then
- clear()
- uncomplete()
- redraw()
- end
- break
- end
- end
- local cx, cy = term.getCursorPos()
- term.setCursorBlink( false )
- term.setCursorPos( w + 1, cy )
- print()
- return sLine, nLastUsedKey
- end
- local function tostringn(value)
- if value == nil then
- return nil
- else
- return tostring(value)
- end
- end
- local function checkArguments(bNeeded, ...)
- local tArgs = {...}
- local nActualArg = 1
- if #tArgs % 2 == 1 then
- table.remove(tArgs, #tArgs)
- end
- for i = 1, #tArgs, 2 do
- if type(tArgs[i]) ~= tArgs[i + 1] and (bNeeded or type(tArgs[i]) ~= "nil") then
- return false, "Argument #"..nActualArg..": Expected "..tArgs[i + 1]..", got "..type(tArgs[i])
- end
- nActualArg = nActualArg + 1
- end
- return true
- end
- local function reverseTwoArgs(arg1, arg2)
- return arg2, arg1
- end
- function createTextboxGroup(groupId)
- groupId = tostringn(groupId)
- local bValidArgs, sErrMsg = checkArguments(true, groupId, "string")
- if not bValidArgs then
- return false, sErrMsg
- end
- if textboxGroup[groupId] then
- return false, "The specified textbox group already exists"
- end
- textboxGroup[groupId] = {}
- return true
- end
- function removeTextboxGroup(groupId)
- groupId = tostringn(groupId)
- local bValidArgs, sErrMsg = checkArguments(true, groupId, "string")
- if not bValidArgs then
- return false, sErrMsg
- end
- if not textboxGroup[groupId] then
- return false, "The specified textbox group does not exist"
- end
- for k, v in pairs(textboxGroup[groupId]) do
- widgets[v]["group"] = nil
- end
- textboxGroup[groupId] = nil
- return true
- end
- function getTextboxGroup(groupId)
- groupId = tostringn(groupId)
- local bValidArgs, sErrMsg = checkArguments(true, groupId, "string")
- if not bValidArgs then
- return false, sErrMsg
- end
- if not textboxGroup[groupId] then
- return false, "The specified textbox group does not exist"
- end
- return textboxGroup[groupId]
- end
- function addTextboxToGroup(groupId, textboxId)
- groupId = tostringn(groupId)
- textboxId = tostringn(textboxId)
- local bValidArgs, sErrMsg = checkArguments(true, groupId, "string", textboxId, "string")
- if not bValidArgs then
- return false, sErrMsg
- end
- if not widgets[textboxId] then
- return false, "The specified textbox does not exist"
- end
- if not textboxGroup[groupId] then
- return false, "The specified textbox group does not exist"
- end
- table.insert(textboxGroup[groupId], textboxId)
- widgets[textboxId]["group"] = groupId
- return true
- end
- function addTextboxesToGroup(groupId, ...)
- groupId = tostringn(groupId)
- local bValidArgs, sErrMsg = checkArguments(true, groupId, "string")
- if not bValidArgs then
- return false, sErrMsg
- end
- local tArgs = {...}
- if not textboxGroup[groupId] then
- return false, "The specified textbox group does not exist"
- end
- for i = 1, #tArgs do
- tArgs[i] = tostringn(tArgs[i])
- if not widgets[tArgs[i]] then
- return false, "Argument#"..i.." : The specified textbox does not exist"
- end
- end
- for i = 1, #tArgs do
- table.insert(textboxGroup[groupId], tArgs[i])
- widgets[tArgs[i]]["group"] = groupId
- end
- return true
- end
- function writeFormatted(sValue, isBackgroundChangesAllowed)
- sValue = tostringn(sValue)
- if not sValue then
- return false, "Argument #1: Expected string, got "..type(sValue)
- end
- if not sValue:match("$") and not sValue:match("&") then
- term.write(sValue)
- else
- local colorsDecToPaint = {["0"] = colors.white, ["1"] = colors.orange, ["2"] = colors.magenta, ["3"] = colors.lightBlue, ["4"] = colors.yellow, ["5"] = colors.lime, ["6"] = colors.pink, ["7"] = colors.gray, ["8"] = colors.lightGray, ["9"] = colors.cyan, ["a"] = colors.purple, ["b"] = colors.blue, ["c"] = colors.brown, ["d"] = colors.green, ["e"] = colors.red, ["f"] = colors.black}
- local skipCurrentChar = false
- local currentBgColor = term.getBackgroundColor()
- local currentTextColor = term.getTextColor()
- if type(isBackgroundChangesAllowed) == "nil" then
- isBackgroundChangesAllowed = true
- end
- for i = 1, sValue:len() do
- if not skipCurrentChar then
- local currentChar = sValue:sub(i, i)
- if currentChar ~= "$" and currentChar ~= "&" then
- term.write(currentChar)
- else
- skipCurrentChar = true
- local modifier = sValue:sub(i + 1, i + 1)
- if colorsDecToPaint[modifier] then
- if currentChar == "$" then
- term.setTextColor(colorsDecToPaint[modifier])
- elseif currentChar == "&" and isBackgroundChangesAllowed then
- term.setBackgroundColor(colorsDecToPaint[modifier])
- end
- elseif modifier == "r" then
- if currentChar == "$" then
- term.setTextColor(currentTextColor)
- elseif currentChar == "&" and isBackgroundChangesAllowed then
- term.setBackgroundColor(currentBgColor)
- end
- else
- term.write(modifier)
- end
- end
- else
- skipCurrentChar = false
- end
- end
- term.setBackgroundColor(currentBgColor)
- term.setTextColor(currentTextColor)
- end
- end
- local function getWidgetHitbox(sWidgetId)
- local widgetStartX = 0
- local widgetStartY = 0
- local widgetEndX = 0
- local widgetEndY = 0
- local widgetLossX = 0
- local widgetLossTopY = 0
- local widgetLossBotY = 0
- if widgets[sWidgetId]["startX"] then
- widgetStartX = widgets[sWidgetId]["startX"]
- end
- if widgets[sWidgetId]["startY"] then
- widgetStartY = widgets[sWidgetId]["startY"]
- end
- if widgets[sWidgetId]["endX"] then
- widgetEndX = widgets[sWidgetId]["endX"]
- end
- if widgets[sWidgetId]["endY"] then
- widgetEndY = widgets[sWidgetId]["endY"]
- end
- if widgets[sWidgetId]["scrollManager"] then
- if widgetStartY < widgets[widgets[sWidgetId]["scrollManager"]]["startY"] and widgetEndY >= widgets[widgets[sWidgetId]["scrollManager"]]["startY"] then
- widgetStartY = widgets[widgets[sWidgetId]["scrollManager"]]["startY"]
- widgetLossTopY = widgetStartY - widgets[sWidgetId]["startY"]
- end
- if widgetEndY > widgets[widgets[sWidgetId]["scrollManager"]]["endY"] and widgetStartY <= widgets[widgets[sWidgetId]["scrollManager"]]["endY"] then
- widgetEndY = widgets[widgets[sWidgetId]["scrollManager"]]["endY"]
- widgetLossBotY = widgets[sWidgetId]["endY"] - widgetEndY
- end
- end
- return widgetStartX, widgetStartY, widgetEndX, widgetEndY, widgetLossX, widgetLossTopY, widgetLossBotY
- end
- function columnFormatter(...)
- local tArgs = {...}
- if #tArgs % 2 == 1 then
- table.remove(tArgs)
- end
- if #tArgs == 0 then
- return false, "Not enough arguments"
- end
- local stringCount = #tArgs / 2
- for i = 1, #tArgs do
- if i % 2 == 0 then
- tArgs[i] = tonumber(tArgs[i])
- if type(tArgs[i]) ~= "number" then
- return false, "Argument #"..tostring(i)..": Expected number, got "..type(tArgs[i])
- end
- if tArgs[i] < 4 then
- return false, "Argument #"..tostring(i)..": Not enough length, min 4"
- end
- else
- tArgs[i] = tostringn(tArgs[i])
- if type(tArgs[i]) ~= "string" then
- return false, "Argument #"..tostring(i)..": Expected string, got "..type(tArgs[i])
- end
- end
- end
- local returnString = ""
- for i = 1, #tArgs, 2 do
- local currentString = tArgs[i]
- local currentStringLength = currentString:len()
- local currentStringExpectedLength = tArgs[i + 1]
- local startAppendChars = ""
- local endAppendChars = ""
- if currentString:match("$") and currentString:match("&") then
- local isStringTooBig = false
- local formatCharCountStart = 0
- local formatCharCountEnd = 0
- for i = 1, currentStringLength, 2 do
- local currentChar = currentString:sub(i, i)
- local modifier = currentString:sub(i + 1, i + 1)
- if (currentChar == "$" or currentChar == "&") and (modifier:match("%x") or modifier == "r") then
- formatCharCountStart = formatCharCountStart + 1
- else
- break
- end
- end
- for i = currentStringLength - 1, 1, -2 do
- local currentChar = currentString:sub(i, i)
- local modifier = currentString:sub(i + 1, i + 1)
- if (currentChar == "$" or currentChar == "&") and (modifier:match("%x") or modifier == "r") then
- formatCharCountEnd = formatCharCountEnd + 1
- else
- break
- end
- end
- startAppendChars = currentString:sub(1, formatCharCountStart * 2)
- endAppendChars = currentString:sub(currentStringLength - (formatCharCountEnd * 2) + 1, currentStringLength)
- local separatedString = currentString:sub(formatCharCountStart * 2 + 1, currentStringLength - (formatCharCountEnd * 2))
- local formatChars = 0
- local sanitizedString = ""
- local skipCurrentChar = false
- for i = 1, separatedString:len() do
- if not skipCurrentChar then
- local currentChar = separatedString:sub(i, i)
- if currentChar == "$" or currentChar == "&" then
- skipCurrentChar = true
- local modifier = separatedString:sub(i + 1, i + 1)
- if modifier:match("%x") or modifier == "r" then
- formatChars = formatChars + 2
- else
- formatChars = formatChars + 1
- sanitizedString = sanitizedString..modifier
- end
- else
- sanitizedString = sanitizedString..currentChar
- end
- else
- skipCurrentChar = false
- end
- end
- if ((i + 1) / 2 == stringCount and sanitizedString:len() > currentStringExpectedLength) or ((i + 1) / 2 ~= stringCount and sanitizedString:len() >= currentStringExpectedLength) then
- currentString = sanitizedString
- currentStringLength = sanitizedString:len()
- else
- currentStringExpectedLength = currentStringExpectedLength + formatChars
- currentString = separatedString
- currentStringLength = separatedString:len()
- end
- end
- local function inflateFormatChars(currentString)
- if currentString:match("$") and currentString:match("&") then
- local newString = ""
- for i = 1, currentString:len() do
- local currentChar = currentString:sub(i, i)
- newString = newString..currentChar
- if currentChar == "$" or currentChar == "&" then
- newString = newString..currentChar
- end
- end
- return newString
- else
- return currentString
- end
- end
- if (i + 1) / 2 == stringCount then
- if currentStringLength > currentStringExpectedLength then
- currentString = currentString:sub(1, currentStringExpectedLength - 3).."..."
- currentString = inflateFormatChars(currentString)
- currentString = currentString..endAppendChars
- else
- currentString = currentString..endAppendChars
- end
- else
- if currentStringLength >= currentStringExpectedLength then
- currentString = currentString:sub(1, currentStringExpectedLength - 4).."..."
- currentString = inflateFormatChars(currentString)
- currentString = currentString..endAppendChars.." "
- elseif currentStringLength < currentStringExpectedLength then
- currentString = currentString..endAppendChars
- for i = 1, currentStringExpectedLength - currentStringLength do
- currentString = currentString.." "
- end
- end
- end
- currentString = startAppendChars..currentString
- returnString = returnString..currentString
- end
- return returnString
- end
- function widgetUpdate(sId)
- if not sId or not widgets[sId] then
- return false
- end
- local widgetStartX, widgetStartY, widgetEndX, widgetEndY, _, widgetLossTopY, widgetLossBotY = getWidgetHitbox(sId)
- local monX, monY = term.getSize()
- local oldColor = widgets["window"]["bgColor"]
- local oldTextColor = term.getTextColor()
- local function drawVerticalScrollbar(widgetWorkingHeight, sId, widgetStartY, widgetEndY, widgetLossTopY, widgetLossBotY)
- if widgetWorkingHeight > widgetEndY - widgetStartY + 1 + widgetLossTopY then
- local navBarWorkingLength = widgets[sId]["height"] - 1
- local navBarLength = math.floor(widgets[sId]["height"] * navBarWorkingLength / widgetWorkingHeight)
- local navBarJump = math.floor((widgets[sId]["valuesShownMin"] - 1) * navBarWorkingLength / widgetWorkingHeight)
- if widgetLossTopY > 0 then
- navBarJump = navBarJump - widgetLossTopY
- end
- if navBarLength > navBarWorkingLength then
- navBarLength = navBarWorkingLength - 1
- end
- if (navBarJump + navBarLength >= navBarWorkingLength) or (widgets[sId]["valuesShownMax"] == widgetWorkingHeight) then
- navBarJump = navBarWorkingLength - navBarLength - 1 - widgetLossTopY
- end
- if widgetLossTopY == 0 and widgetLossBotY == 0 then
- paintutils.drawLine(widgetEndX, widgetStartY + 1 + navBarJump, widgetEndX, widgetStartY + 1 + navBarLength + navBarJump, colors.blue)
- else
- local navBarTop = widgetStartY + 1 + navBarJump
- local navBarBottom = navBarTop + navBarLength
- if navBarTop < widgetStartY then
- navBarLength = navBarLength - (widgetStartY - navBarTop)
- navBarTop = widgetStartY
- end
- navBarBottom = navBarTop + navBarLength
- if navBarBottom > widgetEndY then
- navBarLength = navBarLength - (navBarBottom - widgetEndY)
- end
- navBarBottom = navBarTop + navBarLength
- if navBarLength >= 0 then
- paintutils.drawLine(widgetEndX, navBarTop, widgetEndX, navBarBottom, colors.blue)
- end
- end
- end
- end
- if widgetStartX > monX or widgetEndX < 1 or widgetStartY > monY or widgetEndY < 1 then
- return false
- end
- if widgets[sId]["height"] then
- widgets[sId]["height"] = widgets[sId]["endY"] - widgets[sId]["startY"]
- end
- if widgets[sId]["type"] == "widget_button" then
- if widgets[sId]["enabled"] then
- paintutils.drawFilledBox(widgetStartX, widgetStartY, widgetEndX, widgetEndY, widgets[sId]["btnColor"])
- if widgetEndY >= 1 and widgetStartY <= monY then
- local nButtonMiddleX = (widgetEndX - widgetStartX) / 2
- local nButtonMiddleInSpaceX = nButtonMiddleX + widgetStartX
- local nButtonMiddleY = (widgetEndY - widgetStartY) / 2
- local nButtonMiddleInSpaceY = nButtonMiddleY + widgetStartY
- term.setCursorPos(nButtonMiddleInSpaceX - math.floor(string.len(widgets[sId]["text"]) / 2), nButtonMiddleInSpaceY)
- term.write(widgets[sId]["text"])
- end
- else
- paintutils.drawFilledBox(widgetStartX, widgetStartY, widgetEndX, widgetEndY, oldColor)
- end
- elseif widgets[sId]["type"] == "widget_progress" then
- if widgets[sId]["enabled"] then
- local pixelWidth = (widgets[sId]["value"] * widgets[sId]["width"]) / widgets[sId]["maxValue"]
- local pixelWidthInSpace = pixelWidth + widgetStartX
- paintutils.drawLine(widgetStartX, widgetStartY, widgetEndX, widgetStartY, colors.cyan)
- if widgets[sId]["value"] ~= 0 then
- paintutils.drawLine(widgetStartX, widgetStartY, pixelWidthInSpace, widgetStartY, colors.blue)
- end
- widgets[sId]["value_width"] = pixelWidthInSpace
- else
- paintutils.drawFilledBox(widgetStartX, widgetStartY, widgetEndX, widgetStartY, oldColor)
- end
- elseif widgets[sId]["type"] == "widget_progress_marquee" then
- if widgets[sId]["enabled"] then
- paintutils.drawLine(widgetStartX, widgetStartY, widgetEndX, widgetStartY, colors.cyan)
- else
- paintutils.drawFilledBox(widgetStartX, widgetStartY, widgetEndX, widgetStartY, oldColor)
- end
- elseif widgets[sId]["type"] == "widget_label" then
- if widgets[sId]["enabled"] then
- local curX, curY = term.getCursorPos()
- paintutils.drawFilledBox(widgetStartX, widgetStartY, widgetStartX + string.len(widgets[sId]["text"]), widgetStartY, widgets[sId]["bgColor"])
- term.setBackgroundColor(widgets[sId]["bgColor"] or oldColor)
- term.setTextColor(tonumber(widgets[sId]["textColor"]) or colors.white)
- term.setCursorPos(widgetStartX, widgetStartY)
- writeFormatted(widgets[sId]["text"])
- term.setCursorPos(curX, curY)
- term.setBackgroundColor(oldColor)
- term.setTextColor(colors.white)
- else
- term.setCursorPos(widgetStartX, widgetStartY)
- paintutils.drawFilledBox(widgetStartX, widgetStartY, widgetStartX + string.len(widgets[sId]["text"]), widgetStartY, term.getBackgroundColor())
- end
- elseif widgets[sId]["type"] == "widget_textbox" then
- if widgets[sId]["enabled"] then
- paintutils.drawLine(widgetStartX + 1, widgetStartY, widgetEndX - 1, widgetStartY, widgets[sId]["inactiveColor"])
- if widgets[sId]["value"] ~= "" then
- paintutils.drawLine(widgetStartX, widgetStartY, widgetEndX, widgetStartY, widgets[sId]["activeColor"])
- term.setCursorPos(widgetStartX, widgetStartY)
- term.setTextColor(widgets[sId]["textActiveColor"])
- if not widgets[sId]["charReplace"] or widgets[sId]["charReplace"] == "" then
- writeFormatted(widgets[sId]["value"]:sub(widgets[sId]["value"]:len() - (widgetEndX - widgetStartX - 1), widgets[sId]["value"]:len()))
- else
- local nTextLength = widgets[sId]["value"]:len()
- local nTextboxWidth = widgetEndX - widgetStartX - 1
- if nTextLength > nTextboxWidth then
- nTextLength = nTextboxWidth
- end
- for i = 1, nTextLength do
- write(widgets[sId]["charReplace"])
- end
- end
- term.setTextColor(colors.white)
- else
- paintutils.drawLine(widgetStartX, widgetStartY, widgetEndX, widgetStartY, oldColor)
- paintutils.drawLine(widgetStartX + 1, widgetStartY, widgetEndX - 1, widgetStartY, widgets[sId]["inactiveColor"])
- if widgets[sId]["text"] then
- term.setCursorPos(widgetStartX + 1, widgetStartY)
- term.setTextColor(widgets[sId]["textInactiveColor"])
- writeFormatted(widgets[sId]["text"])
- term.setTextColor(colors.white)
- end
- end
- else
- paintutils.drawFilledBox(widgetStartX, widgetStartY, widgetEndX, widgetStartY, term.getBackgroundColor())
- end
- elseif widgets[sId]["type"] == "widget_switch" then
- if widgets[sId]["enabled"] then
- if widgets[sId]["state"] == false then
- paintutils.drawLine(widgetStartX, widgetStartY, widgetStartX + 3, widgetStartY, colors.white)
- paintutils.drawPixel(widgetStartX, widgetStartY, colors.gray)
- elseif widgets[sId]["state"] == true then
- paintutils.drawLine(widgetStartX, widgetStartY, widgetStartX + 3, widgetStartY, colors.green)
- paintutils.drawPixel(widgetStartX + 3, widgetStartY, colors.lime)
- end
- term.setCursorPos(widgetStartX + 5, widgetStartY)
- term.setBackgroundColor(oldColor)
- writeFormatted(widgets[sId]["text"])
- else
- paintutils.drawLine(widgetStartX, widgetStartY, widgetStartX + 4 + string.len(widgets[sId]["text"]), widgetStartY, oldColor)
- end
- elseif widgets[sId]["type"] == "widget_numeric" then
- if widgets[sId]["enabled"] then
- paintutils.drawPixel(widgetStartX, widgetStartY, colors.blue)
- term.setCursorPos(widgetStartX, widgetStartY)
- term.write("-")
- paintutils.drawPixel(widgetEndX, widgetStartY, colors.blue)
- term.setCursorPos(widgetEndX, widgetStartY)
- term.write("+")
- paintutils.drawLine(widgetStartX + 1, widgetStartY, widgetEndX - 1, widgetStartY, colors.cyan)
- local nNumericMiddleX = (widgetEndX - widgetStartX) / 2
- local nNumericMiddleInSpaceX = nNumericMiddleX + widgetStartX
- term.setCursorPos(nNumericMiddleInSpaceX, widgetStartY)
- writeFormatted(tostring(widgets[sId]["value"]))
- else
- paintutils.drawLine(widgetStartX, widgetStartY, widgetEndX, widgetStartY, oldColor)
- end
- elseif widgets[sId]["type"] == "widget_list" then
- if widgets[sId]["enabled"] then
- widgets[sId]["valuesShown"] = {}
- widgets[sId]["valuesShownMax"] = widgets[sId]["valuesShownMin"] + widgets[sId]["height"]
- paintutils.drawFilledBox(widgetStartX, widgetStartY, widgetEndX - 1, widgetEndY, widgets[sId]["backgroundColor"])
- paintutils.drawLine(widgetEndX, widgetStartY, widgetEndX, widgetEndY, colors.gray)
- if widgetLossTopY == 0 then
- if widgets[sId]["valuesShownMin"] == 1 then
- term.setTextColor(colors.lightGray)
- end
- term.setCursorPos(widgetEndX, widgetStartY)
- term.write("-")
- end
- if widgetLossBotY == 0 then
- if widgets[sId]["valuesShownMax"] >= #widgets[sId]["values"] then
- term.setTextColor(colors.lightGray)
- else
- term.setTextColor(colors.white)
- end
- term.setCursorPos(widgetEndX, widgetEndY)
- term.write("+")
- end
- if widgets[sId]["backgroundColor"] == widgets[sId]["secondBackgroundColor"] then
- term.setBackgroundColor(widgets[sId]["backgroundColor"])
- end
- term.setTextColor(widgets[sId]["textColor"])
- for i = widgets[sId]["valuesShownMin"], widgets[sId]["valuesShownMax"] do
- table.insert(widgets[sId]["valuesShown"], widgets[sId]["values"][i])
- end
- for i = 0, #widgets[sId]["valuesShown"] - 1 do
- if widgetStartY + i > widgetEndY or not widgets[sId]["valuesShown"][i + 1 + widgetLossTopY] then
- break
- end
- local isCurrentlySelected = i + widgets[sId]["valuesShownMin"] + widgetLossTopY == widgets[sId]["selectedValue"]
- if isCurrentlySelected then
- paintutils.drawLine(widgetStartX, widgetStartY + i, widgetEndX - 1, widgetStartY + i, widgets[sId]["selectedColor"])
- elseif widgets[sId]["backgroundColor"] ~= widgets[sId]["secondBackgroundColor"] then
- if (i + widgets[sId]["valuesShownMin"] + widgetLossTopY) % 2 == 1 then
- paintutils.drawLine(widgetStartX, widgetStartY + i, widgetEndX - 1, widgetStartY + i, widgets[sId]["secondBackgroundColor"])
- else
- term.setBackgroundColor(widgets[sId]["backgroundColor"])
- end
- end
- term.setCursorPos(widgetStartX, widgetStartY + i)
- writeFormatted(widgets[sId]["valuesShown"][i + 1 + widgetLossTopY], not isCurrentlySelected)
- term.setBackgroundColor(widgets[sId]["backgroundColor"])
- end
- term.setTextColor(colors.white)
- drawVerticalScrollbar(#widgets[sId]["values"], sId, widgetStartY, widgetEndY, widgetLossTopY, widgetLossBotY)
- else
- paintutils.drawFilledBox(widgetStartX, widgetStartY, widgetEndX, widgetEndY, oldColor)
- end
- elseif widgets[sId]["type"] == "widget_numericslider" then
- if widgets[sId]["enabled"] then
- local nSliderPositionX = (widgets[sId]["value"] - widgets[sId]["minValue"]) * (widgetEndX - widgetStartX) / (widgets[sId]["maxValue"] - widgets[sId]["minValue"])
- local nSliderPositionInSpaceX = nSliderPositionX + widgetStartX
- paintutils.drawLine(widgetStartX, widgetStartY, widgetEndX, widgetStartY, colors.black)
- paintutils.drawLine(widgetStartX, widgetStartY, nSliderPositionInSpaceX, widgetStartY, widgets[sId]["sliderColor"] or colors.gray)
- paintutils.drawPixel(nSliderPositionInSpaceX, widgetStartY, colors.white)
- else
- paintutils.drawLine(widgetStartX, widgetStartY, widgetEndX, widgetStartY, oldColor)
- end
- elseif widgets[sId]["type"] == "widget_scrollmanager" then
- if widgets[sId]["enabled"] then
- widgets[sId]["valuesShownMax"] = widgets[sId]["valuesShownMin"] + widgets[sId]["height"]
- paintutils.drawFilledBox(widgetStartX, widgetStartY, widgetEndX, widgetEndY, colors.lightBlue)
- paintutils.drawLine(widgetEndX, widgetStartY, widgetEndX, widgetEndY, colors.gray)
- term.setTextColor(colors.white)
- if widgets[sId]["valuesShownMin"] <= 1 then
- term.setTextColor(colors.lightGray)
- end
- term.setCursorPos(widgetEndX, widgetStartY)
- term.write("-")
- term.setTextColor(colors.white)
- if widgets[sId]["valuesShownMax"] >= widgets[sId]["size"] then
- term.setTextColor(colors.lightGray)
- end
- term.setCursorPos(widgetEndX, widgetEndY)
- term.write("+")
- for i = 1, #widgets[sId]["linkedWidgets"] do
- widgetUpdate(widgets[sId]["linkedWidgets"][i])
- end
- drawVerticalScrollbar(widgets[sId]["size"], sId, widgetStartY, widgetEndY, widgetLossTopY, widgetLossBotY)
- else
- paintutils.drawFilledBox(widgetStartX, widgetStartY, widgetEndX, widgetEndY, oldColor)
- end
- else
- return false
- end
- term.setBackgroundColor(oldColor)
- term.setTextColor(oldTextColor)
- return widgets[sId]
- end
- function setProperties(sId, ...)
- local tArguments = {...}
- if #tArguments % 2 == 1 then
- table.remove(tArguments, #tArguments)
- end
- if widgets[sId] then
- local curX, curY = term.getCursorPos()
- local oldBgColor = term.getBackgroundColor()
- local oldTextColor = term.getTextColor()
- local widgetStartX, widgetStartY, widgetEndX, widgetEndY = getWidgetHitbox(sId)
- local monX, monY = term.getSize()
- if widgets[sId]["type"] == "widget_button" then
- paintutils.drawFilledBox(widgetStartX, widgetStartY, widgetEndX, widgetEndY, term.getBackgroundColor())
- widgets[sId]["oldBtnColor"] = widgets[sId]["btnColor"]
- elseif widgets[sId]["type"] == "widget_progress" or widgets[sId]["type"] == "widget_progress_marquee" then
- paintutils.drawFilledBox(widgetStartX, widgetStartY, widgetEndX, widgetStartY, term.getBackgroundColor())
- elseif widgets[sId]["type"] == "widget_label" then
- if sValueIndex == "text" and type(sNewValue) ~= "string" then
- if not tostring(sNewValue) then
- return false
- else
- sNewValue = tostring(sNewValue)
- end
- end
- term.setCursorPos(widgetStartX, widgetStartY)
- paintutils.drawFilledBox(widgetStartX, widgetStartY, widgetStartX + string.len(widgets[sId]["text"]), widgetStartY, widgets["window"]["bgColor"])
- term.setCursorPos(curX, curY)
- elseif widgets[sId]["type"] == "widget_textbox" then
- paintutils.drawFilledBox(widgetStartX, widgetStartY, widgetEndX, widgetStartY, term.getBackgroundColor())
- elseif widgets[sId]["type"] == "widget_switch" then
- paintutils.drawLine(widgetStartX, widgetStartY, widgetStartX + 4 + string.len(widgets[sId]["text"]), widgetStartY, oldColor)
- elseif widgets[sId]["type"] == "widget_numeric" then
- paintutils.drawLine(widgetStartX, widgetStartY, widgetEndX, widgetStartY, term.getBackgroundColor())
- elseif widgets[sId]["type"] == "widget_list" then
- paintutils.drawFilledBox(widgetStartX, widgetStartY, widgetEndX, widgetEndY, term.getBackgroundColor())
- widgets[sId]["oldSelectedColor"] = widgets[sId]["selectedColor"]
- elseif widgets[sId]["type"] == "widget_numericslider" then
- paintutils.drawLine(widgetStartX, widgetStartY, widgetEndX, widgetStartY, term.getBackgroundColor())
- elseif widgets[sId]["type"] == "widget_scrollmanager" then
- paintutils.drawFilledBox(widgetStartX, widgetStartY, widgetEndX, widgetEndY, term.getBackgroundColor())
- end
- for i = 1, #tArguments, 2 do
- if type(widgets[sId][tArguments[i]]) ~= "nil" then
- widgets[sId][tArguments[i]] = tArguments[i + 1]
- end
- end
- widgetUpdate(sId)
- term.setCursorPos(curX, curY)
- term.setTextColor(oldTextColor)
- term.setBackgroundColor(oldBgColor)
- else
- return false
- end
- end
- function setProperty(sId, sValueIndex, sNewValue)
- return setProperties(sId, sValueIndex, sNewValue)
- end
- function changeValue(sId, sValueIndex, sNewValue)
- return setProperty(sId, sValueIndex, sNewValue)
- end
- function getProperty(sId, sValueIndex)
- if not widgets[sId] then
- return false, "Unknown widget"
- elseif not widgets[sId][sValueIndex] then
- return false, "Unknown property"
- end
- return widgets[sId][sValueIndex]
- end
- local function updateLinkedWidgets()
- local monX, monY = term.getSize()
- for k, v in pairs(tabs) do
- if v["id"] ~= activeTabData["id"] and oldActiveTabData["id"] == v["id"] then
- for i = 1, #v["linkedWidgets"] do
- setProperties(v["linkedWidgets"][i], "startY", widgets[v["linkedWidgets"][i]]["startY"] + monY, "endY", widgets[v["linkedWidgets"][i]]["endY"] + monY)
- if widgets[v["linkedWidgets"][i]]["linkedWidgets"] then
- for j = 1, #widgets[v["linkedWidgets"][i]]["linkedWidgets"] do
- setProperties(widgets[v["linkedWidgets"][i]]["linkedWidgets"][j], "startY", widgets[widgets[v["linkedWidgets"][i]]["linkedWidgets"][j]]["startY"] + monY, "endY", widgets[widgets[v["linkedWidgets"][i]]["linkedWidgets"][j]]["endY"] + monY)
- end
- end
- end
- end
- end
- for i = 1, #activeTabData["linkedWidgets"] do
- setProperties(activeTabData["linkedWidgets"][i], "startY", widgets[activeTabData["linkedWidgets"][i]]["startY"] - monY, "endY", widgets[activeTabData["linkedWidgets"][i]]["endY"] - monY)
- if widgets[activeTabData["linkedWidgets"][i]]["linkedWidgets"] then
- for j = 1, #widgets[activeTabData["linkedWidgets"][i]]["linkedWidgets"] do
- setProperties(widgets[activeTabData["linkedWidgets"][i]]["linkedWidgets"][j], "startY", widgets[widgets[activeTabData["linkedWidgets"][i]]["linkedWidgets"][j]]["startY"] - monY, "endY", widgets[widgets[activeTabData["linkedWidgets"][i]]["linkedWidgets"][j]]["endY"] - monY)
- end
- end
- end
- end
- local function updateTabs()
- local oldColor = term.getBackgroundColor()
- local monX, monY = term.getSize()
- local isTabOnBottom = widgets["window"]["tabsBottom"]
- local tabsPosition = 2
- if isTabOnBottom then
- tabsPosition = monY
- end
- paintutils.drawLine(1, tabsPosition, monX, tabsPosition, widgets["window"]["bgColor"])
- if getTabPageCount() > 1 then
- if activeTabPage == 1 then
- paintutils.drawLine(monX - 1, tabsPosition, monX, tabsPosition, colors.blue)
- term.setCursorPos(monX - 1, tabsPosition)
- term.write(" >")
- elseif activeTabPage == getTabPageCount() then
- paintutils.drawLine(monX - 1, tabsPosition, monX, tabsPosition, colors.blue)
- term.setCursorPos(monX - 1, tabsPosition)
- term.write("< ")
- else
- paintutils.drawLine(monX - 1, tabsPosition, monX, tabsPosition, colors.blue)
- term.setCursorPos(monX - 1, tabsPosition)
- term.write("<>")
- end
- end
- term.setBackgroundColor(widgets["window"]["titleBarColor"])
- term.setCursorPos(1, tabsPosition)
- local activeTabPageIDs = tabsPage[activeTabPage]
- local tabBefore = getTabPageCountBeforeActive()
- for i = 1, #activeTabPageIDs do
- if activeTab == tabBefore + i then
- term.setBackgroundColor(widgets["window"]["bgColor"])
- term.setTextColor(colors.yellow)
- activeTabData = tabs[activeTabPageIDs[i]]
- end
- write(" "..tabs[activeTabPageIDs[i]]["name"].." ")
- if activeTab == tabBefore + i then
- term.setBackgroundColor(widgets["window"]["titleBarColor"])
- term.setTextColor(colors.white)
- end
- end
- term.setBackgroundColor(oldColor)
- updateLinkedWidgets()
- end
- local function updateTabManager()
- local oldColor = term.getBackgroundColor()
- local monX, monY = term.getSize()
- tabsPage = {}
- tabsPage[1] = {}
- local copyTabs = tabs
- local tabOrder = {}
- local orderedTabs = {}
- local actualPage = 1
- local charNumber = 0
- for k, v in pairs(tabs) do
- table.insert(tabOrder, v["position"])
- end
- table.sort(tabOrder)
- for k, v in ipairs(tabOrder) do
- for k1, v1 in pairs(copyTabs) do
- if v1["position"] == v then
- table.insert(orderedTabs, v1)
- break
- end
- end
- end
- for k, v in pairs(orderedTabs) do
- local newCharNumber = charNumber + v["name"]:len() + 2
- if newCharNumber <= monX - 2 then
- table.insert(tabsPage[actualPage], v["id"])
- charNumber = newCharNumber
- else
- actualPage = actualPage + 1
- tabsPage[actualPage] = {}
- table.insert(tabsPage[actualPage], v["id"])
- charNumber = v["name"]:len() + 2
- end
- end
- if activeTabPage > actualPage then
- activeTabPage = actualPage
- end
- if activeTab == 0 and getTabCount() > 0 then
- activeTab = 1
- end
- updateTabs()
- term.setBackgroundColor(oldColor)
- end
- function getTabCount()
- local tabCount = 0
- for k in pairs(tabs) do
- tabCount = tabCount + 1
- end
- return tabCount
- end
- function getTabPageCount()
- return #tabsPage
- end
- function getTabPageCountBeforeActive()
- local tabBefore = 0
- for i = 1, activeTabPage - 1 do
- tabBefore = tabBefore + #tabsPage[i]
- end
- return tabBefore
- end
- function linkToTab(tabId, tWidget)
- if not tabId or not tabs[tabId] then
- return false, "Unknown Tab"
- end
- if type(tWidget) ~= "table" then
- return false, "Widget must be a table"
- end
- local widgetId = tWidget["id"]
- local monX, monY = term.getSize()
- widgets[widgetId] = tWidget
- table.insert(tabs[tabId]["linkedWidgets"], widgetId)
- if activeTabData["id"] ~= tabId then
- if widgets[widgetId]["startY"] then
- widgets[widgetId]["startY"] = widgets[widgetId]["startY"] + monY
- end
- if widgets[widgetId]["endY"] then
- widgets[widgetId]["endY"] = widgets[widgetId]["endY"] + monY
- end
- end
- widgets[widgetId]["tab"] = tabId
- setProperty(widgetId, "enabled", true)
- return true
- end
- function unlinkFromTab(id)
- if not id or not widgets[id] or not widgets[id]["tab"] then
- return false
- end
- for i = 1, #tabs[widgets[id]["tab"]]["linkedWidgets"] do
- if tabs[widgets[id]["tab"]]["linkedWidgets"][i] == id then
- table.remove(tabs[widgets[id]["tab"]]["linkedWidgets"], i)
- break
- end
- end
- widgets[id]["tab"] = nil
- end
- function addTab(id, sName, nPosition)
- if not sName then
- return false
- end
- local nPosition = nPosition or getTabCount() + 1
- tabs[id] = {}
- tabs[id]["name"] = sName
- tabs[id]["position"] = nPosition
- tabs[id]["id"] = id
- tabs[id]["linkedWidgets"] = {}
- updateTabManager()
- return tabs[id]
- end
- function removeTab(id)
- if not id or not tabs[id] then
- return false
- end
- if tabs[id]["position"] < activeTabData["position"] then
- activeTab = activeTab - 1
- elseif tabs[id]["position"] == activeTabData["position"] then
- activeTab = 1
- end
- tabs[id] = nil
- updateTabManager()
- return true
- end
- function deleteAllTabs()
- lastSessionTabs = tabs
- tabs = {}
- end
- function deleteWidget(id)
- if widgets[id] then
- setProperty(id, "enabled", false)
- if widgets[id]["scrollManager"] and widgets[widgets[id]["scrollManager"]] then
- for i = 1, #widgets[widgets[id]["scrollManager"]]["linkedWidgets"] do
- if widgets[widgets[id]["scrollManager"]]["linkedWidgets"][i] == id then
- table.remove(widgets[widgets[id]["scrollManager"]]["linkedWidgets"], i)
- break
- end
- end
- end
- widgets[id] = nil
- end
- end
- function deleteAllWidgets()
- lastSessionWidgets = widgets
- widgets = {}
- end
- function getWidgetList()
- local widgetList = {}
- for k, v in pairs(widgets) do
- widgetList[k] = v["type"]
- end
- return widgetList
- end
- function getWidgetListByType(sType)
- if not sType then
- return false
- end
- local widgetList = {}
- for k, v in pairs(widgets) do
- if v["type"] == sType then
- table.insert(widgetList, k)
- end
- end
- return widgetList
- end
- function drawWindow(sTitle, bCloseButton, bNoAnimation, titleBarColor, bgColor, tabsBottom)
- local bDefaultCloseButton = true
- local sDefaultWindowTitle = "WindowTitle"
- if widgets["window"] then
- bDefaultCloseButton = widgets["window"]["enabled"]
- sDefaultWindowTitle = widgets["window"]["title"]
- end
- if type(bCloseButton) == "nil" then
- bCloseButton = bDefaultCloseButton
- end
- local sWindowTitle = sTitle or sDefaultWindowTitle
- local monX, monY = term.getSize()
- local titleBarColor = titleBarColor or colors.gray
- local bgColor = bgColor or colors.lightGray
- local tabsBottom = tabsBottom or false
- term.setBackgroundColor(colors.black)
- term.clear()
- paintutils.drawLine(1, 1, monX, 1, titleBarColor)
- term.setCursorPos(1, 1)
- term.write(sWindowTitle)
- widgets["window"] = {}
- widgets["window"]["startX"] = monX
- widgets["window"]["startY"] = 1
- widgets["window"]["endX"] = monX
- widgets["window"]["endY"] = 1
- widgets["window"]["btnColor"] = colors.red
- widgets["window"]["text"] = "X"
- widgets["window"]["title"] = sWindowTitle
- widgets["window"]["titleBarColor"] = titleBarColor
- widgets["window"]["bgColor"] = bgColor
- widgets["window"]["tabsBottom"] = tabsBottom
- widgets["window"]["type"] = "widget_close_button"
- if bCloseButton == nil or bCloseButton == true then
- paintutils.drawPixel(monX, 1, colors.red)
- term.setCursorPos(monX, 1)
- term.write("X")
- widgets["window"]["enabled"] = true
- else
- widgets["window"]["enabled"] = false
- end
- if not bNoAnimation then
- local animationSpeed = math.ceil((monY - 1) * (0.05 / 0.3))
- for i = 2, monY, animationSpeed do
- paintutils.drawFilledBox(1, i, monX, i + (animationSpeed - 1), bgColor)
- sleep(0.05)
- end
- else
- paintutils.drawFilledBox(1, 2, monX, monY, bgColor)
- end
- term.setCursorPos(1, 2)
- term.setBackgroundColor(bgColor)
- for k, v in pairs(widgets) do
- widgetUpdate(k)
- end
- if getTabCount() > 0 then
- updateTabs()
- end
- return true
- end
- function redrawWindow()
- return drawWindow(nil, nil, true)
- end
- function closeWindow(bNoAnim)
- local monX, monY = term.getSize()
- lastSessionWidgets = widgets
- lastSessionTabs = tabs
- if not bNoAnim then
- local animationSpeed = 0 - math.ceil((monY - 1) * (0.05 / 0.3))
- for i = monY, 2, animationSpeed do
- paintutils.drawFilledBox(1, i, monX, i - (animationSpeed + 1), colors.black)
- sleep(0.01)
- end
- paintutils.drawLine(1, 3, monX, 3, colors.black)
- paintutils.drawLine(1, 2, monX, 2, colors.black)
- sleep(0.2)
- end
- term.setBackgroundColor(colors.black)
- term.clear()
- term.setCursorPos(1, 1)
- deleteAllWidgets()
- deleteAllTabs()
- bRun = false
- end
- function linkToScrollManager(sScrollManagerId, tWidget)
- if not widgets[sScrollManagerId] or widgets[sScrollManagerId]["type"] ~= "widget_scrollmanager" then
- return false, "Unknown ScrollManager"
- end
- if type(tWidget) ~= "table" then
- return false, "Widget must be a table"
- end
- local widgetId = tWidget["id"]
- local monX, monY = term.getSize()
- local addX = widgets[sScrollManagerId]["startX"] - 1
- local addY = widgets[sScrollManagerId]["startY"] - 1
- if widgets[sScrollManagerId]["size"] < tWidget["endY"] and widgets[sScrollManagerId]["autosize"] then
- widgets[sScrollManagerId]["size"] = tWidget["endY"]
- widgetUpdate(sScrollManagerId)
- end
- widgets[widgetId] = tWidget
- table.insert(widgets[sScrollManagerId]["linkedWidgets"], widgetId)
- if widgets[widgetId]["startX"] then
- widgets[widgetId]["startX"] = widgets[widgetId]["startX"] + addX
- end
- if widgets[widgetId]["startY"] then
- widgets[widgetId]["startY"] = widgets[widgetId]["startY"] + addY
- if widgets[widgetId]["startY"] > widgets[sScrollManagerId]["endY"] then
- widgets[widgetId]["startY"] = widgets[widgetId]["startY"] + (monY - widgets[sScrollManagerId]["endY"])
- end
- end
- if widgets[widgetId]["endX"] then
- widgets[widgetId]["endX"] = widgets[widgetId]["endX"] + addX
- end
- if widgets[widgetId]["endY"] then
- widgets[widgetId]["endY"] = widgets[widgetId]["endY"] + addY
- if widgets[widgetId]["endY"] > widgets[sScrollManagerId]["endY"] and widgets[widgetId]["startY"] > widgets[sScrollManagerId]["endY"] then
- widgets[widgetId]["endY"] = widgets[widgetId]["endY"] + (monY - widgets[sScrollManagerId]["endY"])
- end
- end
- widgets[widgetId]["scrollManager"] = sScrollManagerId
- setProperty(widgetId, "enabled", true)
- return true
- end
- function autoResizeScrollManager(sScrollManagerId)
- if not sScrollManagerId or not widgets[sScrollManagerId] or widgets[sScrollManagerId]["type"] ~= "widget_scrollmanager" then
- return false, "Unknown ScrollManager"
- end
- local maxEndY = 0
- local widgetStartX, widgetStartY, widgetEndX, widgetEndY = getWidgetHitbox(sScrollManagerId)
- local monX, monY = term.getSize()
- local scrollManagerTopPadding = widgetStartY - 1
- local scrollManagerBotPadding = monY - widgetEndY
- if scrollManagerTopPadding < 0 then
- scrollManagerTopPadding = 0
- end
- if scrollManagerBotPadding < 0 then
- scrollManagerBotPadding = 0
- end
- for i = 1, #widgets[sScrollManagerId]["linkedWidgets"] do
- local currentWidgetEndY = widgets[widgets[sScrollManagerId]["linkedWidgets"][i]]["endY"]
- if currentWidgetEndY < 1 then
- currentWidgetEndY = currentWidgetEndY + scrollManagerTopPadding
- end
- if currentWidgetEndY > monY then
- currentWidgetEndY = currentWidgetEndY - scrollManagerBotPadding
- end
- if currentWidgetEndY + widgets[sScrollManagerId]["valuesShownMin"] - 1 > maxEndY then
- maxEndY = currentWidgetEndY + widgets[sScrollManagerId]["valuesShownMin"] - 1
- end
- end
- maxEndY = maxEndY - scrollManagerTopPadding
- if maxEndY < widgetEndY - widgetStartY + 1 then
- maxEndY = widgetEndY - widgetStartY + 1
- end
- widgets[sScrollManagerId]["size"] = maxEndY
- if widgets[sScrollManagerId]["valuesShownMax"] > maxEndY then
- scrollScrollManagerTo(widgets[sScrollManagerId]["size"] - widgets[sScrollManagerId]["height"], sScrollManagerId)
- end
- widgetUpdate(sScrollManagerId)
- end
- function createButton(id, startX, startY, endX, endY, btnColor, sText, bAnim)
- -- Ensure backward compatibility with older version of arcUI
- if (type(sText) == "number" or not sText) and type(btnColor) == "string" then
- sText, btnColor = reverseTwoArgs(sText, btnColor)
- end
- -- Ensure types of args
- id = tostringn(id)
- startX = math.floor(tonumber(startX))
- startY = math.floor(tonumber(startY))
- endX = math.floor(tonumber(endX))
- endY = math.floor(tonumber(endY))
- btnColor = tonumber(btnColor)
- sText = tostringn(sText)
- -- Check boolean args
- if bAnim == nil then
- bAnim = true
- end
- -- Check required and optionals args
- local bValidArgs, sErrMsg = checkArguments(true, id, "string", startX, "number", startY, "number", endX, "number", endY, "number", sText, "string")
- if not bValidArgs then
- return false, sErrMsg
- end
- bValidArgs, sErrMsg = checkArguments(false, btnColor, "number", bAnim, "boolean")
- if not bValidArgs then
- return false, sErrMsg
- end
- -- Creating the widget
- local tWidget = {}
- tWidget["startX"] = startX
- tWidget["startY"] = startY
- tWidget["endX"] = endX
- tWidget["endY"] = endY
- tWidget["height"] = endY - startY
- tWidget["btnColor"] = btnColor or colors.blue
- tWidget["text"] = sText
- tWidget["enabled"] = false
- tWidget["type"] = "widget_button"
- tWidget["oldBtnColor"] = btnColor
- tWidget["animation"] = bAnim
- tWidget["id"] = id
- -- Returning the widget
- return tWidget
- end
- function createProgress(id, startX, startY, endX, maxValue, value)
- -- Ensure types of args
- id = tostringn(id)
- startX = math.floor(tonumber(startX))
- startY = math.floor(tonumber(startY))
- endX = math.floor(tonumber(endX))
- maxValue = tonumber(maxValue)
- value = tonumber(value)
- -- Check required args
- local bValidArgs, sErrMsg = checkArguments(true, id, "string", startX, "number", startY, "number", endX, "number", maxValue, "number", value, "number")
- if not bValidArgs then
- return false, sErrMsg
- end
- -- Creating the widget
- tWidget = {}
- tWidget["startX"] = startX
- tWidget["startY"] = startY
- tWidget["endX"] = endX
- tWidget["endY"] = startY
- tWidget["height"] = 0
- tWidget["value"] = value
- tWidget["maxValue"] = maxValue
- tWidget["anim_health"] = 50
- tWidget["anim_pixel"] = startX
- tWidget["enabled"] = false
- tWidget["type"] = "widget_progress"
- tWidget["width"] = endX - startX
- tWidget["id"] = id
- -- Returning the widget
- return tWidget
- end
- function createMarqueeProgress(id, startX, startY, endX)
- -- Ensure types of args
- id = tostringn(id)
- startX = math.floor(tonumber(startX))
- startY = math.floor(tonumber(startY))
- endX = math.floor(tonumber(endX))
- -- Check required args
- local bValidArgs, sErrMsg = checkArguments(true, id, "string", startX, "number", startY, "number", endX, "number")
- if not bValidArgs then
- return false, sErrMsg
- end
- -- Creating the widget
- tWidget = {}
- tWidget["startX"] = startX
- tWidget["startY"] = startY
- tWidget["endX"] = endX
- tWidget["endY"] = startY
- tWidget["height"] = 0
- tWidget["enabled"] = false
- tWidget["type"] = "widget_progress_marquee"
- tWidget["width"] = endX - startX
- tWidget["minGreen"] = startX
- tWidget["maxGreen"] = startX + 2
- tWidget["animDirection"] = "+"
- tWidget["id"] = id
- -- Returning the widget
- return tWidget
- end
- function createLabel(id, startX, startY, sText, bgColor, textColor)
- -- Ensure types of args
- id = tostringn(id)
- startX = tonumber(startX)
- startY = tonumber(startY)
- sText = tostringn(sText)
- bgColor = tonumber(bgColor)
- textColor = tonumber(bgColor)
- -- Check required and optionals args
- local bValidArgs, sErrMsg = checkArguments(true, id, "string", startX, "number", startY, "number", sText, "string")
- if not bValidArgs then
- return false, sErrMsg
- end
- bValidArgs, sErrMsg = checkArguments(false, bgColor, "number", textColor, "number")
- if not bValidArgs then
- return false, sErrMsg
- end
- -- Creting the widget
- tWidget = {}
- tWidget["startX"] = startX
- tWidget["startY"] = startY
- tWidget["endX"] = startX
- tWidget["endY"] = startY
- tWidget["height"] = 0
- tWidget["text"] = sText
- tWidget["bgColor"] = bgColor or term.getBackgroundColor()
- tWidget["textColor"] = textColor or colors.white
- tWidget["enabled"] = false
- tWidget["type"] = "widget_label"
- tWidget["id"] = id
- -- Returning the widget
- return tWidget
- end
- function createTextbox(id, startX, startY, endX, placeholder, charReplace, bHistory, tHistory, tCompletion, inactiveColor, activeColor, textInactiveColor, textActiveColor, bNumericOnly)
- -- Ensure types of args
- id = tostringn(id)
- startX = math.floor(tonumber(startX))
- startY = math.floor(tonumber(startY))
- endX = math.floor(tonumber(endX))
- placeholder = tostringn(placeholder)
- charReplace = tostringn(charReplace)
- inactiveColor = tonumber(inactiveColor)
- activeColor = tonumber(activeColor)
- textInactiveColor = tonumber(textInactiveColor)
- textActiveColor = tonumber(textActiveColor)
- -- Check boolean args
- if bHistory == nil then
- bHistory = false
- end
- if bNumericOnly == nil then
- bNumericOnly = false
- end
- -- Check required and optionals args
- local bValidArgs, sErrMsg = checkArguments(true, id, "string", startX, "number", startY, "number", endX, "number")
- if not bValidArgs then
- return false, sErrMsg
- end
- bValidArgs, sErrMsg = checkArguments(false, placeholder, "string", charReplace, "string", bHistory, "boolean", tHistory, "table", tCompletion, "table", inactiveColor, "number", activeColor, "number", textInactiveColor, "number", textActiveColor, "number", bNumericOnly, "boolean")
- if not bValidArgs then
- return false, sErrMsg
- end
- -- Creating the widget
- tWidget = {}
- tWidget["startX"] = startX
- tWidget["startY"] = startY
- tWidget["endX"] = endX
- tWidget["endY"] = startY
- tWidget["height"] = 0
- tWidget["width"] = endX - startX
- tWidget["text"] = placeholder
- tWidget["value"] = ""
- tWidget["charReplace"] = charReplace
- tWidget["bHistory"] = bHistory
- tWidget["tHistory"] = tHistory or {}
- tWidget["tCompletion"] = tCompletion or {}
- tWidget["inactiveColor"] = inactiveColor or colors.cyan
- tWidget["activeColor"] = activeColor or colors.green
- tWidget["textInactiveColor"] = textInactiveColor or colors.gray
- tWidget["textActiveColor"] = textActiveColor or colors.white
- tWidget["numericOnly"] = bNumericOnly
- tWidget["enabled"] = false
- tWidget["type"] = "widget_textbox"
- tWidget["id"] = id
- -- Returning the widget
- return tWidget
- end
- function createSwitch(id, startX, startY, sText, bState)
- -- Ensure types of args
- id = tostringn(id)
- startX = math.floor(tonumber(startX))
- startY = math.floor(tonumber(startY))
- sText = tostringn(sText)
- -- Check boolean args
- if bState == nil then
- bState = false
- end
- -- Check required and optionals args
- local bValidArgs, sErrMsg = checkArguments(true, id, "string", startX, "number", startY, "number", sText, "string")
- if not bValidArgs then
- return false, sErrMsg
- end
- bValidArgs, sErrMsg = checkArguments(false, bState, "boolean")
- if not bValidArgs then
- return false, sErrMsg
- end
- -- Creating the widget
- tWidget = {}
- tWidget["startX"] = startX
- tWidget["startY"] = startY
- tWidget["endX"] = startX
- tWidget["endY"] = startY
- tWidget["height"] = 0
- tWidget["text"] = sText
- tWidget["enabled"] = false
- tWidget["state"] = bState
- tWidget["type"] = "widget_switch"
- tWidget["id"] = id
- -- Returning the widget
- return tWidget
- end
- function createNumeric(id, startX, startY, endX, value, minValue, maxValue, increment)
- -- Ensure type of args
- id = tostringn(id)
- startX = math.floor(tonumber(startX))
- startY = math.floor(tonumber(startY))
- endX = math.floor(tonumber(endX))
- value = tonumber(value)
- minValue = tonumber(minValue)
- maxValue = tonumber(maxValue)
- increment = tonumber(increment)
- -- Check required and optionals args
- local bValidArgs, sErrMsg = checkArguments(true, id, "string", startX, "number", startY, "number", endX, "number", value, "number", minValue, "number", maxValue, "number")
- if not bValidArgs then
- return false, sErrMsg
- end
- bValidArgs, sErrMsg = checkArguments(false, increment, "number")
- if not bValidArgs then
- return false, sErrMsg
- end
- -- Check widget bounds
- if value > maxValue or value < minValue then
- return false, "Value must be between maxValue and minValue"
- end
- -- Creating the widget
- tWidget = {}
- tWidget["startX"] = startX
- tWidget["startY"] = startY
- tWidget["endX"] = endX
- tWidget["endY"] = startY
- tWidget["height"] = 0
- tWidget["width"] = endX - startX
- tWidget["value"] = value
- tWidget["minValue"] = minValue
- tWidget["maxValue"] = maxValue
- tWidget["increment"] = increment or 1
- tWidget["activeColor"] = colors.blue
- tWidget["numericOnly"] = true
- tWidget["enabled"] = false
- tWidget["type"] = "widget_numeric"
- tWidget["id"] = id
- -- Returning the widget
- return tWidget
- end
- function createList(id, startX, startY, endX, endY, tValues, nSelectedColor, nTextColor, nBGColor, nSBGColor)
- -- Ensure type of args
- id = tostringn(id)
- startX = math.floor(tonumber(startX))
- startY = math.floor(tonumber(startY))
- endX = math.floor(tonumber(endX))
- endY = math.floor(tonumber(endY))
- nSelectedColor = tonumber(nSelectedColor)
- nTextColor = tonumber(nTextColor)
- nBGColor = tonumber(nBGColor)
- nSBGColor = tonumber(nSBGColor)
- -- Check required and optionals args
- local bValidArgs, sErrMsg = checkArguments(true, id, "string", startX, "number", startY, "number", endX, "number", endY, "number", tValues, "table")
- if not bValidArgs then
- return false, sErrMsg
- end
- bValidArgs, sErrMsg = checkArguments(false, nSelectedColor, "number", nTextColor, "number", nBGColor, "number", nSBGColor, "number")
- if not bValidArgs then
- return false, sErrMsg
- end
- -- Creating the widget
- tWidget = {}
- tWidget["startX"] = startX
- tWidget["startY"] = startY
- tWidget["endX"] = endX
- tWidget["endY"] = endY
- tWidget["height"] = endY - startY
- tWidget["values"] = tValues
- tWidget["valuesShown"] = {}
- tWidget["valuesShownMin"] = 1
- tWidget["valuesShownMax"] = 0
- tWidget["selectedValue"] = 0
- tWidget["selectedColor"] = nSelectedColor or colors.blue
- tWidget["oldSelectedColor"] = colors.lightBlue
- tWidget["textColor"] = nTextColor or colors.white
- tWidget["backgroundColor"] = nBGColor or colors.lightBlue
- tWidget["secondBackgroundColor"] = nSBGColor or nBGColor or colors.lightBlue
- tWidget["enabled"] = false
- tWidget["type"] = "widget_list"
- tWidget["id"] = id
- -- Returning the widget
- return tWidget
- end
- function createNumericSlider(id, startX, startY, endX, value, minValue, maxValue, sliderColor)
- -- Ensure types of args
- id = tostringn(id)
- startX = math.floor(tonumber(startX))
- startY = math.floor(tonumber(startY))
- endX = math.floor(tonumber(endX))
- value = tonumber(value)
- minValue = tonumber(minValue)
- maxValue = tonumber(maxValue)
- sliderColor = tonumber(sliderColor)
- -- Check required and optionals args
- local bValidArgs, sErrMsg = checkArguments(true, id, "string", startX, "number", startY, "number", endX, "number")
- if not bValidArgs then
- return false, sErrMsg
- end
- bValidArgs, sErrMsg = checkArguments(false, value, "number", minValue, "number", maxValue, "number", sliderColor, "number")
- if not bValidArgs then
- return false, sErrMsg
- end
- -- Creating the widget
- tWidget = {}
- tWidget["startX"] = startX
- tWidget["startY"] = startY
- tWidget["endX"] = endX
- tWidget["endY"] = startY
- tWidget["height"] = 0
- tWidget["value"] = value or 0
- tWidget["minValue"] = minValue or 0
- tWidget["maxValue"] = maxValue or 100
- tWidget["sliderColor"] = sliderColor or colors.gray
- tWidget["enabled"] = false
- tWidget["type"] = "widget_numericslider"
- tWidget["id"] = id
- -- Returning the widget
- return tWidget
- end
- function createScrollManager(id, startX, startY, endX, endY, autoSize, size)
- -- Ensure types of args
- id = tostringn(id)
- startX = math.floor(tonumber(startX))
- startY = math.floor(tonumber(startY))
- endX = math.floor(tonumber(endX))
- endY = math.floor(tonumber(endY))
- size = tonumber(size)
- -- Check boolean args
- if autoSize == nil then
- autoSize = true
- end
- -- Check required and optionals args
- local bValidArgs, sErrMsg = checkArguments(true, id, "string", startX, "number", startY, "number", endX, "number", endY, "number", autoSize, "boolean", size, "number")
- if not bValidArgs then
- return false, sErrMsg
- end
- -- Check widget bounds
- if autoSize == true or size < endY - startY + 1 then
- size = endY - startY + 1
- end
- -- Creating the widget
- tWidget = {}
- tWidget["startX"] = startX
- tWidget["startY"] = startY
- tWidget["endX"] = endX
- tWidget["endY"] = endY
- tWidget["height"] = endY - startY
- tWidget["size"] = size
- tWidget["autosize"] = autoSize
- tWidget["valuesShownMin"] = 1
- tWidget["valuesShownMax"] = 0
- tWidget["linkedWidgets"] = {}
- tWidget["enabled"] = false
- tWidget["type"] = "widget_scrollmanager"
- tWidget["id"] = id
- -- Returning the widget
- return tWidget
- end
- local function drawGenericWidget(tWidget, errMsg)
- if type(tWidget) == "table" then
- widgets[tWidget["id"]] = tWidget
- setProperty(tWidget["id"], "enabled", true)
- return true
- else
- return tWidget, errMsg
- end
- end
- function drawButton(...)
- return drawGenericWidget(createButton(...))
- end
- function drawProgress(...)
- return drawGenericWidget(createProgress(...))
- end
- function drawMarqueeProgress(...)
- return drawGenericWidget(createMarqueeProgress(...))
- end
- function drawLabel(...)
- return drawGenericWidget(createLabel(...))
- end
- function drawTextbox(...)
- return drawGenericWidget(createTextbox(...))
- end
- function drawSwitch(...)
- return drawGenericWidget(createSlider(...))
- end
- function drawNumeric(...)
- return drawGenericWidget(createNumeric(...))
- end
- function drawList(...)
- return drawGenericWidget(createList(...))
- end
- function drawNumericSlider(...)
- return drawGenericWidget(createNumericSlider(...))
- end
- function drawScrollManager(...)
- return drawGenericWidget(createScrollManager(...))
- end
- function createSlider(...)
- error("arcUI:\nSliders have been renamed to Switches.\nPlease update your function calls and event filters accordingly.\nCheck the documentation for more details.", 0)
- end
- function drawSlider(...)
- createSlider(...)
- end
- function openDialog(id, sTitle, sText, sLeftButtonText, sRightButtonText, bgColor, textColor, leftButtonColor, rightButtonColor, leftButtonTextColor, rightButtonTextColor, bHideCancelButton)
- if not sText then
- return false
- end
- local sLeftButtonText = sLeftButtonText or "Cancel"
- local sRightButtonText = sRightButtonText or "OK"
- local bgColor = bgColor or colors.white
- local textColor = textColor or colors.black
- local leftButtonColor = leftButtonColor or colors.gray
- local rightButtonColor = rightButtonColor or colors.gray
- local leftButtonTextColor = leftButtonTextColor or colors.lightGray
- local rightButtonTextColor = rightButtonTextColor or colors.lightBlue
- local hideCancelButton = false
- if bHideCancelButton == true then
- hideCancelButton = true
- end
- local results = false
- local click = {}
- bDialogRunning = true
- bCanButtonAnim = false
- local monX, monY = term.getSize()
- local dialogWindow = window.create(term.current(), 2, monY + 1, monX - 2, math.ceil(monY / 2))
- local oldTarget = term.redirect(dialogWindow)
- local dialogX, dialogY = term.getSize()
- term.setBackgroundColor(bgColor)
- term.clear()
- term.setTextColor(textColor)
- term.setCursorPos(dialogX / 2 - string.len(sTitle) / 2, 1)
- term.write(sTitle)
- term.setCursorPos(2, 3)
- print(sText)
- if not hideCancelButton then
- paintutils.drawFilledBox(1, dialogY - 1, math.floor(dialogX / 2) - 1, dialogY, leftButtonColor)
- paintutils.drawFilledBox(math.floor(dialogX / 2) + 1, dialogY - 1, dialogX, dialogY, rightButtonColor)
- term.setBackgroundColor(leftButtonColor)
- term.setTextColor(leftButtonTextColor)
- term.setCursorPos((dialogX / 4) - (string.len(sLeftButtonText) / 2), dialogY)
- term.write(sLeftButtonText)
- term.setBackgroundColor(rightButtonColor)
- term.setTextColor(rightButtonTextColor)
- term.setCursorPos(math.ceil(dialogX * 3 / 4) - (string.len(sRightButtonText) / 2), dialogY)
- term.write(sRightButtonText)
- else
- paintutils.drawFilledBox(1, dialogY - 1, dialogX, dialogY, rightButtonColor)
- term.setBackgroundColor(rightButtonColor)
- term.setTextColor(rightButtonTextColor)
- term.setCursorPos(math.ceil(dialogX / 2) - (string.len(sRightButtonText) / 2), dialogY)
- term.write(sRightButtonText)
- end
- for i = monY, monY / 2, -2 do
- dialogWindow.reposition(2, i)
- sleep(0.01)
- end
- if monY % 2 == 1 then
- dialogWindow.reposition(2, math.ceil(monY / 2))
- else
- dialogWindow.reposition(2, math.ceil(monY / 2) + 1)
- end
- local windowPosX, windowPosY = dialogWindow.getPosition()
- while true do
- local event, button, mousex, mousey = os.pullEvent("mouse_click")
- if mousex and mousey then
- mousex = mousex - windowPosX + 1
- mousey = mousey - windowPosY + 1
- if mousex >= 1 and mousex < math.floor(dialogX / 2) and mousey >= dialogY - 1 and mousey <= dialogY and not hideCancelButton then
- results = false
- click = {mousex, mousey}
- break
- elseif ((mousex >= 1 and hideCancelButton) or (mousex > math.floor(dialogX / 2) and not hideCancelButton)) and mousex <= dialogX and mousey >= dialogY - 1 and mousey <= dialogY then
- results = true
- click = {mousex, mousey}
- break
- end
- end
- end
- term.redirect(oldTarget)
- dialogWindow = nil
- term.setTextColor(colors.white)
- bDialogRunning = false
- bCanButtonAnim = true
- if widgets["window"] then
- redrawWindow()
- end
- return results, click
- end
- local function completer(sText, sWidget)
- local tComplete = {}
- for k, v in pairs(widgets[sWidget]["tCompletion"]) do
- if string.sub(v, 1, #sText) == sText then
- table.insert(tComplete, string.sub(v, #sText + 1, #v))
- end
- end
- return tComplete
- end
- local function scrollbarCompute(k, a1, a2, a3, widgetWorkingHeight)
- -- Scrollbar selected
- local selectedValue = a3 - widgets[k]["startY"]
- local navBarWorkingLength = (widgets[k]["endY"] - widgets[k]["startY"]) - 1
- if selectedValue < 1 then
- selectedValue = 1
- elseif selectedValue > widgets[k]["height"] + 1 then
- selectedValue = widgets[k]["height"] + 1
- end
- local indexSelectedValue = math.floor(selectedValue * widgetWorkingHeight / navBarWorkingLength)
- if selectedValue == 1 then
- indexSelectedValue = 1
- elseif selectedValue == navBarWorkingLength then
- indexSelectedValue = widgetWorkingHeight
- end
- if indexSelectedValue > widgetWorkingHeight - math.floor((widgets[k]["endY"] - widgets[k]["startY"] + 1) / 2) then
- indexSelectedValue = widgetWorkingHeight - math.floor((widgets[k]["endY"] - widgets[k]["startY"] + 1) / 2)
- if (widgets[k]["endY"] - widgets[k]["startY"] + 1) % 2 == 0 then
- indexSelectedValue = indexSelectedValue + 1
- end
- end
- local newvaluesShownMin = indexSelectedValue - math.floor((widgets[k]["endY"] - widgets[k]["startY"] + 1) / 2)
- if newvaluesShownMin < 1 then
- newvaluesShownMin = 1
- end
- if newvaluesShownMin ~= widgets[k]["valuesShownMin"] then
- return newvaluesShownMin
- else
- return false
- end
- end
- function scrollScrollManager(scrollSize, k)
- scrollSize = tonumber(scrollSize)
- k = tostring(k)
- if type(scrollSize) ~= "number" then return false, "Argument #1: Expected number, got "..type(scrollSize) end
- if type(k) ~= "string" then return false, "Argument #2: Expected string, got "..type(k) end
- if not widgets[k] or widgets[k]["type"] ~= "widget_scrollmanager" then
- return false, "Unknown ScrollManager"
- end
- local widgetStartX, widgetStartY, widgetEndX, widgetEndY, _, widgetLossTopY, widgetLossBotY = getWidgetHitbox(k)
- local monX, monY = term.getSize()
- local scrollManagerTopPadding = widgetStartY - 1
- local scrollManagerBotPadding = monY - widgetEndY
- if scrollSize < 0 then
- --Moins
- if widgets[k]["valuesShownMin"] + scrollSize < 1 then
- scrollSize = 1 - widgets[k]["valuesShownMin"]
- end
- if widgets[k]["valuesShownMin"] > 1 then
- for i = 1, #widgets[k]["linkedWidgets"] do
- local actualWidgetStartY = widgets[widgets[k]["linkedWidgets"][i]]["startY"]
- local actualWidgetEndY = widgets[widgets[k]["linkedWidgets"][i]]["endY"]
- local computedWidgetStartY = actualWidgetStartY - scrollSize
- local computedWidgetEndY = actualWidgetEndY - scrollSize
- if actualWidgetEndY < 1 and computedWidgetEndY >= 1 then
- computedWidgetStartY = computedWidgetStartY + scrollManagerTopPadding
- computedWidgetEndY = computedWidgetEndY + scrollManagerTopPadding
- end
- if actualWidgetStartY <= widgetEndY and computedWidgetStartY > widgetEndY then
- computedWidgetStartY = computedWidgetStartY + scrollManagerBotPadding
- computedWidgetEndY = computedWidgetEndY + scrollManagerBotPadding
- end
- widgets[widgets[k]["linkedWidgets"][i]]["startY"] = computedWidgetStartY
- widgets[widgets[k]["linkedWidgets"][i]]["endY"] = computedWidgetEndY
- end
- setProperty(k, "valuesShownMin", widgets[k]["valuesShownMin"] + scrollSize)
- end
- elseif scrollSize > 0 then
- --Plus
- if widgets[k]["valuesShownMin"] + scrollSize > widgets[k]["size"] - widgets[k]["height"] then
- scrollSize = widgets[k]["size"] - widgets[k]["height"] - widgets[k]["valuesShownMin"]
- end
- if widgets[k]["valuesShownMax"] < widgets[k]["size"] then
- for i = 1, #widgets[k]["linkedWidgets"] do
- local actualWidgetStartY = widgets[widgets[k]["linkedWidgets"][i]]["startY"]
- local actualWidgetEndY = widgets[widgets[k]["linkedWidgets"][i]]["endY"]
- local computedWidgetStartY = actualWidgetStartY - scrollSize
- local computedWidgetEndY = actualWidgetEndY - scrollSize
- if actualWidgetStartY > monY and computedWidgetStartY <= monY then
- computedWidgetStartY = computedWidgetStartY - scrollManagerBotPadding
- computedWidgetEndY = computedWidgetEndY - scrollManagerBotPadding
- end
- if actualWidgetEndY >= widgetStartY and computedWidgetEndY < widgetStartY then
- computedWidgetStartY = computedWidgetStartY - scrollManagerTopPadding
- computedWidgetEndY = computedWidgetEndY - scrollManagerTopPadding
- end
- widgets[widgets[k]["linkedWidgets"][i]]["startY"] = computedWidgetStartY
- widgets[widgets[k]["linkedWidgets"][i]]["endY"] = computedWidgetEndY
- end
- setProperty(k, "valuesShownMin", widgets[k]["valuesShownMin"] + scrollSize)
- end
- end
- end
- function scrollScrollManagerTo(nScrollTo, sScrollManagerId)
- nScrollTo = tonumber(nScrollTo)
- sScrollManagerId = tostring(sScrollManagerId)
- if type(nScrollTo) ~= "number" then return false, "Argument #1: Expected number, got "..type(nScrollTo) end
- if type(sScrollManagerId) ~= "string" then return false, "Argument #2: Expected string, got "..type(sScrollManagerId) end
- if not widgets[sScrollManagerId] or widgets[sScrollManagerId]["type"] ~= "widget_scrollmanager" then
- return false, "Unknown ScrollManager"
- end
- if nScrollTo < 1 or nScrollTo > widgets[sScrollManagerId]["size"] then
- return false, "Argument #1: Out of Bounds Error"
- end
- scrollScrollManager(nScrollTo - widgets[sScrollManagerId]["valuesShownMin"], sScrollManagerId)
- end
- local function useTextbox(textboxId, widgetStartX, widgetStartY, widgetEndX, widgetEndY)
- local runLoop = true
- while runLoop do
- local oldColor = term.getBackgroundColor()
- local oldTextColor = term.getTextColor()
- paintutils.drawLine(widgetStartX, widgetStartY, widgetEndX, widgetStartY, widgets[textboxId]["activeColor"])
- term.setCursorPos(widgetStartX, widgetStartY)
- term.setTextColor(widgets[textboxId]["textActiveColor"])
- local rep, lastUsedKey = custRead(widgets[textboxId]["width"] + widgetStartX, widgets[textboxId]["charReplace"], widgets[textboxId]["tHistory"], completer, textboxId)
- term.setTextColor(colors.white)
- if widgets[textboxId]["bHistory"] then
- table.insert(widgets[textboxId]["tHistory"], rep)
- end
- if widgets[textboxId]["value"] ~= rep then
- widgets[textboxId]["value"] = rep
- os.queueEvent("textbox_text", textboxId, rep, lastUsedKey == 28)
- end
- if widgets[textboxId]["value"] == "" then
- paintutils.drawLine(widgetStartX, widgetStartY, widgetEndX, widgetStartY, oldColor)
- paintutils.drawLine(widgetStartX + 1, widgetStartY, widgetEndX - 1, widgetStartY, widgets[textboxId]["inactiveColor"])
- if widgets[textboxId]["text"] then
- term.setCursorPos(widgetStartX + 1, widgetStartY)
- term.setTextColor(widgets[textboxId]["textInactiveColor"])
- term.write(widgets[textboxId]["text"])
- term.setTextColor(colors.white)
- end
- end
- term.setBackgroundColor(oldColor)
- term.setTextColor(oldTextColor)
- if lastUsedKey == 15 and widgets[textboxId]["group"] then
- local bNextFound = false
- local bLoopBroken = false
- local firstTextbox = ""
- for k, v in pairs(textboxGroup[widgets[textboxId]["group"]]) do
- if firstTextbox == "" then
- firstTextbox = v
- end
- if bNextFound then
- textboxId = v
- widgetStartX, widgetStartY, widgetEndX, widgetEndY = getWidgetHitbox(textboxId)
- bLoopBroken = true
- break
- end
- if v == textboxId then
- bNextFound = true
- end
- end
- if not bLoopBroken then
- textboxId = firstTextbox
- widgetStartX, widgetStartY, widgetEndX, widgetEndY = getWidgetHitbox(textboxId)
- end
- else
- runLoop = false
- end
- end
- end
- function eventHandler()
- local mouseDragUtility = ""
- while bRun do
- event, a1, a2, a3, a4, a5 = os.pullEvent()
- local monX, monY = term.getSize()
- if bDialogRunning == false then
- if event == "mouse_click" or (event == "monitor_touch" and monX ~= 51 and monY ~= 19) then
- if getTabCount() > 0 and ((a3 == 2 and not widgets["window"]["tabsBottom"]) or (a3 == monY and widgets["window"]["tabsBottom"])) then
- if a2 == monX and getTabPageCount() > 1 then
- -- Next button clicked
- if activeTabPage < getTabPageCount() then
- activeTabPage = activeTabPage + 1
- updateTabs()
- end
- elseif a2 == monX - 1 and getTabPageCount() > 1 then
- -- Previous button clicked
- if activeTabPage > 1 then
- activeTabPage = activeTabPage - 1
- updateTabs()
- end
- else
- local activeTabPageIDs = tabsPage[activeTabPage]
- local tabBefore = getTabPageCountBeforeActive()
- local oldPosX = 0
- local posX = 0
- for i = 1, #activeTabPageIDs do
- local tabIndex = tabBefore + i
- oldPosX = posX + 1
- posX = posX + tabs[activeTabPageIDs[i]]["name"]:len() + 2
- if a2 >= oldPosX and a2 <= posX then
- if activeTabData == tabs[activeTabPageIDs[i]] then
- break
- end
- activeTab = tabIndex
- oldActiveTabData = activeTabData
- activeTabData = tabs[activeTabPageIDs[i]]
- updateTabs()
- os.queueEvent("tab_changed", activeTabData["id"], a1, a2, a3)
- break
- end
- end
- end
- else
- for k, v in pairs(widgets) do
- local widgetStartX, widgetStartY, widgetEndX, widgetEndY, _, widgetLossTopY, widgetLossBotY = getWidgetHitbox(k)
- if widgets[k]["enabled"] == true and ((widgets[k]["tab"] and widgets[k]["tab"] == activeTabData["id"]) or type(widgets[k]["tab"]) == "nil") then
- if widgets[k]["type"] == "widget_button" and a2 <= widgetEndX and a2 >= widgetStartX and a3 <= widgetEndY and a3 >= widgetStartY then
- os.queueEvent("button_clicked", k, a1, a2, a3)
- if widgets[k]["animation"] == true then
- os.queueEvent("button_anim", k)
- end
- elseif widgets[k]["type"] == "widget_close_button" and a2 <= widgetEndX and a2 >= widgetStartX and a3 <= widgetEndY and a3 >= widgetStartY then
- os.queueEvent("button_close_clicked")
- bRun = false
- elseif widgets[k]["type"] == "widget_textbox" and a2 <= widgetEndX and a2 >= widgetStartX and a3 == widgetStartY then
- useTextbox(k, widgetStartX, widgetStartY, widgetEndX, widgetEndY)
- elseif widgets[k]["type"] == "widget_switch" and a2 <= widgetStartX + 3 and a2 >= widgetStartX and a3 == widgetStartY then
- local oldColor = term.getBackgroundColor()
- if widgets[k]["state"] == true then
- widgets[k]["state"] = false
- paintutils.drawPixel(widgetStartX + 3, widgetStartY, colors.gray)
- sleep(0.05)
- paintutils.drawPixel(widgetStartX + 3, widgetStartY, colors.white)
- paintutils.drawPixel(widgetStartX + 2, widgetStartY, colors.gray)
- sleep(0.05)
- paintutils.drawPixel(widgetStartX + 2, widgetStartY, colors.white)
- paintutils.drawPixel(widgetStartX + 1, widgetStartY, colors.gray)
- sleep(0.05)
- paintutils.drawPixel(widgetStartX + 1, widgetStartY, colors.white)
- paintutils.drawPixel(widgetStartX, widgetStartY, colors.gray)
- sleep(0.05)
- elseif widgets[k]["state"] == false then
- widgets[k]["state"] = true
- paintutils.drawPixel(widgetStartX, widgetStartY, colors.lime)
- sleep(0.05)
- paintutils.drawPixel(widgetStartX, widgetStartY, colors.green)
- paintutils.drawPixel(widgetStartX + 1, widgetStartY, colors.lime)
- sleep(0.05)
- paintutils.drawPixel(widgetStartX + 1, widgetStartY, colors.green)
- paintutils.drawPixel(widgetStartX + 2, widgetStartY, colors.lime)
- sleep(0.05)
- paintutils.drawPixel(widgetStartX + 2, widgetStartY, colors.green)
- paintutils.drawPixel(widgetStartX + 3, widgetStartY, colors.lime)
- sleep(0.05)
- end
- term.setBackgroundColor(oldColor)
- os.queueEvent("switch_state", k, widgets[k]["state"], a1, a2, a3)
- elseif widgets[k]["type"] == "widget_numeric" and a2 >= widgetStartX and a2 <= widgetEndX and a3 == widgetStartY then
- local oldValue = widgets[k]["value"]
- if a2 == widgetStartX and a3 == widgetStartY then
- --Moins
- if widgets[k]["value"] - widgets[k]["increment"] > widgets[k]["minValue"] then
- widgets[k]["value"] = widgets[k]["value"] - widgets[k]["increment"]
- else
- widgets[k]["value"] = widgets[k]["minValue"]
- end
- elseif a2 == widgetEndX and a3 == widgetStartY then
- --Plus
- if widgets[k]["value"] + widgets[k]["increment"] < widgets[k]["maxValue"] then
- widgets[k]["value"] = widgets[k]["value"] + widgets[k]["increment"]
- else
- widgets[k]["value"] = widgets[k]["maxValue"]
- end
- elseif a2 > widgetStartX and a2 < widgetEndX and a3 == widgetStartY then
- -- Bar
- local oldColor = term.getBackgroundColor()
- local oldTextColor = term.getTextColor()
- paintutils.drawLine(widgetStartX + 1, widgetStartY, widgetEndX - 1, widgetStartY, colors.blue)
- term.setCursorPos(widgetStartX + 1, widgetStartY)
- term.setTextColor(colors.white)
- local rep = custRead(widgets[k]["width"] + widgetStartX - 1, nil, nil, nil, k)
- if tonumber(rep) then
- rep = tonumber(rep)
- if rep < widgets[k]["minValue"] then
- rep = widgets[k]["minValue"]
- elseif rep > widgets[k]["maxValue"] then
- rep = widgets[k]["maxValue"]
- end
- widgets[k]["value"] = rep
- end
- term.setBackgroundColor(oldColor)
- term.setTextColor(oldTextColor)
- end
- widgetUpdate(k)
- if oldValue ~= widgets[k]["value"] then
- os.queueEvent("numeric_value", k, widgets[k]["value"], a1, a2, a3)
- end
- elseif widgets[k]["type"] == "widget_list" then
- local oldValue = widgets[k]["selectedValue"]
- if a2 == widgetEndX and a3 - widgetLossTopY == widgetStartY then
- --Moins
- if widgets[k]["valuesShownMin"] > 1 then
- setProperty(k, "valuesShownMin", widgets[k]["valuesShownMin"] - 1)
- end
- elseif a2 == widgetEndX and a3 + widgetLossBotY == widgetEndY then
- --Plus
- if widgets[k]["valuesShownMax"] < #widgets[k]["values"] then
- setProperty(k, "valuesShownMin", widgets[k]["valuesShownMin"] + 1)
- end
- elseif a2 == widgetEndX and a3 >= widgetStartY and a3 <= widgetEndY then
- -- Scrollbar selected
- mouseDragUtility = k
- local scrollbarResult = scrollbarCompute(k, a1, a2, a3, #widgets[k]["values"])
- if scrollbarResult then
- setProperty(k, "valuesShownMin", scrollbarResult)
- end
- elseif a2 <= widgetEndX - 1 and a2 >= widgetStartX and a3 <= widgetEndY and a3 >= widgetStartY then
- --Item selected
- local computedSelectedIndex = (a3 - (widgetStartY - 1)) + (widgets[k]["valuesShownMin"] - 1) + widgetLossTopY
- if computedSelectedIndex <= #widgets[k]["values"] and computedSelectedIndex ~= oldValue then
- setProperty(k, "selectedValue", computedSelectedIndex)
- os.queueEvent("list_anim", k)
- os.queueEvent("list_selected", k, widgets[k]["valuesShown"][a3 - (widgetStartY - 1)], a1, a2, a3)
- end
- end
- elseif widgets[k]["type"] == "widget_numericslider" and a2 >= widgetStartX and a2 <= widgetEndX and a3 == widgetStartY then
- local oldValue = widgets[k]["value"]
- mouseDragUtility = k
- local nNumericSliderLength = widgetEndX - widgetStartX
- local nClickPosition = a2 - widgetStartX
- local nNewValue = nClickPosition * (widgets[k]["maxValue"] - widgets[k]["minValue"]) / nNumericSliderLength
- nNewValue = nNewValue + widgets[k]["minValue"]
- widgets[k]["value"] = nNewValue
- widgetUpdate(k)
- if widgets[k]["value"] ~= oldValue then
- os.queueEvent("numericslider_value", k, widgets[k]["value"], a1, a2, a3)
- end
- elseif widgets[k]["type"] == "widget_scrollmanager" then
- if a2 == widgetEndX and a3 == widgetStartY then
- --Moins
- scrollScrollManager(-1, k)
- elseif a2 == widgetEndX and a3 == widgetEndY then
- --Plus
- scrollScrollManager(1, k)
- elseif a2 == widgetEndX and a3 >= widgetStartY and a3 <= widgetEndY then
- -- Scrollbar selected
- mouseDragUtility = k
- local scrollbarResult = scrollbarCompute(k, a1, a2, a3, widgets[k]["size"])
- if scrollbarResult then
- scrollScrollManagerTo(scrollbarResult, k)
- end
- end
- end
- end
- end
- end
- elseif event == "mouse_drag" then
- for k, v in pairs(widgets) do
- local widgetStartX, widgetStartY, widgetEndX, widgetEndY = getWidgetHitbox(k)
- if widgets[k]["enabled"] == true then
- if widgets[k]["type"] == "widget_numericslider" and mouseDragUtility == k then
- local oldValue = widgets[k]["value"]
- local nDragX = a2
- if nDragX < widgetStartX then
- nDragX = widgetStartX
- elseif nDragX > widgetEndX then
- nDragX = widgetEndX
- end
- local nNumericSliderLength = widgetEndX - widgetStartX
- local nClickPosition = nDragX - widgetStartX
- local nNewValue = nClickPosition * (widgets[k]["maxValue"] - widgets[k]["minValue"]) / nNumericSliderLength
- nNewValue = nNewValue + widgets[k]["minValue"]
- if nNewValue ~= widgets[k]["value"] then
- widgets[k]["value"] = nNewValue
- widgetUpdate(k)
- end
- if widgets[k]["value"] ~= oldValue then
- os.queueEvent("numericslider_value", k, widgets[k]["value"], a1, a2, a3)
- end
- elseif widgets[k]["type"] == "widget_list" and mouseDragUtility == k and a3 >= widgetStartY and a3 <= widgetEndY then
- -- Scrollbar selected
- local scrollbarResult = scrollbarCompute(k, a1, a2, a3, #widgets[k]["values"])
- if scrollbarResult then
- setProperty(k, "valuesShownMin", scrollbarResult)
- end
- elseif widgets[k]["type"] == "widget_scrollmanager" and mouseDragUtility == k and a3 >= widgetStartY and a3 <= widgetEndY then
- -- Scrollbar selected
- local scrollbarResult = scrollbarCompute(k, a1, a2, a3, widgets[k]["size"])
- if scrollbarResult then
- scrollScrollManagerTo(scrollbarResult, k)
- end
- end
- end
- end
- elseif event == "mouse_up" then
- -- Reset mouse_drag event filters
- mouseDragUtility = ""
- elseif event == "mouse_scroll" then
- for k, v in pairs(widgets) do
- local widgetStartX, widgetStartY, widgetEndX, widgetEndY = getWidgetHitbox(k)
- if widgets[k]["enabled"] == true then
- if widgets[k]["type"] == "widget_list" and a2 <= widgetEndX and a2 >= widgetStartX and a3 <= widgetEndY and a3 >= widgetStartY then
- if widgets[k]["valuesShownMin"] > 1 and a1 == -1 then
- setProperty(k, "valuesShownMin", widgets[k]["valuesShownMin"] - 1)
- elseif widgets[k]["valuesShownMax"] < #widgets[k]["values"] and a1 == 1 then
- setProperty(k, "valuesShownMin", widgets[k]["valuesShownMin"] + 1)
- end
- elseif widgets[k]["type"] == "widget_scrollmanager" and a2 <= widgetEndX and a2 >= widgetStartX and a3 <= widgetEndY and a3 >= widgetStartY then
- scrollScrollManager(a1, k)
- end
- end
- end
- end
- end
- end
- end
- function marqueeAnim()
- while bRun do
- if not bDialogRunning then
- for k, v in pairs(widgets) do
- if widgets[k]["enabled"] == true then
- if widgets[k]["type"] == "widget_progress_marquee" then
- if widgets[k]["maxGreen"] == widgets[k]["endX"] then
- widgets[k]["animDirection"] = "-"
- elseif widgets[k]["minGreen"] == widgets[k]["startX"] then
- widgets[k]["animDirection"] = "+"
- end
- if widgets[k]["animDirection"] == "+" then
- widgets[k]["minGreen"] = widgets[k]["minGreen"] + 1
- widgets[k]["maxGreen"] = widgets[k]["maxGreen"] + 1
- elseif widgets[k]["animDirection"] == "-" then
- widgets[k]["minGreen"] = widgets[k]["minGreen"] - 1
- widgets[k]["maxGreen"] = widgets[k]["maxGreen"] - 1
- end
- local oldColor = term.getBackgroundColor()
- local curX, curY = term.getCursorPos()
- paintutils.drawLine(widgets[k]["startX"], widgets[k]["startY"], widgets[k]["endX"], widgets[k]["startY"], colors.cyan)
- paintutils.drawLine(widgets[k]["minGreen"], widgets[k]["startY"], widgets[k]["maxGreen"], widgets[k]["startY"], colors.green)
- term.setBackgroundColor(oldColor)
- term.setCursorPos(curX, curY)
- end
- end
- end
- end
- sleep(0.05)
- end
- end
- function progressAnim()
- while bRun do
- local oldColor = term.getBackgroundColor()
- local curX, curY = term.getCursorPos()
- if not bDialogRunning then
- for k, v in pairs(widgets) do
- if widgets[k]["enabled"] == true then
- if widgets[k]["type"] == "widget_progress" and widgets[k]["value"] > 0 then
- if widgets[k]["anim_health"] == 1 then
- if widgets[k]["anim_pixel"] >= widgets[k]["value_width"] then
- widgets[k]["anim_pixel"] = widgets[k]["value_width"]
- paintutils.drawPixel(widgets[k]["anim_pixel"] - 1, widgets[k]["startY"], colors.blue)
- paintutils.drawPixel(widgets[k]["anim_pixel"], widgets[k]["startY"], colors.lightBlue)
- term.setBackgroundColor(oldColor)
- term.setCursorPos(curX, curY)
- sleep(0.01)
- paintutils.drawPixel(widgets[k]["anim_pixel"], widgets[k]["startY"], colors.blue)
- term.setBackgroundColor(oldColor)
- term.setCursorPos(curX, curY)
- widgets[k]["anim_health"] = 100
- widgets[k]["anim_pixel"] = widgets[k]["startX"]
- else
- paintutils.drawPixel(widgets[k]["startX"], widgets[k]["startY"], colors.blue)
- paintutils.drawPixel(widgets[k]["anim_pixel"], widgets[k]["startY"], colors.lightBlue)
- term.setBackgroundColor(oldColor)
- term.setCursorPos(curX, curY)
- if widgets[k]["anim_pixel"] > widgets[k]["startX"] then
- paintutils.drawPixel(widgets[k]["anim_pixel"] - 1, widgets[k]["startY"], colors.blue)
- term.setBackgroundColor(oldColor)
- term.setCursorPos(curX, curY)
- end
- widgets[k]["anim_pixel"] = widgets[k]["anim_pixel"] + 1
- end
- else
- widgets[k]["anim_health"] = widgets[k]["anim_health"] - 1
- end
- end
- end
- end
- end
- term.setBackgroundColor(oldColor)
- term.setCursorPos(curX, curY)
- sleep(0.01)
- end
- end
- function buttonAnim()
- while bRun do
- local event, param1 = os.pullEvent()
- if event == "button_anim" and bCanButtonAnim then
- for i = 1, 4 do
- setProperty(param1, "btnColor", term.getBackgroundColor())
- sleep(0.05)
- local oldButtonColor = widgets[param1]["oldBtnColor"]
- setProperty(param1, "btnColor", oldButtonColor)
- sleep(0.05)
- end
- end
- end
- end
- function listAnim()
- while bRun do
- local event, param1 = os.pullEvent()
- if event == "list_anim" then
- for i = 1, 4 do
- setProperty(param1, "selectedColor", colors.lightBlue)
- sleep(0.05)
- local oldSelectedColor = widgets[param1]["oldSelectedColor"]
- setProperty(param1, "selectedColor", oldSelectedColor)
- sleep(0.05)
- end
- end
- end
- end
Add Comment
Please, Sign In to add comment