Files
pyfa/gui/builtinShipBrowser/raceSelector.py
Ryan Holmes 729c46ab00 Revert "Remove EVT_ERASE_BACKGROUND events - pretty sure these were there for older versions of wx where the background wasn't erased properly"
This does help prevent flickering on resizing. Need to research more before removing them

This reverts commit 8c5c7fba29.
2017-06-14 03:57:57 -04:00

272 lines
9.1 KiB
Python

# coding: utf-8
import wx
from logbook import Logger
import gui.utils.anim_effects as animEffects
import gui.utils.color as colorUtils
import gui.utils.draw as drawUtils
from .events import *
from gui.bitmap_loader import BitmapLoader
pyfalog = Logger(__name__)
class RaceSelector(wx.Window):
def __init__(self, parent, id=wx.ID_ANY, label="", pos=wx.DefaultPosition, size=wx.DefaultSize, style=0,
layout=wx.VERTICAL, animate=False):
wx.Window.__init__(self, parent, id, pos=pos, size=size, style=style)
self.animTimerID = wx.NewId()
self.animTimer = wx.Timer(self, self.animTimerID)
self.animPeriod = 25
self.animDuration = 250
self.animStep = 0
self.maxWidth = 24
self.minWidth = 5 if animate else self.maxWidth
self.maxHeight = 24
self.minHeight = 10 if animate else self.maxHeight
self.direction = 0 if animate else 1
self.layout = layout
self.animate = animate
if layout == wx.VERTICAL:
self.SetSize(wx.Size(self.minWidth, -1))
self.SetMinSize(wx.Size(self.minWidth, -1))
else:
self.SetSize(wx.Size(-1, self.minHeight))
self.SetMinSize(wx.Size(-1, self.minHeight))
self.checkTimerID = wx.NewId()
self.checkTimer = wx.Timer(self, self.checkTimerID)
self.checkPeriod = 250
self.checkMaximize = True
self.shipBrowser = self.Parent
self.raceBmps = []
self.raceNames = []
self.hoveredItem = None
if layout == wx.VERTICAL:
self.buttonsBarPos = (4, 0)
else:
self.buttonsBarPos = (0, 4)
self.buttonsPadding = 4
if layout == wx.VERTICAL:
self.bmpArrow = BitmapLoader.getBitmap("down-arrow2", "gui")
else:
self.bmpArrow = BitmapLoader.getBitmap("up-arrow2", "gui")
# Make the bitmaps have the same color as window text
sysTextColour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT)
img = self.bmpArrow.ConvertToImage()
if layout == wx.VERTICAL:
img = img.Rotate90(False)
img.Replace(0, 0, 0, sysTextColour[0], sysTextColour[1], sysTextColour[2])
if layout == wx.VERTICAL:
img = img.Scale(self.minWidth, 8, wx.IMAGE_QUALITY_HIGH)
self.bmpArrow = wx.Bitmap(img)
self.RebuildRaces(self.shipBrowser.RACE_ORDER)
self.Bind(wx.EVT_ENTER_WINDOW, self.OnWindowEnter)
self.Bind(wx.EVT_LEAVE_WINDOW, self.OnWindowLeave)
self.Bind(wx.EVT_TIMER, self.OnTimer)
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnBackgroundErase)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
self.Bind(wx.EVT_MOTION, self.OnMouseMove)
self.Bind(wx.EVT_SIZE, self.OnSizeUpdate)
self.Layout()
def OnMouseMove(self, event):
mx, my = event.GetPosition()
location = self.HitTest(mx, my)
if location != self.hoveredItem:
self.hoveredItem = location
self.Refresh()
if location is not None:
self.SetCursor(wx.Cursor(wx.CURSOR_HAND))
else:
self.SetCursor(wx.Cursor(wx.CURSOR_ARROW))
def OnSizeUpdate(self, event):
self.CalcButtonsBarPos()
self.Refresh()
event.Skip()
def CalcButtonsBarPos(self):
if self.layout == wx.HORIZONTAL:
rect = self.GetRect()
width = 0
height = 0
for bmp in self.raceBmps:
width += bmp.GetWidth() + self.buttonsPadding
height = max(bmp.GetHeight(), height)
posx = (rect.width - width) / 2
posy = (rect.height - height) / 2
self.buttonsBarPos = (posx, posy)
def OnLeftUp(self, event):
mx, my = event.GetPosition()
toggle = self.HitTest(mx, my)
if toggle is not None:
self.Refresh()
self.shipBrowser.ToggleRacesFilter(self.raceNames[toggle])
stage = self.shipBrowser.GetActiveStage()
if stage == 2:
categoryID = self.shipBrowser.GetStageData(stage)
wx.PostEvent(self.shipBrowser, Stage2Selected(categoryID=categoryID, back=True))
event.Skip()
def HitTest(self, mx, my):
x, y = self.buttonsBarPos
padding = self.buttonsPadding
for bmp in self.raceBmps:
if (x < mx < x + bmp.GetWidth()) and (y < my < y + bmp.GetHeight()):
return self.raceBmps.index(bmp)
if self.layout == wx.VERTICAL:
y += bmp.GetHeight() + padding
else:
x += bmp.GetWidth() + padding
return None
def RebuildRaces(self, races):
self.raceBmps = []
for race in races:
if race:
self.raceBmps.append(BitmapLoader.getBitmap("race_%s_small" % race, "gui"))
self.raceNames = races
self.CalcButtonsBarPos()
self.Refresh()
def OnBackgroundErase(self, event):
pass
def OnPaint(self, event):
rect = self.GetRect()
windowColor = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)
# bkColor = colorUtils.GetSuitable(windowColor, 0.1)
sepColor = colorUtils.GetSuitable(windowColor, 0.2)
mdc = wx.BufferedPaintDC(self)
bkBitmap = drawUtils.RenderGradientBar(windowColor, rect.width, rect.height, 0.1, 0.1, 0.2, 2)
mdc.DrawBitmap(bkBitmap, 0, 0, True)
x, y = self.buttonsBarPos
if self.direction == 1:
for raceBmp in self.raceBmps:
dropShadow = drawUtils.CreateDropShadowBitmap(raceBmp, 0.2)
if self.shipBrowser.GetRaceFilterState(self.raceNames[self.raceBmps.index(raceBmp)]):
bmp = raceBmp
else:
img = raceBmp.ConvertToImage()
if self.hoveredItem == self.raceBmps.index(raceBmp):
img = img.AdjustChannels(1, 1, 1, 0.7)
else:
img = img.AdjustChannels(1, 1, 1, 0.4)
bmp = wx.Bitmap(img)
if self.layout == wx.VERTICAL:
mdc.DrawBitmap(dropShadow, rect.width - self.buttonsPadding - bmp.GetWidth() + 1, y + 1)
mdc.DrawBitmap(bmp, rect.width - self.buttonsPadding - bmp.GetWidth(), y)
y += raceBmp.GetHeight() + self.buttonsPadding
mdc.SetPen(wx.Pen(sepColor, 1))
mdc.DrawLine(rect.width - 1, 0, rect.width - 1, rect.height)
else:
mdc.DrawBitmap(dropShadow, x + 1, self.buttonsPadding + 1)
mdc.DrawBitmap(bmp, x, self.buttonsPadding)
x += raceBmp.GetWidth() + self.buttonsPadding
mdc.SetPen(wx.Pen(sepColor, 1))
mdc.DrawLine(0, 0, rect.width, 0)
if self.direction < 1:
if self.layout == wx.VERTICAL:
mdc.DrawBitmap(self.bmpArrow, -2, (rect.height - self.bmpArrow.GetHeight()) / 2)
else:
mdc.SetPen(wx.Pen(sepColor, 1))
mdc.DrawLine(0, 0, rect.width, 0)
mdc.DrawBitmap(self.bmpArrow, (rect.width - self.bmpArrow.GetWidth()) / 2, -2)
def OnTimer(self, event):
if event.GetId() == self.animTimerID:
start = 0
if self.layout == wx.VERTICAL:
end = self.maxWidth - self.minWidth
else:
end = self.maxHeight - self.minHeight
step = animEffects.OUT_CIRC(self.animStep, start, end, self.animDuration)
self.animStep += self.animPeriod * self.direction
self.AdjustSize((self.minWidth if self.layout == wx.VERTICAL else self.minHeight) + step)
if self.animStep > self.animDuration or self.animStep < 0:
self.animTimer.Stop()
self.animStep = self.animDuration if self.direction == 1 else 0
self.Parent.GetBrowserContainer().RefreshList(True)
if event.GetId() == self.checkTimerID:
if self.checkMaximize:
self.direction = 1
else:
self.direction = -1
if not self.animTimer.IsRunning():
self.animTimer.Start(self.animPeriod)
def AdjustSize(self, delta):
self.SetMinSize(wx.Size(delta, -1) if self.layout == wx.VERTICAL else wx.Size(-1, delta))
self.Parent.Layout()
self.Refresh()
def OnWindowEnter(self, event):
if not self.animate:
return
if not self.checkTimer.IsRunning():
self.checkTimer.Start(self.checkPeriod, wx.TIMER_ONE_SHOT)
self.checkMaximize = True
event.Skip()
def OnWindowLeave(self, event):
if self.hoveredItem is not None:
self.hoveredItem = None
self.SetCursor(wx.Cursor(wx.CURSOR_ARROW))
self.Refresh()
if not self.animate:
return
if not self.checkTimer.IsRunning():
self.checkTimer.Start(self.checkPeriod, wx.TIMER_ONE_SHOT)
self.checkMaximize = False
event.Skip()