diff --git a/data/styles/10-comboboxes.otui b/data/styles/10-comboboxes.otui index a2966f7d..a4ad9daf 100644 --- a/data/styles/10-comboboxes.otui +++ b/data/styles/10-comboboxes.otui @@ -1,3 +1,24 @@ +ComboBoxPopupScrollMenuButton < UIButton + height: 23 + font: verdana-11px-antialised + text-align: left + text-offset: 4 0 + color: #dfdfdf + background-color: alpha + margin: 1 + + $hover !disabled: + color: #dfdfdf + background-color: #355d89 + + $disabled: + color: #dfdfdf88 + +ComboBoxPopupScrollMenu < UIPopupScrollMenu + image-source: /images/ui/combobox_square + image-clip: 0 69 91 23 + image-border: 1 + ComboBoxPopupMenuButton < UIButton height: 23 font: verdana-11px-antialised @@ -40,6 +61,26 @@ ComboBox < UIComboBox color: #dfdfdf88 opacity: 0.8 +ComboBoxRoundedPopupScrollMenuButton < UIButton + height: 23 + font: verdana-11px-antialised + text-align: left + text-offset: 4 0 + color: #dfdfdf + background-color: alpha + + $hover !disabled: + color: #ffffff + background-color: #355d89 + + $disabled: + color: #dfdfdf88 + +ComboBoxRoundedPopupScrollMenu < UIPopupScrollMenu + image-source: /images/ui/combobox_rounded + image-clip: 0 69 91 23 + image-border: 3 + ComboBoxRoundedPopupMenuButton < UIButton height: 23 font: verdana-11px-antialised diff --git a/data/styles/20-popupmenus.otui b/data/styles/20-popupmenus.otui index 15aa0473..d7b71fc4 100644 --- a/data/styles/20-popupmenus.otui +++ b/data/styles/20-popupmenus.otui @@ -39,3 +39,45 @@ PopupMenu < UIPopupMenu image-source: /images/ui/menubox image-border: 3 padding: 3 + +PopupScrollMenuButton < UIButton + height: 18 + size: 0 21 + text-offset: 4 0 + text-align: left + font: verdana-11px-antialised + + color: #aaaaaa + background-color: alpha + + $hover !disabled: + color: #ffffff + background-color: #ffffff44 + image-clip: 0 40 20 20 + + $disabled: + color: #555555 + +PopupScrollMenuShortcutLabel < Label + font: verdana-11px-antialised + text-align: right + anchors.fill: parent + margin-right: 2 + margin-left: 5 + +PopupScrollMenuSeparator < UIWidget + margin-left: 2 + margin-right: 2 + margin-bottom: 1 + image-source: /images/ui/menubox + image-border-left: 1 + image-border-right: 1 + image-clip: 0 0 32 2 + height: 2 + phantom: true + +PopupScrollMenu < UIPopupScrollMenu + width: 50 + image-source: /images/ui/menubox + image-border: 3 + padding: 3 diff --git a/modules/client_entergame/entergame.otui b/modules/client_entergame/entergame.otui index 0b97526f..52c60e01 100644 --- a/modules/client_entergame/entergame.otui +++ b/modules/client_entergame/entergame.otui @@ -92,6 +92,9 @@ EnterGameWindow margin-top: 2 margin-right: 3 width: 90 + menu-scroll: true + menu-height: 125 + menu-scroll-step: 25 MenuLabel id: portLabel diff --git a/modules/corelib/ui/uicombobox.lua b/modules/corelib/ui/uicombobox.lua index 9f5f830f..47154e0b 100644 --- a/modules/corelib/ui/uicombobox.lua +++ b/modules/corelib/ui/uicombobox.lua @@ -7,6 +7,9 @@ function UIComboBox.create() combobox.options = {} combobox.currentIndex = -1 combobox.mouseScroll = true + combobox.menuScroll = false + combobox.menuHeight = 100 + combobox.menuScrollStep = 0 return combobox end @@ -86,7 +89,16 @@ function UIComboBox:removeOption(text) end function UIComboBox:onMousePress(mousePos, mouseButton) - local menu = g_ui.createWidget(self:getStyleName() .. 'PopupMenu') + local menu + if self.menuScroll then + menu = g_ui.createWidget(self:getStyleName() .. 'PopupScrollMenu') + menu:setHeight(self.menuHeight) + if self.menuScrollStep > 0 then + menu:setScrollbarStep(self.menuScrollStep) + end + else + menu = g_ui.createWidget(self:getStyleName() .. 'PopupMenu') + end menu:setId(self:getId() .. 'PopupMenu') for i,v in ipairs(self.options) do menu:addOption(v.text, function() self:setCurrentOption(v.text) end) @@ -129,6 +141,12 @@ function UIComboBox:onStyleApply(styleName, styleNode) for name,value in pairs(styleNode) do if name == 'mouse-scroll' then self.mouseScroll = value + elseif name == 'menu-scroll' then + self.menuScroll = value + elseif name == 'menu-height' then + self.menuHeight = value + elseif name == 'menu-scroll-step' then + self.menuScrollStep = value end end end diff --git a/modules/corelib/ui/uipopupmenu.lua b/modules/corelib/ui/uipopupmenu.lua index 57f04bc1..79907023 100644 --- a/modules/corelib/ui/uipopupmenu.lua +++ b/modules/corelib/ui/uipopupmenu.lua @@ -56,9 +56,8 @@ end function UIPopupMenu:addOption(optionName, optionCallback, shortcut) local optionWidget = g_ui.createWidget(self:getStyleName() .. 'Button', self) - local lastOptionWidget = self:getLastChild() - optionWidget.onClick = function(self) - self:getParent():destroy() + optionWidget.onClick = function(widget) + self:destroy() optionCallback() end optionWidget:setText(optionName) diff --git a/modules/corelib/ui/uipopupscrollmenu.lua b/modules/corelib/ui/uipopupscrollmenu.lua new file mode 100644 index 00000000..405054fd --- /dev/null +++ b/modules/corelib/ui/uipopupscrollmenu.lua @@ -0,0 +1,129 @@ +-- @docclass +UIPopupScrollMenu = extends(UIWidget, "UIPopupScrollMenu") + +local currentMenu + +function UIPopupScrollMenu.create() + local menu = UIPopupScrollMenu.internalCreate() + + local scrollArea = g_ui.createWidget('UIScrollArea', menu) + scrollArea:setLayout(UIVerticalLayout.create(menu)) + scrollArea:setId('scrollArea') + + local scrollBar = g_ui.createWidget('VerticalScrollBar', menu) + scrollBar:setId('scrollBar') + scrollBar.pixelsScroll = false + + scrollBar:addAnchor(AnchorRight, 'parent', AnchorRight) + scrollBar:addAnchor(AnchorTop, 'parent', AnchorTop) + scrollBar:addAnchor(AnchorBottom, 'parent', AnchorBottom) + + scrollArea:addAnchor(AnchorLeft, 'parent', AnchorLeft) + scrollArea:addAnchor(AnchorTop, 'parent', AnchorTop) + scrollArea:addAnchor(AnchorBottom, 'parent', AnchorBottom) + scrollArea:addAnchor(AnchorRight, 'next', AnchorLeft) + scrollArea:setVerticalScrollBar(scrollBar) + + menu.scrollArea = scrollArea + menu.scrollBar = scrollBar + return menu +end + +function UIPopupScrollMenu:setScrollbarStep(step) + self.scrollBar:setStep(step) +end + +function UIPopupScrollMenu:display(pos) + -- don't display if not options was added + if self.scrollArea:getChildCount() == 0 then + self:destroy() + return + end + + if g_ui.isMouseGrabbed() then + self:destroy() + return + end + + if currentMenu then + currentMenu:destroy() + end + + if pos == nil then + pos = g_window.getMousePosition() + end + + rootWidget:addChild(self) + self:setPosition(pos) + self:grabMouse() + currentMenu = self +end + +function UIPopupScrollMenu:onGeometryChange(oldRect, newRect) + local parent = self:getParent() + if not parent then return end + local ymax = parent:getY() + parent:getHeight() + local xmax = parent:getX() + parent:getWidth() + if newRect.y + newRect.height > ymax then + local newy = newRect.y - newRect.height + if newy > 0 and newy + newRect.height < ymax then self:setY(newy) end + end + if newRect.x + newRect.width > xmax then + local newx = newRect.x - newRect.width + if newx > 0 and newx + newRect.width < xmax then self:setX(newx) end + end + self:bindRectToParent() +end + +function UIPopupScrollMenu:addOption(optionName, optionCallback, shortcut) + local optionWidget = g_ui.createWidget(self:getStyleName() .. 'Button', self.scrollArea) + optionWidget.onClick = function(widget) + self:destroy() + optionCallback() + end + optionWidget:setText(optionName) + local width = optionWidget:getTextSize().width + optionWidget:getMarginLeft() + optionWidget:getMarginRight() + 15 + + if shortcut then + local shortcutLabel = g_ui.createWidget(self:getStyleName() .. 'ShortcutLabel', optionWidget) + shortcutLabel:setText(shortcut) + width = width + shortcutLabel:getTextSize().width + shortcutLabel:getMarginLeft() + shortcutLabel:getMarginRight() + end + + self:setWidth(math.max(self:getWidth(), width)) +end + +function UIPopupScrollMenu:addSeparator() + g_ui.createWidget(self:getStyleName() .. 'Separator', self.scrollArea) +end + +function UIPopupScrollMenu:onDestroy() + if currentMenu == self then + currentMenu = nil + end + self:ungrabMouse() +end + +function UIPopupScrollMenu:onMousePress(mousePos, mouseButton) + -- clicks outside menu area destroys the menu + if not self:containsPoint(mousePos) then + self:destroy() + end + return true +end + +function UIPopupScrollMenu: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} )