require "ISUI/ISPanelJoypad" require "ISUI/ISButton" require "ISUI/ISMouseDrag" require "TimedActions/ISTimedActionQueue" require "TimedActions/ISEatFoodAction" ISScrollingListBox = ISPanelJoypad:derive("ISScrollingListBox"); ISScrollingListBox.joypadListIndex = 1; local FONT_HGT_SMALL = getTextManager():getFontHeight(UIFont.Small) -- -- Created by IntelliJ IDEA. -- User: LEMMY -- Date: 10/10/12 -- Time: 03:48 -- To change this template use File | Settings | File Templates. -- -- --************************************************************************-- --** ISInventoryPane:initialise --** --************************************************************************-- function ISScrollingListBox:initialise() ISPanelJoypad.initialise(self); end function ISScrollingListBox:setJoypadFocused(focused, joypadData) if focused then joypadData.focus = self; updateJoypadFocus(joypadData); if self.selected == -1 then self.selected = 1; if self.resetSelectionOnChangeFocus then if self.items[self.selectedBeforeReset] then self.selected = self.selectedBeforeReset end self.selectedBeforeReset = nil end if self.onmousedown and self.items[self.selected] then self.onmousedown(self.target, self.items[self.selected].item); end end end self.joypadFocused = focused; end function ISScrollingListBox:onJoypadDirRight(joypadData) if self.joypadParent then self.joypadParent:onJoypadDirRight(joypadData); end end function ISScrollingListBox:onJoypadDirLeft(joypadData) if self.joypadParent then self.joypadParent:onJoypadDirLeft(joypadData); end end --************************************************************************-- --** ISPanel:instantiate --** --************************************************************************-- function ISScrollingListBox:instantiate() --self:initialise(); self.javaObject = UIElement.new(self); self.javaObject:setX(self.x); self.javaObject:setY(self.y); self.javaObject:setHeight(self.height); self.javaObject:setWidth(self.width); self.javaObject:setAnchorLeft(self.anchorLeft); self.javaObject:setAnchorRight(self.anchorRight); self.javaObject:setAnchorTop(self.anchorTop); self.javaObject:setAnchorBottom(self.anchorBottom); self:addScrollBars(); end function ISScrollingListBox:rowAt(x, y) local y0 = 0 for i,v in ipairs(self.items) do if not v.height then v.height = self.itemheight end -- compatibililty if y >= y0 and y < y0 + v.height then return i end y0 = y0 + v.height end return -1 end function ISScrollingListBox:topOfItem(index) local y = 0 for k,v in ipairs(self.items) do if k == index then return y end y = y + v.height end return -1 end function ISScrollingListBox:prevVisibleIndex(index) if index <= 1 then return -1 end for i=index-1,1,-1 do local item = self.items[i] if item and item.height and item.height > 0 then return i end end return -1 end function ISScrollingListBox:nextVisibleItem(index) if index >= #self.items then return -1 end for i=index+1,#self.items do if self.items[i] and self.items[i].height and self.items[i].height > 0 then return i end end return -1 end ISScrollingListBox.nextVisibleIndex = ISScrollingListBox.nextVisibleItem function ISScrollingListBox:isMouseOverScrollBar() return self:isVScrollBarVisible() and self.vscroll:isMouseOver() end function ISScrollingListBox:onMouseMove(dx, dy) if self:isMouseOverScrollBar() then return end self.mouseoverselected = self:rowAt(self:getMouseX(), self:getMouseY()) end function ISScrollingListBox:onMouseMoveOutside(x, y) self.mouseoverselected = -1; end function ISScrollingListBox:onMouseUpOutside(x, y) if self.vscroll then self.vscroll.scrolling = false; end end function ISScrollingListBox:onMouseUp(x, y) if self.vscroll then self.vscroll.scrolling = false; end end function ISScrollingListBox:addItem(name, item) local i = {} i.text=name; i.item=item; i.tooltip = nil; i.itemindex = self.count + 1; i.height = self.itemheight table.insert(self.items, i); self.count = self.count + 1; self:setScrollHeight(self:getScrollHeight()+i.height); return i; end function ISScrollingListBox:insertItem(index, name, item) local i = {} i.text = name i.item = item i.tooltip = nil i.height = self.itemheight if #self.items == 0 or index > #self.items then i.itemindex = 1 table.insert(self.items, i) elseif index < 1 then i.itemindex = 1 table.insert(self.items, 1, i) else i.itemindex = index table.insert(self.items, index, i) end self.count = self.count + 1 self:setScrollHeight(self:getScrollHeight() + i.height) return i end function ISScrollingListBox:removeItem(itemText) for i,v in ipairs(self.items) do if v.text == itemText then table.remove(self.items, i); self.count = self.count - 1; if not v.height then v.height = self.itemheight end -- compatibililty self:setScrollHeight(self:getScrollHeight()-v.height); if self.selected > self.count then self.selected = self.count end return v; end end return nil; end function ISScrollingListBox:removeItemByIndex(itemIndex) if itemIndex >= 1 and itemIndex <= #self.items then local item = self.items[itemIndex] table.remove(self.items, itemIndex) self.count = self.count - 1 if not item.height then item.height = self.itemheight end -- compatibililty self:setScrollHeight(self:getScrollHeight() - item.height) if self.selected > self.count then self.selected = self.count end return item end return nil end function ISScrollingListBox:removeFirst() if self.count == 0 then return end local item = self.items[1] table.remove(self.items, 0); self.count = self.count - 1; if not item.height then item.height = self.itemheight end -- compatibililty self:setScrollHeight(self:getScrollHeight()-item.height); end function ISScrollingListBox:size() return self.count; end function ISScrollingListBox:setOnMouseDownFunction(target, onmousedown) self.onmousedown = onmousedown; self.target = target; end function ISScrollingListBox:setOnMouseDoubleClick(target, onmousedblclick) self.onmousedblclick = onmousedblclick; self.target = target; end function ISScrollingListBox:doDrawItem(y, item, alt) if not item.height then item.height = self.itemheight end -- compatibililty if self.selected == item.index then self:drawRect(0, (y), self:getWidth(), item.height-1, 0.3, 0.7, 0.35, 0.15); end self:drawRectBorder(0, (y), self:getWidth(), item.height, 0.5, self.borderColor.r, self.borderColor.g, self.borderColor.b); local itemPadY = self.itemPadY or (item.height - self.fontHgt) / 2 self:drawText(item.text, 15, (y)+itemPadY, 0.9, 0.9, 0.9, 0.9, self.font); y = y + item.height; return y; end function ISScrollingListBox:clear() self.items = {} self.selected = 1; self.itemheightoverride = {} self.count = 0; end function ISScrollingListBox:onMouseWheel(del) local yScroll = self.smoothScrollTargetY or self:getYScroll() local topRow = self:rowAt(0, -yScroll) if self.items[topRow] then if not self.smoothScrollTargetY then self.smoothScrollY = self:getYScroll() end local y = self:topOfItem(topRow) if del < 0 then if yScroll == -y and topRow > 1 then local prev = self:prevVisibleIndex(topRow) y = self:topOfItem(prev) end self.smoothScrollTargetY = -y; else self.smoothScrollTargetY = -(y + self.items[topRow].height); end else self:setYScroll(self:getYScroll() - (del*18)); end return true; end function ISScrollingListBox:scrollToSelected() end function ISScrollingListBox.sortByName(a, b) return not string.sort(a.text, b.text); end function ISScrollingListBox:sort() table.sort(self.items, ISScrollingListBox.sortByName); for i,item in ipairs(self.items) do item.itemindex = i; end end function ISScrollingListBox:updateTooltip() local row = -1 local lx = getMouseX() - self:getAbsoluteX() local ly = getMouseY() - self:getAbsoluteY() local sbarWid = 0 if self.vscroll and self.vscroll:getHeight() < self:getScrollHeight() then sbarWid = self.vscroll:getWidth() end if lx >= 0 and lx < self.width - sbarWid and ly >= 0 and ly < self.height then row = self:rowAt(self:getMouseX(), self:getMouseY()) -- Hack - don't show tooltip if another window is in front local root = self.parent or self while root.parent do root = root.parent end local uis = UIManager.getUI() for i=1,uis:size() do local ui = uis:get(i-1) if ui:isMouseOver() and (not self.tooltipUI or ui ~= self.tooltipUI.javaObject) and ui ~= root.javaObject then row = -1 break end end end if self.items[row] and self.items[row].tooltip then local text = self.items[row].tooltip if not self.tooltipUI then self.tooltipUI = ISToolTip:new() self.tooltipUI:setOwner(self) self.tooltipUI:setVisible(false) self.tooltipUI:setAlwaysOnTop(true) self.tooltipUI.maxLineWidth = 1000 -- don't wrap the lines end if not self.tooltipUI:getIsVisible() then self.tooltipUI:addToUIManager() self.tooltipUI:setVisible(true) end self.tooltipUI.description = text self.tooltipUI:setX(self:getMouseX() + 23) self.tooltipUI:setY(self:getMouseY() + 23) else if self.tooltipUI and self.tooltipUI:getIsVisible() then self.tooltipUI:setVisible(false) self.tooltipUI:removeFromUIManager() end end end function ISScrollingListBox:updateSmoothScrolling() if not self.smoothScrollTargetY or #self.items == 0 then return end local dy = self.smoothScrollTargetY - self.smoothScrollY local maxYScroll = self:getScrollHeight() - self:getHeight() local frameRateFrac = UIManager.getMillisSinceLastRender() / 33.3 local itemHeightFrac = 160 / (self:getScrollHeight() / #self.items) local targetY = self.smoothScrollY + dy * math.min(0.5, 0.25 * frameRateFrac * itemHeightFrac) if frameRateFrac > 1 then targetY = self.smoothScrollY + dy * math.min(1.0, math.min(0.5, 0.25 * frameRateFrac * itemHeightFrac) * frameRateFrac) end if targetY > 0 then targetY = 0 end if targetY < -maxYScroll then targetY = -maxYScroll end if math.abs(targetY - self.smoothScrollY) > 0.1 then self:setYScroll(targetY) self.smoothScrollY = targetY else self:setYScroll(self.smoothScrollTargetY) self.smoothScrollTargetY = nil self.smoothScrollY = nil end end function ISScrollingListBox:prerender() if self.items == nil then return; end local stencilX = 0 local stencilY = 0 local stencilX2 = self.width local stencilY2 = self.height self:drawRect(0, -self:getYScroll(), self.width, self.height, self.backgroundColor.a, self.backgroundColor.r, self.backgroundColor.g, self.backgroundColor.b); if self.drawBorder then self:drawRectBorder(0, -self:getYScroll(), self.width, self.height, self.borderColor.a, self.borderColor.r, self.borderColor.g, self.borderColor.b) stencilX = 1 stencilY = 1 stencilX2 = self.width - 1 stencilY2 = self.height - 1 end if self:isVScrollBarVisible() then stencilX2 = self.vscroll.x + 3 -- +3 because the scrollbar texture is narrower than the scrollbar width end -- This is to handle this listbox being inside a scrolling parent. if self.parent and self.parent:getScrollChildren() then stencilX = self.javaObject:clampToParentX(self:getAbsoluteX() + stencilX) - self:getAbsoluteX() stencilX2 = self.javaObject:clampToParentX(self:getAbsoluteX() + stencilX2) - self:getAbsoluteX() stencilY = self.javaObject:clampToParentY(self:getAbsoluteY() + stencilY) - self:getAbsoluteY() stencilY2 = self.javaObject:clampToParentY(self:getAbsoluteY() + stencilY2) - self:getAbsoluteY() end self:setStencilRect(stencilX, stencilY, stencilX2 - stencilX, stencilY2 - stencilY) local y = 0; local alt = false; -- if self.selected ~= -1 and self.selected < 1 then -- self.selected = 1 if self.selected ~= -1 and self.selected > #self.items then self.selected = #self.items end local altBg = self.altBgColor self.listHeight = 0; local i = 1; for k, v in ipairs(self.items) do if not v.height then v.height = self.itemheight end -- compatibililty if alt and altBg then self:drawRect(0, y, self:getWidth(), v.height-1, altBg.r, altBg.g, altBg.b, altBg.a); else end v.index = i; local y2 = self:doDrawItem(y, v, alt); self.listHeight = y2; v.height = y2 - y y = y2 alt = not alt; i = i + 1; end self:setScrollHeight((y)); self:clearStencilRect(); if self.doRepaintStencil then self:repaintStencilRect(stencilX, stencilY, stencilX2 - stencilX, stencilY2 - stencilY) end local mouseY = self:getMouseY() self:updateSmoothScrolling() if mouseY ~= self:getMouseY() and self:isMouseOver() then self:onMouseMove(0, self:getMouseY() - mouseY) end self:updateTooltip() if #self.columns > 0 then -- print(self:getScrollHeight()) self:drawRectBorderStatic(0, 0 - self.itemheight, self.width, self.itemheight - 1, 1, self.borderColor.r, self.borderColor.g, self.borderColor.b); self:drawRectStatic(0, 0 - self.itemheight - 1, self.width, self.itemheight-2,self.listHeaderColor.a,self.listHeaderColor.r, self.listHeaderColor.g, self.listHeaderColor.b); local dyText = (self.itemheight - FONT_HGT_SMALL) / 2 for i,v in ipairs(self.columns) do self:drawRectStatic(v.size, 0 - self.itemheight, 1, self.itemheight + math.min(self.height, self.itemheight * #self.items - 1), 1, self.borderColor.r, self.borderColor.g, self.borderColor.b); if v.name then self:drawText(v.name, v.size + 10, 0 - self.itemheight - 1 + dyText - self:getYScroll(), 1,1,1,1,UIFont.Small); end end end end function ISScrollingListBox:onMouseDoubleClick(x, y) if self.onmousedblclick and self.items[self.selected] ~= nil then self.onmousedblclick(self.target, self.items[self.selected].item); end end function ISScrollingListBox:onMouseDown(x, y) if #self.items == 0 then return end local row = self:rowAt(x, y) if row > #self.items then row = #self.items; end if row < 1 then row = 1; end -- RJ: If you select the same item it unselect it --if self.selected == y then --if self.selected == y then --self.selected = -1; --return; --end getSoundManager():playUISound("UISelectListItem") self.selected = row; if self.onmousedown then self.onmousedown(self.target, self.items[self.selected].item); end end function ISScrollingListBox:onJoypadDirUp() self.selected = self:prevVisibleIndex(self.selected) if self.selected <= 0 then self.selected = self:prevVisibleIndex(self.count + 1); end getSoundManager():playUISound("UISelectListItem") self:ensureVisible(self.selected) if self.onmousedown and self.items[self.selected] then self.onmousedown(self.target, self.items[self.selected].item); end end function ISScrollingListBox:onJoypadDirDown() self.selected = self:nextVisibleIndex(self.selected) if self.selected == -1 then self.selected = self:nextVisibleIndex(0); end getSoundManager():playUISound("UISelectListItem") self:ensureVisible(self.selected) if self.onmousedown and self.items[self.selected] then self.onmousedown(self.target, self.items[self.selected].item); end end function ISScrollingListBox:ensureVisible(index) if not index or index < 1 or index > #self.items then return end local y = 0 local height = 0 for k, v in ipairs(self.items) do if k == index then height = v.height break end y = y + v.height end -- print('y='..y..' top='..self:getYScroll()..' bottom='..(self:getYScroll() + self.height)) if not self.smoothScrollTargetY then self.smoothScrollY = self:getYScroll() end if y < 0-self:getYScroll() then self.smoothScrollTargetY = 0 - y elseif y + height > 0 - self:getYScroll() + self.height then self.smoothScrollTargetY = 0 - (y + height - self.height) end end function ISScrollingListBox:render() if self.joypadFocused then self:drawRectBorder(0, -self:getYScroll(), self:getWidth(), self:getHeight(), 0.4, 0.2, 1.0, 1.0); self:drawRectBorder(1, 1-self:getYScroll(), self:getWidth()-2, self:getHeight()-2, 0.4, 0.2, 1.0, 1.0); end end function ISScrollingListBox:onJoypadDown(button, joypadData) if button == Joypad.AButton and self.onmousedblclick then if (#self.items > 0) and (self.selected ~= -1) then local previousSelected = self.selected; self.onmousedblclick(self.target, self.items[self.selected].item); self.selected = previousSelected; end elseif button == Joypad.BButton and self.joypadParent then self.joypadFocused = false; joypadData.focus = self.joypadParent; updateJoypadFocus(joypadData); else ISPanelJoypad.onJoypadDown(self, button); end end function ISScrollingListBox:onLoseJoypadFocus(joypadData) ISPanelJoypad.onLoseJoypadFocus(self, joypadData) self:setJoypadFocused(false, joypadData) if self.resetSelectionOnChangeFocus then self.selectedBeforeReset = self.selected self.selected = -1; end end function ISScrollingListBox:setFont(font, padY) self.font = UIFont[font] or font self.fontHgt = getTextManager():getFontFromEnum(self.font):getLineHeight() self.itemPadY = padY self.itemheight = self.fontHgt + (self.itemPadY or 0) * 2; end function ISScrollingListBox:addColumn(columnName, size) table.insert(self.columns, {name = columnName, size = size}); end --************************************************************************-- --** ISInventoryPane:new --** --************************************************************************-- function ISScrollingListBox:new (x, y, width, height) local o = {} --o.data = {} o = ISPanelJoypad:new(x, y, width, height); setmetatable(o, self) self.__index = self o.x = x; o.y = y; o:noBackground(); o.backgroundColor = {r=0, g=0, b=0, a=0.8}; o.borderColor = {r=0.4, g=0.4, b=0.4, a=0.9}; o.altBgColor = {r=0.2, g=0.3, b=0.2, a=0.1 } o.listHeaderColor = {r=0.4, g=0.4, b=0.4, a=0.3}; -- Since these were broken before, don't draw them by default o.altBgColor = nil o.drawBorder = false o.width = width; o.height = height; o.anchorLeft = true; o.anchorRight = false; o.anchorTop = true; o.anchorBottom = false; o.font = UIFont.Large o.fontHgt = getTextManager():getFontFromEnum(o.font):getLineHeight() o.itemPadY = 7 o.itemheight = o.fontHgt + o.itemPadY * 2; o.selected = 1; o.count = 0; o.itemheightoverride = {} o.items = {} o.columns = {}; return o end