mirror of
https://github.com/edubart/otclient.git
synced 2025-10-14 03:24:55 +02:00
BEAWARE all game functionality is disabled with this commit for a while
* rework client modules * hide main window when loading * remake top menu functions * rework modules autoload * improve path resolving for otml and lua * move core_widgets to core_lib * fix tooltip issues * split some styles * add bit32 lua library * fix assert issues * fix compilation on linux 32 systems * rework gcc compile options * renable and fix some warnings * remove unused constants * speedup sprite cache * move UIGame to lua (not funcional yet) * fix a lot of issues in x11 window * fix crash handler * add some warnings do uiwidget and much more...
This commit is contained in:
@@ -4,9 +4,9 @@ Module
|
||||
author: OTClient team
|
||||
website: https://github.com/edubart/otclient
|
||||
autoload: true
|
||||
autoload-antecedence: 10
|
||||
autoload-priority: 10
|
||||
|
||||
onLoad: |
|
||||
@onLoad: |
|
||||
dofile 'ext/table'
|
||||
dofile 'ext/string'
|
||||
dofile 'ext/os'
|
||||
@@ -17,9 +17,26 @@ Module
|
||||
dofile 'const'
|
||||
dofile 'util'
|
||||
dofile 'globals'
|
||||
dofile 'dispatcher'
|
||||
dofile 'effects'
|
||||
dofile 'settings'
|
||||
dofile 'keyboard'
|
||||
dofile 'mouse'
|
||||
|
||||
dofile 'ui/effects'
|
||||
dofile 'ui/radiogroup'
|
||||
dofile 'ui/tooltip'
|
||||
|
||||
dofile 'widgets/uiwidget'
|
||||
dofile 'widgets/uibutton'
|
||||
dofile 'widgets/uilabel'
|
||||
dofile 'widgets/uicheckbox'
|
||||
dofile 'widgets/uicombobox'
|
||||
dofile 'widgets/uispinbox'
|
||||
dofile 'widgets/uiprogressbar'
|
||||
dofile 'widgets/uitabbar'
|
||||
dofile 'widgets/uipopupmenu'
|
||||
dofile 'widgets/uiwindow'
|
||||
--dofile 'widgets/uiminiwindow'
|
||||
--dofile 'widgets/uiminiwindowcontainer'
|
||||
dofile 'widgets/uimessagebox'
|
||||
|
||||
|
||||
|
@@ -1,20 +0,0 @@
|
||||
function scheduleEvent(callback, delay)
|
||||
local event = g_dispatcher.scheduleEvent(callback, delay)
|
||||
|
||||
-- must hold a reference to the callback, otherwise it would be collected
|
||||
event._callback = callback
|
||||
return event
|
||||
end
|
||||
|
||||
function addEvent(callback, front)
|
||||
local event = g_dispatcher.addEvent(callback, front)
|
||||
-- must hold a reference to the callback, otherwise it would be collected
|
||||
event._callback = callback
|
||||
return event
|
||||
end
|
||||
|
||||
function removeEvent(event)
|
||||
if event then
|
||||
event:cancel()
|
||||
end
|
||||
end
|
@@ -1,57 +1,13 @@
|
||||
rootWidget = g_ui.getRootWidget()
|
||||
|
||||
function importStyle(otui)
|
||||
g_ui.importStyle(resolvepath(otui, 2))
|
||||
end
|
||||
importStyle = g_ui.importStyle
|
||||
importFont = g_fonts.importFont
|
||||
setDefaultFont = g_fonts.setDefaultFont
|
||||
|
||||
function importFont(otfont)
|
||||
g_fonts.importFont(resolvepath(otfont, 2))
|
||||
end
|
||||
loadUI = g_ui.loadUI
|
||||
|
||||
function setDefaultFont(font)
|
||||
g_fonts.setDefaultFont(font)
|
||||
end
|
||||
|
||||
function displayUI(arg1, options)
|
||||
local widget
|
||||
local parent
|
||||
if options then parent = options.parent end
|
||||
function displayUI(otui, parent)
|
||||
parent = parent or rootWidget
|
||||
|
||||
-- display otui files
|
||||
if type(arg1) == 'string' then
|
||||
local otuiFilePath = resolvepath(arg1, 2)
|
||||
widget = g_ui.loadUI(otuiFilePath, parent)
|
||||
-- display already loaded widgets
|
||||
else
|
||||
widget = arg1
|
||||
if parent:hasChild(widget) then
|
||||
widget:focus()
|
||||
widget:show()
|
||||
else
|
||||
parent:addChild(widget)
|
||||
widget:show()
|
||||
end
|
||||
end
|
||||
|
||||
-- apply display options
|
||||
if widget and options then
|
||||
for option,value in pairs(options) do
|
||||
if option == 'locked' and value then
|
||||
widget:lock()
|
||||
elseif option == 'visible' then
|
||||
widget:setVisible(value)
|
||||
elseif option == 'x' then
|
||||
widget:setX(value)
|
||||
elseif option == 'y' then
|
||||
widget:setY(value)
|
||||
end
|
||||
end
|
||||
end
|
||||
return widget
|
||||
end
|
||||
|
||||
function loadUI(otui, parent)
|
||||
local otuiFilePath = resolvepath(otui, 2)
|
||||
return g_ui.loadUI(otuiFilePath, parent)
|
||||
end
|
||||
@@ -65,7 +21,7 @@ function createWidget(style, parent)
|
||||
|
||||
local class = _G[className]
|
||||
if not class then
|
||||
error('could not find widget class ' .. class)
|
||||
error('could not find widget class ' .. className)
|
||||
return
|
||||
end
|
||||
|
||||
@@ -80,6 +36,28 @@ function createWidget(style, parent)
|
||||
return widget
|
||||
end
|
||||
|
||||
function scheduleEvent(callback, delay)
|
||||
local event = g_dispatcher.scheduleEvent(callback, delay)
|
||||
|
||||
-- must hold a reference to the callback, otherwise it would be collected
|
||||
event._callback = callback
|
||||
return event
|
||||
end
|
||||
|
||||
function addEvent(callback, front)
|
||||
local event = g_dispatcher.addEvent(callback, front)
|
||||
-- must hold a reference to the callback, otherwise it would be collected
|
||||
event._callback = callback
|
||||
return event
|
||||
end
|
||||
|
||||
function removeEvent(event)
|
||||
if event then
|
||||
event:cancel()
|
||||
event._callback = nil
|
||||
end
|
||||
end
|
||||
|
||||
function reloadModule(name)
|
||||
local module = g_modules.getModule(name)
|
||||
if module then
|
||||
|
@@ -7,3 +7,4 @@ end
|
||||
function Mouse.restoreCursor()
|
||||
g_window.restoreMouseCursor()
|
||||
end
|
||||
|
||||
|
@@ -32,7 +32,6 @@ function Settings.set(key, value)
|
||||
g_configs.set(key, convertSettingValue(value))
|
||||
end
|
||||
|
||||
|
||||
function Settings.setDefault(key, value)
|
||||
if Settings.exists(key) then return false end
|
||||
Settings.set(key, value)
|
||||
|
43
modules/core_lib/ui/radiogroup.lua
Normal file
43
modules/core_lib/ui/radiogroup.lua
Normal file
@@ -0,0 +1,43 @@
|
||||
RadioGroup = newclass()
|
||||
|
||||
function RadioGroup.create()
|
||||
local radiogroup = RadioGroup.internalCreate()
|
||||
radiogroup.widgets = {}
|
||||
return radiogroup
|
||||
end
|
||||
|
||||
function RadioGroup:destroy()
|
||||
while #self.widgets ~= 0 do
|
||||
self:removeWidget(self.widgets[1])
|
||||
end
|
||||
end
|
||||
|
||||
function RadioGroup:addWidget(widget)
|
||||
table.insert(self.widgets, widget)
|
||||
widget.onMousePress = function(widget) self:selectWidget(widget) end
|
||||
end
|
||||
|
||||
function RadioGroup:removeWidget(widget)
|
||||
if self.selectedWidget == widget then
|
||||
self:selectWidget(nil)
|
||||
end
|
||||
widget.onMousePress = nil
|
||||
table.removevalue(self.widgets, widget)
|
||||
end
|
||||
|
||||
function RadioGroup:selectWidget(selectedWidget)
|
||||
if selectedWidget == self.selectedWidget then return end
|
||||
|
||||
local previousSelectedWidget = self.selectedWidget
|
||||
self.selectedWidget = selectedWidget
|
||||
|
||||
if previousSelectedWidget then
|
||||
previousSelectedWidget:setChecked(false)
|
||||
end
|
||||
|
||||
if selectedWidget then
|
||||
selectedWidget:setChecked(true)
|
||||
end
|
||||
|
||||
signalcall(self.onSelectionChange, self, selectedWidget, previousSelectedWidget)
|
||||
end
|
94
modules/core_lib/ui/tooltip.lua
Normal file
94
modules/core_lib/ui/tooltip.lua
Normal file
@@ -0,0 +1,94 @@
|
||||
ToolTip = {}
|
||||
|
||||
-- private variables
|
||||
local toolTipLabel
|
||||
local currentHoveredWidget
|
||||
|
||||
-- private functions
|
||||
local function moveToolTip(tooltip)
|
||||
if not tooltip:isVisible() then return end
|
||||
|
||||
local pos = g_window.getMousePosition()
|
||||
pos.y = pos.y + 1
|
||||
local xdif = g_window.getSize().width - (pos.x + tooltip:getWidth())
|
||||
if xdif < 2 then
|
||||
pos.x = pos.x - tooltip:getWidth() - 3
|
||||
else
|
||||
pos.x = pos.x + 10
|
||||
end
|
||||
tooltip:setPosition(pos)
|
||||
end
|
||||
|
||||
local function onWidgetHoverChange(widget, hovered)
|
||||
if hovered then
|
||||
if widget.tooltip then
|
||||
ToolTip.display(widget.tooltip)
|
||||
currentHoveredWidget = widget
|
||||
end
|
||||
else
|
||||
if widget == currentHoveredWidget then
|
||||
ToolTip:hide()
|
||||
currentHoveredWidget = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function onWidgetStyleApply(widget, styleName, styleNode)
|
||||
if styleNode.tooltip then
|
||||
widget.tooltip = styleNode.tooltip
|
||||
end
|
||||
end
|
||||
|
||||
-- public functions
|
||||
function ToolTip.init()
|
||||
connect(UIWidget, { onStyleApply = onWidgetStyleApply,
|
||||
onHoverChange = onWidgetHoverChange})
|
||||
|
||||
addEvent(function()
|
||||
toolTipLabel = createWidget('Label', rootWidget)
|
||||
toolTipLabel:setId('toolTip')
|
||||
toolTipLabel:setBackgroundColor('#111111bb')
|
||||
toolTipLabel.onMouseMove = moveToolTip
|
||||
end)
|
||||
end
|
||||
|
||||
function ToolTip.terminate()
|
||||
disconnect(UIWidget, { onStyleApply = onWidgetStyleApply,
|
||||
onHoverChange = onWidgetHoverChange })
|
||||
|
||||
currentHoveredWidget = nil
|
||||
toolTipLabel:destroy()
|
||||
toolTipLabel = nil
|
||||
|
||||
ToolTip = nil
|
||||
end
|
||||
|
||||
function ToolTip.display(text)
|
||||
if text == nil then return end
|
||||
if not toolTipLabel then return end
|
||||
|
||||
toolTipLabel:setText(text)
|
||||
toolTipLabel:resizeToText()
|
||||
toolTipLabel:resize(toolTipLabel:getWidth() + 4, toolTipLabel:getHeight() + 4)
|
||||
toolTipLabel:show()
|
||||
toolTipLabel:raise()
|
||||
toolTipLabel:enable()
|
||||
moveToolTip(toolTipLabel)
|
||||
end
|
||||
|
||||
function ToolTip.hide()
|
||||
|
||||
toolTipLabel:hide()
|
||||
end
|
||||
|
||||
-- UIWidget extensions
|
||||
function UIWidget:setTooltip(text)
|
||||
self.tooltip = text
|
||||
end
|
||||
|
||||
function UIWidget:getTooltip()
|
||||
return self.tooltip
|
||||
end
|
||||
|
||||
ToolTip.init()
|
||||
connect(g_app, { onTerminate = ToolTip.terminate })
|
@@ -3,20 +3,15 @@ function print(...)
|
||||
for i,v in ipairs(arg) do
|
||||
msg = msg .. tostring(v) .. "\t"
|
||||
end
|
||||
Logger.log(LogInfo, msg)
|
||||
g_logger.log(LogInfo, msg)
|
||||
end
|
||||
|
||||
function fatal(msg)
|
||||
Logger.log(LogFatal, msg)
|
||||
g_logger.log(LogFatal, msg)
|
||||
end
|
||||
|
||||
function setonclose(func)
|
||||
g_app.onClose = func
|
||||
end
|
||||
|
||||
function exit()
|
||||
g_app.exit()
|
||||
end
|
||||
exit = g_app.exit
|
||||
quit = g_app.exit
|
||||
|
||||
function connect(object, signalsAndSlots, pushFront)
|
||||
for signal,slot in pairs(signalsAndSlots) do
|
||||
|
7
modules/core_lib/widgets/uibutton.lua
Normal file
7
modules/core_lib/widgets/uibutton.lua
Normal file
@@ -0,0 +1,7 @@
|
||||
UIButton = extends(UIWidget)
|
||||
|
||||
function UIButton.create()
|
||||
local button = UIButton.internalCreate()
|
||||
button:setFocusable(false)
|
||||
return button
|
||||
end
|
13
modules/core_lib/widgets/uicheckbox.lua
Normal file
13
modules/core_lib/widgets/uicheckbox.lua
Normal file
@@ -0,0 +1,13 @@
|
||||
UICheckBox = extends(UIWidget)
|
||||
|
||||
function UICheckBox.create()
|
||||
local checkbox = UICheckBox.internalCreate()
|
||||
checkbox:setFocusable(false)
|
||||
checkbox:setTextAlign(AlignLeft)
|
||||
return checkbox
|
||||
end
|
||||
|
||||
function UICheckBox:onMousePress(mousePos, mouseButton)
|
||||
self:setChecked(not self:isChecked())
|
||||
return true
|
||||
end
|
69
modules/core_lib/widgets/uicombobox.lua
Normal file
69
modules/core_lib/widgets/uicombobox.lua
Normal file
@@ -0,0 +1,69 @@
|
||||
UIComboBox = extends(UIWidget)
|
||||
|
||||
function UIComboBox.create()
|
||||
local combobox = UIComboBox.internalCreate()
|
||||
combobox.m_options = {}
|
||||
combobox.m_currentIndex = -1
|
||||
return combobox
|
||||
end
|
||||
|
||||
function UIComboBox:setCurrentOption(text)
|
||||
if not self.m_options then return end
|
||||
for i,v in ipairs(self.m_options) do
|
||||
if v.text == text and self.m_currentIndex ~= i then
|
||||
self.m_currentIndex = i
|
||||
self:setText(text)
|
||||
self:onOptionChange(text, v.data)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function UIComboBox:setCurrentIndex(index)
|
||||
if index >= 1 and index <= #self.m_options then
|
||||
local v = self.m_options[index]
|
||||
self.m_currentIndex = index
|
||||
self:setText(v.text)
|
||||
self:onOptionChange(v.text, v.data)
|
||||
end
|
||||
end
|
||||
|
||||
function UIComboBox:addOption(text, data)
|
||||
table.insert(self.m_options, { text = text, data = data })
|
||||
local index = #self.m_options
|
||||
if index == 1 then self:setCurrentOption(text) end
|
||||
return index
|
||||
end
|
||||
|
||||
function UIComboBox:onMousePress(mousePos, mouseButton)
|
||||
local menu = createWidget(self:getStyleName() .. 'PopupMenu', self)
|
||||
for i,v in ipairs(self.m_options) do
|
||||
menu:addOption(v.text, function() self:setCurrentOption(v.text) end)
|
||||
end
|
||||
menu:setWidth(self:getWidth())
|
||||
menu:display({ x = self:getX(), y = self:getY() + self:getHeight() })
|
||||
connect(menu, { onDestroy = function() self:setOn(false) end })
|
||||
self:setOn(true)
|
||||
return true
|
||||
end
|
||||
|
||||
function UIComboBox:onMouseWheel(mousePos, direction)
|
||||
if direction == MouseWheelUp and self.m_currentIndex > 1 then
|
||||
self:setCurrentIndex(self.m_currentIndex - 1)
|
||||
elseif direction == MouseWheelDown and self.m_currentIndex < #self.m_options then
|
||||
self:setCurrentIndex(self.m_currentIndex + 1)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function UIComboBox:onStyleApply(styleName, styleNode)
|
||||
if styleNode.options then
|
||||
for k,option in pairs(styleNode.options) do
|
||||
self:addOption(option)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function UIComboBox:onOptionChange(optionText, optionData)
|
||||
-- nothing todo
|
||||
end
|
9
modules/core_lib/widgets/uilabel.lua
Normal file
9
modules/core_lib/widgets/uilabel.lua
Normal file
@@ -0,0 +1,9 @@
|
||||
UILabel = extends(UIWidget)
|
||||
|
||||
function UILabel.create()
|
||||
local label = UILabel.internalCreate()
|
||||
label:setPhantom(true)
|
||||
label:setFocusable(false)
|
||||
label:setTextAlign(AlignLeft)
|
||||
return label
|
||||
end
|
65
modules/core_lib/widgets/uimessagebox.lua
Normal file
65
modules/core_lib/widgets/uimessagebox.lua
Normal file
@@ -0,0 +1,65 @@
|
||||
UIMessageBox = extends(UIWindow)
|
||||
|
||||
MessageBoxOk = 1
|
||||
MessageBoxCancel = 2
|
||||
|
||||
-- messagebox cannot be created from otui files
|
||||
UIMessageBox.create = nil
|
||||
|
||||
function UIMessageBox.display(title, message, flags)
|
||||
local messagebox = UIMessageBox.internalCreate()
|
||||
rootWidget:addChild(messagebox)
|
||||
|
||||
messagebox:setStyle('MessageBoxWindow')
|
||||
messagebox:setText(title)
|
||||
|
||||
local messageLabel = createWidget('MessageBoxLabel', messagebox)
|
||||
messageLabel:setText(message)
|
||||
messageLabel:resizeToText()
|
||||
|
||||
messagebox:setWidth(math.max(messageLabel:getWidth() + 48, messagebox:getWidth()))
|
||||
messagebox:setHeight(math.max(messageLabel:getHeight() + 64, messagebox:getHeight()))
|
||||
|
||||
-- setup messagebox first button
|
||||
local buttonRight = createWidget('MessageBoxRightButton', messagebox)
|
||||
|
||||
if flags == MessageBoxOk then
|
||||
buttonRight:setText('Ok')
|
||||
connect(buttonRight, { onClick = function(self) self:getParent():ok() end })
|
||||
connect(messagebox, { onEnter = function(self) self:ok() end })
|
||||
connect(messagebox, { onEscape = function(self) self:ok() end })
|
||||
elseif flags == MessageBoxCancel then
|
||||
buttonRight:setText('Cancel')
|
||||
connect(buttonRight, { onClick = function(self) self:getParent():cancel() end })
|
||||
connect(messagebox, { onEnter = function(self) self:cancel() end })
|
||||
connect(messagebox, { onEscape = function(self) self:cancel() end })
|
||||
end
|
||||
|
||||
messagebox:lock()
|
||||
|
||||
return messagebox
|
||||
end
|
||||
|
||||
function displayInfoBox(title, message)
|
||||
return UIMessageBox.display(title, message, MessageBoxOk)
|
||||
end
|
||||
|
||||
function displayErrorBox(title, message)
|
||||
return UIMessageBox.display(title, message, MessageBoxOk)
|
||||
end
|
||||
|
||||
function displayCancelBox(title, message)
|
||||
return UIMessageBox.display(title, message, MessageBoxCancel)
|
||||
end
|
||||
|
||||
function UIMessageBox:ok()
|
||||
signalcall(self.onOk, self)
|
||||
self.onOk = nil
|
||||
self:destroy()
|
||||
end
|
||||
|
||||
function UIMessageBox:cancel()
|
||||
signalcall(self.onCancel, self)
|
||||
self.onCancel = nil
|
||||
self:destroy()
|
||||
end
|
79
modules/core_lib/widgets/uipopupmenu.lua
Normal file
79
modules/core_lib/widgets/uipopupmenu.lua
Normal file
@@ -0,0 +1,79 @@
|
||||
UIPopupMenu = extends(UIWidget)
|
||||
|
||||
local currentMenu
|
||||
|
||||
function UIPopupMenu.create()
|
||||
local menu = UIPopupMenu.internalCreate()
|
||||
local layout = UIVerticalLayout.create(menu)
|
||||
layout:setFitChildren(true)
|
||||
menu:setLayout(layout)
|
||||
return menu
|
||||
end
|
||||
|
||||
function UIPopupMenu:display(pos)
|
||||
-- don't display if not options was added
|
||||
if self:getChildCount() == 0 then
|
||||
self:destroy()
|
||||
return
|
||||
end
|
||||
|
||||
if currentMenu then
|
||||
currentMenu:destroy()
|
||||
end
|
||||
|
||||
rootWidget:addChild(self)
|
||||
self:setPosition(pos)
|
||||
self:grabMouse()
|
||||
self:grabKeyboard()
|
||||
currentMenu = self
|
||||
end
|
||||
|
||||
function UIPopupMenu:onGeometryChange()
|
||||
self:bindRectToParent()
|
||||
end
|
||||
|
||||
function UIPopupMenu:addOption(optionName, optionCallback)
|
||||
local optionWidget = createWidget(self:getStyleName() .. 'Button', self)
|
||||
local lastOptionWidget = self:getLastChild()
|
||||
optionWidget.onClick = function(self)
|
||||
optionCallback()
|
||||
self:getParent():destroy()
|
||||
end
|
||||
optionWidget:setText(optionName)
|
||||
local width = optionWidget:getTextSize().width + optionWidget:getMarginLeft() + optionWidget:getMarginRight() + 6
|
||||
self:setWidth(math.max(self:getWidth(), width))
|
||||
end
|
||||
|
||||
function UIPopupMenu:addSeparator()
|
||||
createWidget(self:getStyleName() .. 'Separator', self)
|
||||
end
|
||||
|
||||
function UIPopupMenu:onDestroy()
|
||||
if currentMenu == self then
|
||||
currentMenu = nil
|
||||
end
|
||||
end
|
||||
|
||||
function UIPopupMenu:onMousePress(mousePos, mouseButton)
|
||||
-- clicks outside menu area destroys the menu
|
||||
if not self:containsPoint(mousePos) then
|
||||
self:destroy()
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function UIPopupMenu:onKeyPress(keyCode, keyboardModifiers)
|
||||
if keyCode == KeyEscape then
|
||||
self:destroy()
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- close all menus when the window is resized
|
||||
local function onRootGeometryUpdate()
|
||||
if currentMenu then
|
||||
currentMenu:destroy()
|
||||
end
|
||||
end
|
||||
connect(rootWidget, { onGeometryChange = onRootGeometryUpdate} )
|
31
modules/core_lib/widgets/uiprogressbar.lua
Normal file
31
modules/core_lib/widgets/uiprogressbar.lua
Normal file
@@ -0,0 +1,31 @@
|
||||
UIProgressBar = extends(UIWidget)
|
||||
|
||||
function UIProgressBar.create()
|
||||
local progressbar = UIProgressBar.internalCreate()
|
||||
progressbar:setFocusable(false)
|
||||
progressbar:setPhantom(true)
|
||||
progressbar.m_percent = 0
|
||||
progressbar:updateBackground()
|
||||
return progressbar
|
||||
end
|
||||
|
||||
function UIProgressBar:setPercent(percent)
|
||||
self.m_percent = math.max(math.min(percent, 100), 0)
|
||||
self:updateBackground()
|
||||
end
|
||||
|
||||
|
||||
function UIProgressBar:getPercent()
|
||||
return self.m_percent
|
||||
end
|
||||
|
||||
function UIProgressBar:updateBackground()
|
||||
local width = math.max((self.m_percent * self:getWidth())/100, 1)
|
||||
local height = self:getHeight()
|
||||
self:setBackgroundSize({width=width, height=height})
|
||||
end
|
||||
|
||||
|
||||
function UIProgressBar:onGeometryChange(oldRect, newRect)
|
||||
self:updateBackground()
|
||||
end
|
88
modules/core_lib/widgets/uispinbox.lua
Normal file
88
modules/core_lib/widgets/uispinbox.lua
Normal file
@@ -0,0 +1,88 @@
|
||||
UISpinBox = extends(UILineEdit)
|
||||
|
||||
function UISpinBox.create()
|
||||
local spinbox = UISpinBox.internalCreate()
|
||||
spinbox:setValidCharacters('0123456789')
|
||||
spinbox.m_minimum = 0
|
||||
spinbox.m_maximum = 0
|
||||
spinbox:setCurrentIndex(0)
|
||||
spinbox:setText("0")
|
||||
return spinbox
|
||||
end
|
||||
|
||||
function UISpinBox:setCurrentIndex(index)
|
||||
if index >= self.m_minimum and index <= self.m_maximum then
|
||||
if self:getText():len() > 0 then
|
||||
self:setText(index)
|
||||
end
|
||||
self.m_currentIndex = index
|
||||
self:onIndexChange(index)
|
||||
end
|
||||
end
|
||||
|
||||
function UISpinBox:setMinimum(minimum)
|
||||
if minimum > self.m_maximum then
|
||||
print("[UISpinBox:setMinimum]: minimum value cant be greater than maximum")
|
||||
return false
|
||||
end
|
||||
if self.m_currentIndex < minimum then
|
||||
self:setCurrentIndex(minimum)
|
||||
end
|
||||
self.m_minimum = minimum
|
||||
end
|
||||
|
||||
function UISpinBox:setMaximum(maximum)
|
||||
if maximum < self.m_minimum then
|
||||
print("[UISpinBox:setMaximum]: maximum value cant be lower than minimum")
|
||||
return false
|
||||
end
|
||||
if self.m_currentIndex > maximum then
|
||||
self:setCurrentIndex(maximum)
|
||||
end
|
||||
self.m_maximum = maximum
|
||||
end
|
||||
|
||||
function UISpinBox:getCurrentIndex()
|
||||
return self.m_currentIndex
|
||||
end
|
||||
|
||||
function UISpinBox:onMouseWheel(mousePos, direction)
|
||||
if direction == MouseWheelUp then
|
||||
self:setCurrentIndex(self.m_currentIndex + 1)
|
||||
elseif direction == MouseWheelDown then
|
||||
self:setCurrentIndex(self.m_currentIndex - 1)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function UISpinBox:onTextChange(text, oldText)
|
||||
|
||||
if text:len() == 0 then
|
||||
self:setCurrentIndex(self.m_minimum)
|
||||
return
|
||||
end
|
||||
|
||||
local number = tonumber(text)
|
||||
if not number or number > self.m_maximum or number < self.m_minimum then
|
||||
self:setText(oldText)
|
||||
return
|
||||
end
|
||||
|
||||
self:setCurrentIndex(number)
|
||||
end
|
||||
|
||||
function UISpinBox:onIndexChange(index)
|
||||
-- nothing todo
|
||||
end
|
||||
|
||||
function UISpinBox:onStyleApply(styleName, styleNode)
|
||||
-- tonumber converts to 0 if not valid
|
||||
if styleNode.maximum and tonumber(styleNode.maximum) then
|
||||
self:setMaximum(tonumber(styleNode.maximum))
|
||||
end
|
||||
|
||||
if styleNode.minimum and tonumber(styleNode.minimum) then
|
||||
self:setMinimum(tonumber(styleNode.minimum))
|
||||
end
|
||||
end
|
||||
|
124
modules/core_lib/widgets/uitabbar.lua
Normal file
124
modules/core_lib/widgets/uitabbar.lua
Normal file
@@ -0,0 +1,124 @@
|
||||
UITabBar = extends(UIWidget)
|
||||
|
||||
-- private functions
|
||||
local function onTabClick(tab)
|
||||
tab.tabBar:selectTab(tab)
|
||||
end
|
||||
|
||||
local function tabBlink(tab)
|
||||
if not tab.blinking then return end
|
||||
tab:setOn(not tab:isOn())
|
||||
scheduleEvent(function() tabBlink(tab) end, 500)
|
||||
end
|
||||
|
||||
-- public functions
|
||||
function UITabBar.create()
|
||||
local tabbar = UITabBar.internalCreate()
|
||||
tabbar:setFocusable(false)
|
||||
tabbar.tabs = {}
|
||||
return tabbar
|
||||
end
|
||||
|
||||
function UITabBar:setContentWidget(widget)
|
||||
self.contentWidget = widget
|
||||
if #self.tabs > 0 then
|
||||
self.contentWidget:addChild(self.tabs[1].tabPanel)
|
||||
end
|
||||
end
|
||||
|
||||
function UITabBar:addTab(text, panel)
|
||||
if panel == nil then
|
||||
panel = createWidget(self:getStyleName() .. 'Panel')
|
||||
end
|
||||
|
||||
local tab = createWidget(self:getStyleName() .. 'Button', self)
|
||||
tab.tabPanel = panel
|
||||
tab.tabBar = self
|
||||
tab:setText(text)
|
||||
tab:setWidth(tab:getTextSize().width + tab:getPaddingLeft() + tab:getPaddingRight())
|
||||
connect(tab, { onClick = onTabClick })
|
||||
|
||||
table.insert(self.tabs, tab)
|
||||
if #self.tabs == 1 then
|
||||
self:selectTab(tab)
|
||||
end
|
||||
|
||||
return tab
|
||||
end
|
||||
|
||||
function UITabBar:removeTab(tab)
|
||||
local index = table.find(self.tabs, tab)
|
||||
if index == nil then return end
|
||||
if self.currentTab == tab then
|
||||
self:selectPrevTab()
|
||||
end
|
||||
table.remove(self.tabs, index)
|
||||
tab:destroy()
|
||||
end
|
||||
|
||||
function UITabBar:getTab(text)
|
||||
for k,tab in pairs(self.tabs) do
|
||||
if tab:getText():lower() == text:lower() then
|
||||
return tab
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function UITabBar:selectTab(tab)
|
||||
if self.currentTab == tab then return end
|
||||
if self.contentWidget then
|
||||
local selectedWidget = self.contentWidget:getFirstChild()
|
||||
if selectedWidget then
|
||||
self.contentWidget:removeChild(selectedWidget)
|
||||
end
|
||||
self.contentWidget:addChild(tab.tabPanel)
|
||||
tab.tabPanel:fill('parent')
|
||||
end
|
||||
|
||||
if self.currentTab then
|
||||
self.currentTab:setChecked(false)
|
||||
end
|
||||
signalcall(self.onTabChange, self, tab)
|
||||
self.currentTab = tab
|
||||
tab:setChecked(true)
|
||||
tab:setOn(false)
|
||||
tab.blinking = false
|
||||
end
|
||||
|
||||
function UITabBar:selectNextTab()
|
||||
if self.currentTab == nil then return end
|
||||
local index = table.find(self.tabs, self.currentTab)
|
||||
if index == nil then return end
|
||||
local nextTab = self.tabs[index + 1] or self.tabs[1]
|
||||
if not nextTab then return end
|
||||
self:selectTab(nextTab)
|
||||
end
|
||||
|
||||
function UITabBar:selectPrevTab()
|
||||
if self.currentTab == nil then return end
|
||||
local index = table.find(self.tabs, self.currentTab)
|
||||
if index == nil then return end
|
||||
local prevTab = self.tabs[index - 1] or self.tabs[#self.tabs]
|
||||
if not prevTab then return end
|
||||
self:selectTab(prevTab)
|
||||
end
|
||||
|
||||
function UITabBar:blinkTab(tab)
|
||||
if tab:isChecked() or tab.blinking then return end
|
||||
tab.blinking = true
|
||||
tabBlink(tab)
|
||||
end
|
||||
|
||||
function UITabBar:getTabPanel(tab)
|
||||
return tab.tabPanel
|
||||
end
|
||||
|
||||
function UITabBar:getCurrentTabPanel()
|
||||
if self.currentTab then
|
||||
return self.currentTab.tabPanel
|
||||
end
|
||||
end
|
||||
|
||||
function UITabBar:getCurrentTab()
|
||||
return self.currentTab
|
||||
end
|
19
modules/core_lib/widgets/uiwidget.lua
Normal file
19
modules/core_lib/widgets/uiwidget.lua
Normal file
@@ -0,0 +1,19 @@
|
||||
function UIWidget:setMargin(...)
|
||||
local params = {...}
|
||||
if #params == 1 then
|
||||
self:setMarginTop(params[1])
|
||||
self:setMarginRight(params[1])
|
||||
self:setMarginBottom(params[1])
|
||||
self:setMarginLeft(params[1])
|
||||
elseif #params == 2 then
|
||||
self:setMarginTop(params[1])
|
||||
self:setMarginRight(params[2])
|
||||
self:setMarginBottom(params[1])
|
||||
self:setMarginLeft(params[2])
|
||||
elseif #params == 4 then
|
||||
self:setMarginTop(params[1])
|
||||
self:setMarginRight(params[2])
|
||||
self:setMarginBottom(params[3])
|
||||
self:setMarginLeft(params[4])
|
||||
end
|
||||
end
|
38
modules/core_lib/widgets/uiwindow.lua
Normal file
38
modules/core_lib/widgets/uiwindow.lua
Normal file
@@ -0,0 +1,38 @@
|
||||
UIWindow = extends(UIWidget)
|
||||
|
||||
function UIWindow.create()
|
||||
local window = UIWindow.internalCreate()
|
||||
window:setTextAlign(AlignTopCenter)
|
||||
window:setDragable(true)
|
||||
return window
|
||||
end
|
||||
|
||||
function UIWindow:onKeyDown(keyCode, keyboardModifiers)
|
||||
if keyboardModifiers == KeyboardNoModifier then
|
||||
if keyCode == KeyEnter then
|
||||
signalcall(self.onEnter, self)
|
||||
elseif keyCode == KeyEscape then
|
||||
signalcall(self.onEscape, self)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function UIWindow:onFocusChange(focused)
|
||||
if focused then self:raise() end
|
||||
end
|
||||
|
||||
function UIWindow:onDragEnter(mousePos)
|
||||
self:breakAnchors()
|
||||
self.movingReference = { x = mousePos.x - self:getX(), y = mousePos.y - self:getY() }
|
||||
return true
|
||||
end
|
||||
|
||||
function UIWindow:onDragLeave(droppedWidget, mousePos)
|
||||
-- TODO: auto detect and reconnect anchors
|
||||
end
|
||||
|
||||
function UIWindow:onDragMove(mousePos, mouseMoved)
|
||||
local pos = { x = mousePos.x - self.movingReference.x, y = mousePos.y - self.movingReference.y }
|
||||
self:setPosition(pos)
|
||||
self:bindRectToParent()
|
||||
end
|
Reference in New Issue
Block a user