From 048ae0205cf39260fb3d36b132be440ff374116c Mon Sep 17 00:00:00 2001 From: Ryan Holmes Date: Sun, 11 Jun 2017 17:32:43 -0400 Subject: [PATCH] Breakout shipBrowser into individual class files --- gui/builtinShipBrowser/__init__.py | 0 gui/builtinShipBrowser/categoryItem.py | 129 ++ gui/builtinShipBrowser/events.py | 14 + gui/builtinShipBrowser/fitItem.py | 604 ++++++ gui/builtinShipBrowser/navigationPanel.py | 274 +++ gui/builtinShipBrowser/pfBitmapButton.py | 14 + gui/builtinShipBrowser/pfBitmapFrame.py | 59 + .../pfListPane.py} | 0 gui/builtinShipBrowser/pfStaticText.py | 23 + gui/builtinShipBrowser/pfWidgetContainer.py | 35 + gui/builtinShipBrowser/raceSelector.py | 271 +++ gui/{ => builtinShipBrowser}/sfBrowserItem.py | 0 gui/builtinShipBrowser/shipItem.py | 285 +++ gui/builtinViews/fittingView.py | 14 +- gui/mainFrame.py | 3 +- gui/shipBrowser.py | 1641 +---------------- 16 files changed, 1730 insertions(+), 1636 deletions(-) create mode 100644 gui/builtinShipBrowser/__init__.py create mode 100644 gui/builtinShipBrowser/categoryItem.py create mode 100644 gui/builtinShipBrowser/events.py create mode 100644 gui/builtinShipBrowser/fitItem.py create mode 100644 gui/builtinShipBrowser/navigationPanel.py create mode 100644 gui/builtinShipBrowser/pfBitmapButton.py create mode 100644 gui/builtinShipBrowser/pfBitmapFrame.py rename gui/{PFListPane.py => builtinShipBrowser/pfListPane.py} (100%) create mode 100644 gui/builtinShipBrowser/pfStaticText.py create mode 100644 gui/builtinShipBrowser/pfWidgetContainer.py create mode 100644 gui/builtinShipBrowser/raceSelector.py rename gui/{ => builtinShipBrowser}/sfBrowserItem.py (100%) create mode 100644 gui/builtinShipBrowser/shipItem.py diff --git a/gui/builtinShipBrowser/__init__.py b/gui/builtinShipBrowser/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/gui/builtinShipBrowser/categoryItem.py b/gui/builtinShipBrowser/categoryItem.py new file mode 100644 index 000000000..520c0efa7 --- /dev/null +++ b/gui/builtinShipBrowser/categoryItem.py @@ -0,0 +1,129 @@ +# coding: utf-8 + +import wx +from logbook import Logger + +from gui.builtinShipBrowser.sfBrowserItem import SFBrowserItem +import gui.utils.colorUtils as colorUtils +import gui.utils.drawUtils as drawUtils +import gui.utils.fonts as fonts +from gui.bitmapLoader import BitmapLoader +from .events import * + +pyfalog = Logger(__name__) + + +class CategoryItem(SFBrowserItem): + def __init__(self, parent, categoryID, fittingInfo, size=(0, 16)): + SFBrowserItem.__init__(self, parent, size=size) + + if categoryID: + self.shipBmp = BitmapLoader.getBitmap("ship_small", "gui") + else: + self.shipBmp = wx.EmptyBitmap(16, 16) + + self.dropShadowBitmap = drawUtils.CreateDropShadowBitmap(self.shipBmp, 0.2) + + self.categoryID = categoryID + self.fittingInfo = fittingInfo + self.shipBrowser = self.Parent.Parent + + self.padding = 4 + + self.fontBig = wx.Font(fonts.BIG, wx.SWISS, wx.NORMAL, wx.NORMAL) + + self.animTimerId = wx.NewId() + + self.animTimer = wx.Timer(self, self.animTimerId) + self.animStep = 0 + self.animPeriod = 10 + self.animDuration = 100 + + self.Bind(wx.EVT_TIMER, self.OnTimer) + + # ===================================================================== + # Disabled - it will be added as an option to Preferences + self.animCount = 0 + # self.animTimer.Start(self.animPeriod) + # ===================================================================== + + def OnTimer(self, event): + step = self.OUT_QUAD(self.animStep, 0, 10, self.animDuration) + self.animCount = 10 - step + self.animStep += self.animPeriod + if self.animStep > self.animDuration or self.animCount < 0: + self.animCount = 0 + self.animTimer.Stop() + self.Refresh() + + @staticmethod + def OUT_QUAD(t, b, c, d): + t = float(t) + b = float(b) + c = float(c) + d = float(d) + + t /= d + + return -c * t * (t - 2) + b + + def GetType(self): + return 1 + + def MouseLeftUp(self, event): + + categoryID = self.categoryID + wx.PostEvent(self.shipBrowser, Stage2Selected(categoryID=categoryID, back=False)) + + def UpdateElementsPos(self, mdc): + rect = self.GetRect() + self.shipBmpx = self.padding + self.shipBmpy = (rect.height - self.shipBmp.GetWidth()) / 2 + + self.shipBmpx -= self.animCount + + mdc.SetFont(self.fontBig) + categoryName, fittings = self.fittingInfo + wtext, htext = mdc.GetTextExtent(categoryName) + + self.catx = self.shipBmpx + self.shipBmp.GetWidth() + self.padding + self.caty = (rect.height - htext) / 2 + + def DrawItem(self, mdc): + # rect = self.GetRect() + self.UpdateElementsPos(mdc) + + windowColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW) + textColor = colorUtils.GetSuitableColor(windowColor, 1) + + mdc.SetTextForeground(textColor) + mdc.DrawBitmap(self.dropShadowBitmap, self.shipBmpx + 1, self.shipBmpy + 1) + mdc.DrawBitmap(self.shipBmp, self.shipBmpx, self.shipBmpy, 0) + + mdc.SetFont(self.fontBig) + + categoryName, fittings = self.fittingInfo + + mdc.DrawText(categoryName, self.catx, self.caty) + + +# ============================================================================= +# Waiting for total #fits impl in eos/service +# +# mdc.SetFont(wx.Font(8, wx.SWISS, wx.NORMAL, wx.NORMAL, False)) +# +# if fittings <1: +# fformat = "No fits" +# else: +# if fittings == 1: +# fformat = "%d fit" +# else: +# fformat = "%d fits" +# +# if fittings>0: +# xtext, ytext = mdc.GetTextExtent(fformat % fittings) +# ypos = (rect.height - ytext)/2 +# else: +# xtext, ytext = mdc.GetTextExtent(fformat) +# ypos = (rect.height - ytext)/2 +# ============================================================================= diff --git a/gui/builtinShipBrowser/events.py b/gui/builtinShipBrowser/events.py new file mode 100644 index 000000000..eccb0eda9 --- /dev/null +++ b/gui/builtinShipBrowser/events.py @@ -0,0 +1,14 @@ +# noinspection PyPackageRequirements +import wx.lib.newevent + +FitRenamed, EVT_FIT_RENAMED = wx.lib.newevent.NewEvent() +FitSelected, EVT_FIT_SELECTED = wx.lib.newevent.NewEvent() +FitRemoved, EVT_FIT_REMOVED = wx.lib.newevent.NewEvent() + +BoosterListUpdated, BOOSTER_LIST_UPDATED = wx.lib.newevent.NewEvent() + +Stage1Selected, EVT_SB_STAGE1_SEL = wx.lib.newevent.NewEvent() +Stage2Selected, EVT_SB_STAGE2_SEL = wx.lib.newevent.NewEvent() +Stage3Selected, EVT_SB_STAGE3_SEL = wx.lib.newevent.NewEvent() +SearchSelected, EVT_SB_SEARCH_SEL = wx.lib.newevent.NewEvent() +ImportSelected, EVT_SB_IMPORT_SEL = wx.lib.newevent.NewEvent() \ No newline at end of file diff --git a/gui/builtinShipBrowser/fitItem.py b/gui/builtinShipBrowser/fitItem.py new file mode 100644 index 000000000..9f04a8c5b --- /dev/null +++ b/gui/builtinShipBrowser/fitItem.py @@ -0,0 +1,604 @@ +# coding: utf-8 + +import re +import time + +import wx +from logbook import Logger + +import gui.builtinShipBrowser.sfBrowserItem as SFItem +import gui.globalEvents as GE +import gui.mainFrame +import gui.utils.colorUtils as colorUtils +import gui.utils.drawUtils as drawUtils +import gui.utils.fonts as fonts +from events import * +from gui.bitmapLoader import BitmapLoader +from gui.builtinShipBrowser.pfBitmapFrame import PFBitmapFrame +from service.fit import Fit + +pyfalog = Logger(__name__) + + +class FitItem(SFItem.SFBrowserItem): + def __init__(self, parent, fitID=None, shipFittingInfo=("Test", "TestTrait", "cnc's avatar", 0, 0, None), shipID=None, + itemData=None, + id=wx.ID_ANY, pos=wx.DefaultPosition, + size=(0, 40), style=0): + + # ===================================================================== + # animCount should be 10 if we enable animation in Preferences + # ===================================================================== + + self.animCount = 0 + self.selectedDelta = 0 + + SFItem.SFBrowserItem.__init__(self, parent, size=size) + + self.mainFrame = gui.mainFrame.MainFrame.getInstance() + + self._itemData = itemData + + self.fitID = fitID + + self.shipID = shipID + + self.shipBrowser = self.Parent.Parent + + self.shipBmp = None + + self.deleted = False + + if shipID: + self.shipBmp = BitmapLoader.getBitmap(str(shipID), "renders") + + if not self.shipBmp: + self.shipBmp = BitmapLoader.getBitmap("ship_no_image_big", "gui") + + self.shipFittingInfo = shipFittingInfo + self.shipName, self.shipTrait, self.fitName, self.fitBooster, self.timestamp, self.notes = shipFittingInfo + + self.shipTrait = re.sub("<.*?>", " ", self.shipTrait) + # see GH issue #62 + + # Disabling this due to change in gang boosts Nov 2016 + # if self.fitBooster is None: self.fitBooster = False + self.fitBooster = False + + self.boosterBmp = BitmapLoader.getBitmap("fleet_fc_small", "gui") + self.copyBmp = BitmapLoader.getBitmap("fit_add_small", "gui") + self.renameBmp = BitmapLoader.getBitmap("fit_rename_small", "gui") + self.deleteBmp = BitmapLoader.getBitmap("fit_delete_small", "gui") + self.acceptBmp = BitmapLoader.getBitmap("faccept_small", "gui") + self.shipEffBk = BitmapLoader.getBitmap("fshipbk_big", "gui") + + img = wx.ImageFromBitmap(self.shipEffBk) + img = img.Mirror(False) + self.shipEffBkMirrored = wx.BitmapFromImage(img) + + self.dragTLFBmp = None + + self.bkBitmap = None + + self.__setToolTip() + + self.padding = 4 + self.editWidth = 150 + + self.dragging = False + self.dragged = False + self.dragMotionTrail = 5 + self.dragMotionTrigger = self.dragMotionTrail + self.dragWindow = None + + self.fontBig = wx.Font(fonts.BIG, wx.SWISS, wx.NORMAL, wx.BOLD) + self.fontNormal = wx.Font(fonts.NORMAL, wx.SWISS, wx.NORMAL, wx.NORMAL) + self.fontSmall = wx.Font(fonts.SMALL, wx.SWISS, wx.NORMAL, wx.NORMAL) + + self.SetDraggable() + + self.boosterBtn = self.toolbar.AddButton(self.boosterBmp, "Booster", show=self.fitBooster) + self.toolbar.AddButton(self.copyBmp, "Copy", self.copyBtnCB) + self.renameBtn = self.toolbar.AddButton(self.renameBmp, "Rename", self.renameBtnCB) + self.toolbar.AddButton(self.deleteBmp, "Delete", self.deleteBtnCB) + + self.tcFitName = wx.TextCtrl(self, wx.ID_ANY, "%s" % self.fitName, wx.DefaultPosition, (self.editWidth, -1), + wx.TE_PROCESS_ENTER) + + if self.shipBrowser.fitIDMustEditName != self.fitID: + self.tcFitName.Show(False) + else: + self.tcFitName.SetFocus() + self.tcFitName.SelectAll() + self.shipBrowser.fitIDMustEditName = -1 + self.renameBtn.SetBitmap(self.acceptBmp) + + self.tcFitName.Bind(wx.EVT_TEXT_ENTER, self.renameFit) + self.tcFitName.Bind(wx.EVT_KILL_FOCUS, self.editLostFocus) + self.tcFitName.Bind(wx.EVT_KEY_DOWN, self.editCheckEsc) + self.Bind(wx.EVT_MOUSE_CAPTURE_LOST, self.OnMouseCaptureLost) + + self.animTimerId = wx.NewId() + self.animTimer = wx.Timer(self, self.animTimerId) + self.animStep = 0 + self.animPeriod = 10 + self.animDuration = 100 + + self.maxDelta = 48 + + self.Bind(wx.EVT_TIMER, self.OnTimer) + + # ===================================================================== + # DISABLED - it will be added as an option in PREFERENCES + + # if self.shipBrowser.GetActiveStage() != 4 and self.shipBrowser.GetLastStage() !=3: + # self.animTimer.Start(self.animPeriod) + # else: + # self.animCount = 0 + # ===================================================================== + + """ + # Remove this bit as the time stuff is non-functional (works... but not exactly sure what it's meant to do) + self.selTimerID = wx.NewId() + + self.selTimer = wx.Timer(self, self.selTimerID) + self.selTimer.Start(100) + """ + + self.Bind(wx.EVT_RIGHT_UP, self.OnContextMenu) + self.Bind(wx.EVT_MIDDLE_UP, self.OpenNewTab) + + def __setToolTip(self): + sFit = Fit.getInstance() + # show no tooltip if no trait available or setting is disabled + if self.shipTrait and sFit.serviceFittingOptions["showShipBrowserTooltip"]: + notes = "" + if self.notes: + notes = u'─' * 20 + u"\nNotes: {}\n".format(self.notes[:197] + '...' if len(self.notes) > 200 else self.notes) + self.SetToolTip(wx.ToolTip(u'{}\n{}{}\n{}'.format(self.shipName, notes, u'─' * 20, self.shipTrait))) + + def OnKeyDown(self, event): + if event.GetKeyCode() == 32: # space + self.selectFit(event) + event.Skip() + + def OpenNewTab(self, evt): + self.selectFit(newTab=True) + + def OnToggleBooster(self, event): + sFit = Fit.getInstance() + sFit.toggleBoostFit(self.fitID) + self.fitBooster = not self.fitBooster + self.boosterBtn.Show(self.fitBooster) + self.Refresh() + wx.PostEvent(self.mainFrame, BoosterListUpdated()) + event.Skip() + + def OnProjectToFit(self, event): + activeFit = self.mainFrame.getActiveFit() + if activeFit: + sFit = Fit.getInstance() + projectedFit = sFit.getFit(self.fitID) + sFit.project(activeFit, projectedFit) + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=activeFit)) + self.mainFrame.additionsPane.select("Projected") + + def OnAddCommandFit(self, event): + activeFit = self.mainFrame.getActiveFit() + if activeFit: + sFit = Fit.getInstance() + commandFit = sFit.getFit(self.fitID) + sFit.addCommandFit(activeFit, commandFit) + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=activeFit)) + self.mainFrame.additionsPane.select("Command") + + def OnMouseCaptureLost(self, event): + """ Destroy drag information (GH issue #479)""" + if self.dragging and self.dragged: + self.dragging = False + self.dragged = False + if self.HasCapture(): + self.ReleaseMouse() + self.dragWindow.Show(False) + self.dragWindow = None + + def OnContextMenu(self, event): + """ Handles context menu for fit. Dragging is handled by MouseLeftUp() """ + sFit = Fit.getInstance() + fit = sFit.getFit(self.mainFrame.getActiveFit()) + + if not fit: + return + + pos = wx.GetMousePosition() + pos = self.ScreenToClient(pos) + + # Even though we may not select a booster, automatically set this so that the fleet pane knows which fit we're applying + self.mainFrame.additionsPane.gangPage.draggedFitID = self.fitID + + menu = wx.Menu() + # toggleItem = menu.Append(wx.ID_ANY, "Booster Fit", kind=wx.ITEM_CHECK) + # menu.Check(toggleItem.GetId(), self.fitBooster) + # self.Bind(wx.EVT_MENU, self.OnToggleBooster, toggleItem) + + # if fit and not fit.isStructure: + # # If there is an active fit, get menu for setting individual boosters + # menu.AppendSeparator() + # boosterMenu = self.mainFrame.additionsPane.gangPage.buildBoostermenu() + # menu.AppendSubMenu(boosterMenu, 'Set Booster') + + if fit: + newTabItem = menu.Append(wx.ID_ANY, "Open in new tab") + self.Bind(wx.EVT_MENU, self.OpenNewTab, newTabItem) + + projectedItem = menu.Append(wx.ID_ANY, "Project onto Active Fit") + self.Bind(wx.EVT_MENU, self.OnProjectToFit, projectedItem) + + commandItem = menu.Append(wx.ID_ANY, "Add Command Booster") + self.Bind(wx.EVT_MENU, self.OnAddCommandFit, commandItem) + + self.PopupMenu(menu, pos) + + event.Skip() + + def GetType(self): + return 3 + + def OnTimer(self, event): + + # @todo: figure out what exactly this is supposed to accomplish + if self.selTimerID == event.GetId(): + ctimestamp = time.time() + interval = 5 + if ctimestamp < self.timestamp + interval: + delta = (ctimestamp - self.timestamp) / interval + self.selectedDelta = self.CalculateDelta(0x0, self.maxDelta, delta) + self.Refresh() + else: + self.selectedDelta = self.maxDelta + self.selTimer.Stop() + + if self.animTimerId == event.GetId(): + step = self.OUT_QUAD(self.animStep, 0, 10, self.animDuration) + self.animCount = 10 - step + self.animStep += self.animPeriod + if self.animStep > self.animDuration or self.animCount < 0: + self.animCount = 0 + self.animTimer.Stop() + self.Refresh() + + @staticmethod + def CalculateDelta(start, end, delta): + return start + (end - start) * delta + + @staticmethod + def OUT_QUAD(t, b, c, d): + t = float(t) + b = float(b) + c = float(c) + d = float(d) + + t /= d + + return -c * t * (t - 2) + b + + def editLostFocus(self, event): + self.RestoreEditButton() + self.Refresh() + + def editCheckEsc(self, event): + if event.GetKeyCode() == wx.WXK_ESCAPE: + self.RestoreEditButton() + else: + event.Skip() + + def copyBtnCB(self): + if self.tcFitName.IsShown(): + self.RestoreEditButton() + return + + self.copyFit() + + def copyFit(self, event=None): + sFit = Fit.getInstance() + fitID = sFit.copyFit(self.fitID) + self.shipBrowser.fitIDMustEditName = fitID + wx.PostEvent(self.shipBrowser, Stage3Selected(shipID=self.shipID)) + wx.PostEvent(self.mainFrame, FitSelected(fitID=fitID)) + + def renameBtnCB(self): + if self.tcFitName.IsShown(): + self.RestoreEditButton() + self.renameFit() + else: + self.tcFitName.SetValue(self.fitName) + self.tcFitName.Show() + self.renameBtn.SetBitmap(self.acceptBmp) + self.tcFitName.SetFocus() + self.tcFitName.SelectAll() + + self.Refresh() + + def renameFit(self, event=None): + sFit = Fit.getInstance() + self.tcFitName.Show(False) + self.editWasShown = 0 + fitName = self.tcFitName.GetValue() + if fitName: + self.fitName = fitName + sFit.renameFit(self.fitID, self.fitName) + wx.PostEvent(self.mainFrame, FitRenamed(fitID=self.fitID)) + else: + self.tcFitName.SetValue(self.fitName) + + def deleteBtnCB(self): + if self.tcFitName.IsShown(): + self.RestoreEditButton() + return + + # to prevent accidental deletion, give dialog confirmation unless shift is depressed + if wx.GetMouseState().ShiftDown() or wx.GetMouseState().MiddleDown(): + self.deleteFit() + else: + dlg = wx.MessageDialog( + self, + "Do you really want to delete this fit?", + "Confirm Delete", + wx.YES | wx.NO | wx.ICON_QUESTION + ) + + if dlg.ShowModal() == wx.ID_YES: + self.deleteFit() + + def deleteFit(self, event=None): + pyfalog.debug("Deleting ship fit.") + if self.deleted: + return + else: + self.deleted = True + + sFit = Fit.getInstance() + fit = sFit.getFit(self.fitID) + + # need to delete from import cache before actually deleting fit + if self.shipBrowser.GetActiveStage() == 5: + if fit in self.shipBrowser.lastdata: # remove fit from import cache + self.shipBrowser.lastdata.remove(fit) + + sFit.deleteFit(self.fitID) + + # Notify other areas that a fit has been deleted + wx.PostEvent(self.mainFrame, FitRemoved(fitID=self.fitID)) + + # todo: would a simple RefreshList() work here instead of posting that a stage has been selected? + if self.shipBrowser.GetActiveStage() == 5: + wx.PostEvent(self.shipBrowser, ImportSelected(fits=self.shipBrowser.lastdata)) + elif self.shipBrowser.GetActiveStage() == 4: + wx.PostEvent(self.shipBrowser, SearchSelected(text=self.shipBrowser.navpanel.lastSearch, back=True)) + else: + wx.PostEvent(self.shipBrowser, Stage3Selected(shipID=self.shipID)) + + def MouseLeftUp(self, event): + if self.dragging and self.dragged: + self.OnMouseCaptureLost(event) + + targetWnd = wx.FindWindowAtPointer() + + if not targetWnd: + return + + wnd = targetWnd + while wnd is not None: + handler = getattr(wnd, "handleDrag", None) + if handler: + handler("fit", self.fitID) + break + else: + wnd = wnd.Parent + event.Skip() + return + + if self.dragging: + self.dragging = False + + if self.tcFitName.IsShown(): + self.RestoreEditButton() + else: + activeFitID = self.mainFrame.getActiveFit() + if activeFitID != self.fitID: + self.selectFit() + + def MouseLeftDown(self, event): + self.dragging = True + + def MouseMove(self, event): + pos = self.ClientToScreen(event.GetPosition()) + if self.dragging: + if not self.dragged: + if self.dragMotionTrigger < 0: + if not self.HasCapture(): + self.CaptureMouse() + self.dragWindow = PFBitmapFrame(self, pos, self.dragTLFBmp) + self.dragWindow.Show() + self.dragged = True + self.dragMotionTrigger = self.dragMotionTrail + else: + self.dragMotionTrigger -= 1 + if self.dragWindow: + pos.x += 3 + pos.y += 3 + self.dragWindow.SetPosition(pos) + return + + def selectFit(self, event=None, newTab=False): + if newTab: + wx.PostEvent(self.mainFrame, FitSelected(fitID=self.fitID, startup=2)) + else: + wx.PostEvent(self.mainFrame, FitSelected(fitID=self.fitID)) + + def RestoreEditButton(self): + self.tcFitName.Show(False) + self.renameBtn.SetBitmap(self.renameBmp) + self.Refresh() + + def UpdateElementsPos(self, mdc): + rect = self.GetRect() + + self.toolbarx = rect.width - self.toolbar.GetWidth() - self.padding + self.toolbary = (rect.height - self.toolbar.GetHeight()) / 2 + + self.toolbarx += self.animCount + + self.shipEffx = self.padding + (rect.height - self.shipEffBk.GetWidth()) / 2 + self.shipEffy = (rect.height - self.shipEffBk.GetHeight()) / 2 + + self.shipEffx -= self.animCount + + self.shipBmpx = self.padding + (rect.height - self.shipBmp.GetWidth()) / 2 + self.shipBmpy = (rect.height - self.shipBmp.GetHeight()) / 2 + + self.shipBmpx -= self.animCount + + self.textStartx = self.shipEffx + self.shipEffBk.GetWidth() + self.padding + + self.fitNamey = (rect.height - self.shipBmp.GetHeight()) / 2 + + mdc.SetFont(self.fontBig) + wtext, htext = mdc.GetTextExtent(self.fitName) + + self.timestampy = self.fitNamey + htext + + mdc.SetFont(self.fontSmall) + + wlabel, hlabel = mdc.GetTextExtent(self.toolbar.hoverLabel) + + self.thoverx = self.toolbarx - self.padding - wlabel + self.thovery = (rect.height - hlabel) / 2 + self.thoverw = wlabel + + def DrawItem(self, mdc): + rect = self.GetRect() + + windowColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW) + textColor = colorUtils.GetSuitableColor(windowColor, 1) + + mdc.SetTextForeground(textColor) + + self.UpdateElementsPos(mdc) + + self.toolbar.SetPosition((self.toolbarx, self.toolbary)) + + if self.GetState() & SFItem.SB_ITEM_HIGHLIGHTED: + shipEffBk = self.shipEffBkMirrored + else: + shipEffBk = self.shipEffBk + + mdc.DrawBitmap(shipEffBk, self.shipEffx, self.shipEffy, 0) + + mdc.DrawBitmap(self.shipBmp, self.shipBmpx, self.shipBmpy, 0) + + mdc.SetFont(self.fontNormal) + + fitDate = self.timestamp.strftime("%m/%d/%Y %H:%M") + fitLocalDate = fitDate # "%d/%02d/%02d %02d:%02d" % (fitDate[0], fitDate[1], fitDate[2], fitDate[3], fitDate[4]) + pfdate = drawUtils.GetPartialText(mdc, fitLocalDate, + self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw) + + mdc.DrawText(pfdate, self.textStartx, self.timestampy) + + mdc.SetFont(self.fontSmall) + mdc.DrawText(self.toolbar.hoverLabel, self.thoverx, self.thovery) + + mdc.SetFont(self.fontBig) + + psname = drawUtils.GetPartialText(mdc, self.fitName, + self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw) + + mdc.DrawText(psname, self.textStartx, self.fitNamey) + + if self.tcFitName.IsShown(): + self.AdjustControlSizePos(self.tcFitName, self.textStartx, self.toolbarx - self.editWidth - self.padding) + + tdc = wx.MemoryDC() + self.dragTLFBmp = wx.EmptyBitmap((self.toolbarx if self.toolbarx < 200 else 200), rect.height, 24) + tdc.SelectObject(self.dragTLFBmp) + tdc.Blit(0, 0, (self.toolbarx if self.toolbarx < 200 else 200), rect.height, mdc, 0, 0, wx.COPY) + tdc.SelectObject(wx.NullBitmap) + + def AdjustControlSizePos(self, editCtl, start, end): + fnEditSize = editCtl.GetSize() + wSize = self.GetSize() + fnEditPosX = end + fnEditPosY = (wSize.height - fnEditSize.height) / 2 + if fnEditPosX < start: + editCtl.SetSize((self.editWidth + fnEditPosX - start, -1)) + editCtl.SetPosition((start, fnEditPosY)) + else: + editCtl.SetSize((self.editWidth, -1)) + editCtl.SetPosition((fnEditPosX, fnEditPosY)) + + def GetState(self): + activeFitID = self.mainFrame.getActiveFit() + + if self.highlighted and not activeFitID == self.fitID: + state = SFItem.SB_ITEM_HIGHLIGHTED + + else: + if activeFitID == self.fitID: + if self.highlighted: + state = SFItem.SB_ITEM_SELECTED | SFItem.SB_ITEM_HIGHLIGHTED + else: + state = SFItem.SB_ITEM_SELECTED + else: + state = SFItem.SB_ITEM_NORMAL + return state + + def Refresh(self): + activeFit = self.mainFrame.getActiveFit() + if activeFit == self.fitID and not self.deleted: + sFit = Fit.getInstance() + fit = sFit.getFit(activeFit) + if fit is not None: # sometimes happens when deleting fits, dunno why. + self.timestamp = fit.modifiedCoalesce + self.notes = fit.notes + self.__setToolTip() + + SFItem.SFBrowserItem.Refresh(self) + + def RenderBackground(self): + rect = self.GetRect() + + windowColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW) + + # activeFitID = self.mainFrame.getActiveFit() + state = self.GetState() + + sFactor = 0.2 + mFactor = None + eFactor = 0 + + if state == SFItem.SB_ITEM_HIGHLIGHTED: + mFactor = 0.45 + eFactor = 0.30 + + elif state == SFItem.SB_ITEM_SELECTED | SFItem.SB_ITEM_HIGHLIGHTED: + eFactor = 0.3 + mFactor = 0.4 + + elif state == SFItem.SB_ITEM_SELECTED: + eFactor = (self.maxDelta - self.selectedDelta) / 100 + 0.25 + else: + sFactor = 0 + + if self.bkBitmap: + if self.bkBitmap.eFactor == eFactor and self.bkBitmap.sFactor == sFactor and self.bkBitmap.mFactor == mFactor \ + and rect.width == self.bkBitmap.GetWidth() and rect.height == self.bkBitmap.GetHeight(): + return + else: + del self.bkBitmap + + self.bkBitmap = drawUtils.RenderGradientBar(windowColor, rect.width, rect.height, sFactor, eFactor, mFactor) + self.bkBitmap.state = state + self.bkBitmap.sFactor = sFactor + self.bkBitmap.eFactor = eFactor + self.bkBitmap.mFactor = mFactor diff --git a/gui/builtinShipBrowser/navigationPanel.py b/gui/builtinShipBrowser/navigationPanel.py new file mode 100644 index 000000000..0ad3382ec --- /dev/null +++ b/gui/builtinShipBrowser/navigationPanel.py @@ -0,0 +1,274 @@ +# coding: utf-8 + +import wx +from logbook import Logger + +import gui.builtinShipBrowser.sfBrowserItem as SFItem +import gui.mainFrame +import gui.utils.colorUtils as colorUtils +import gui.utils.drawUtils as drawUtils +import gui.utils.fonts as fonts +from events import * +from gui.bitmapLoader import BitmapLoader +from service.fit import Fit + +pyfalog = Logger(__name__) + + +class NavigationPanel(SFItem.SFBrowserItem): + def __init__(self, parent, size=(-1, 24)): + SFItem.SFBrowserItem.__init__(self, parent, size=size) + + self.rewBmpH = BitmapLoader.getBitmap("frewind_small", "gui") + self.forwBmp = BitmapLoader.getBitmap("fforward_small", "gui") + self.searchBmpH = BitmapLoader.getBitmap("fsearch_small", "gui") + self.newBmpH = BitmapLoader.getBitmap("fit_add_small", "gui") + self.resetBmpH = BitmapLoader.getBitmap("freset_small", "gui") + self.switchBmpH = BitmapLoader.getBitmap("fit_switch_view_mode_small", "gui") + self.recentBmpH = BitmapLoader.getBitmap("frecent_small", "gui") + + switchImg = BitmapLoader.getImage("fit_switch_view_mode_small", "gui") + switchImg = switchImg.AdjustChannels(1, 1, 1, 0.4) + self.switchBmpD = wx.BitmapFromImage(switchImg) + + recentImg = BitmapLoader.getImage("frecent_small", "gui") + recentImg = recentImg.AdjustChannels(1, 1, 1, 0.4) + self.recentBmpD = wx.BitmapFromImage(recentImg) + + self.resetBmp = self.AdjustChannels(self.resetBmpH) + self.rewBmp = self.AdjustChannels(self.rewBmpH) + self.searchBmp = self.AdjustChannels(self.searchBmpH) + self.switchBmp = self.AdjustChannels(self.switchBmpH) + self.recentBmp = self.AdjustChannels(self.recentBmpH) + self.newBmp = self.AdjustChannels(self.newBmpH) + + self.toolbar.AddButton(self.resetBmp, "Ship groups", clickCallback=self.OnHistoryReset, + hoverBitmap=self.resetBmpH) + self.toolbar.AddButton(self.rewBmp, "Back", clickCallback=self.OnHistoryBack, hoverBitmap=self.rewBmpH) + self.btnNew = self.toolbar.AddButton(self.newBmp, "New fitting", clickCallback=self.OnNewFitting, + hoverBitmap=self.newBmpH, show=False) + self.btnSwitch = self.toolbar.AddButton(self.switchBmpD, "Hide empty ship groups", + clickCallback=self.ToggleEmptyGroupsView, hoverBitmap=self.switchBmpH, + show=False) + self.btnRecent = self.toolbar.AddButton(self.recentBmpD, "Recent Fits", + clickCallback=self.ToggleRecentShips, hoverBitmap=self.recentBmpH, + show=True) + + modifier = "CTRL" if 'wxMac' not in wx.PlatformInfo else "CMD" + self.toolbar.AddButton(self.searchBmp, "Search fittings ({}+F)".format(modifier), clickCallback=self.ToggleSearchBox, + hoverBitmap=self.searchBmpH) + + self.padding = 4 + self.lastSearch = "" + self.recentSearches = [] # not used? + self.inSearch = False + + self.fontSmall = wx.Font(fonts.SMALL, wx.SWISS, wx.NORMAL, wx.NORMAL) + w, h = size + self.BrowserSearchBox = wx.TextCtrl(self, wx.ID_ANY, "", wx.DefaultPosition, + (-1, h - 2 if 'wxGTK' in wx.PlatformInfo else -1), + wx.TE_PROCESS_ENTER | (wx.BORDER_NONE if 'wxGTK' in wx.PlatformInfo else 0)) + self.BrowserSearchBox.Show(False) + + self.BrowserSearchBox.Bind(wx.EVT_TEXT_ENTER, self.OnBrowserSearchBoxEnter) + self.BrowserSearchBox.Bind(wx.EVT_KILL_FOCUS, self.OnBrowserSearchBoxLostFocus) + self.BrowserSearchBox.Bind(wx.EVT_KEY_DOWN, self.OnBrowserSearchBoxEsc) + self.BrowserSearchBox.Bind(wx.EVT_TEXT, self.OnScheduleSearch) + + self.SetMinSize(size) + self.shipBrowser = self.Parent + self.mainFrame = gui.mainFrame.MainFrame.getInstance() + + self.Bind(wx.EVT_SIZE, self.OnResize) + + def OnScheduleSearch(self, event): + search = self.BrowserSearchBox.GetValue() + # Make sure we do not count wildcard as search symbol + realsearch = search.replace("*", "") + if len(realsearch) >= 3: + self.lastSearch = search + wx.PostEvent(self.shipBrowser, SearchSelected(text=search, back=False)) + + def ToggleSearchBox(self): + if self.BrowserSearchBox.IsShown(): + self.BrowserSearchBox.Show(False) + else: + self.BrowserSearchBox.Show(True) + self.BrowserSearchBox.ChangeValue("") + self.BrowserSearchBox.SetFocus() + + def OnBrowserSearchBoxEnter(self, event): + self.OnBrowserSearchBoxLostFocus(None) + + def OnBrowserSearchBoxLostFocus(self, event): + self.BrowserSearchBox.Show(False) + + def OnBrowserSearchBoxEsc(self, event): + if event.GetKeyCode() == wx.WXK_ESCAPE: + self.BrowserSearchBox.Show(False) + else: + event.Skip() + + def OnResize(self, event): + self.Refresh() + + def ToggleRecentShips(self, bool=None, emitEvent=True): + # this is so janky. Need to revaluate pretty much entire ship browser. >.< + toggle = bool if bool is not None else not self.shipBrowser.recentFits + + if not toggle: + self.shipBrowser.recentFits = False + self.btnRecent.label = "Recent Fits" + self.btnRecent.normalBmp = self.recentBmpD + + if emitEvent: + wx.PostEvent(self.shipBrowser, Stage1Selected()) + else: + self.shipBrowser.recentFits = True + self.btnRecent.label = "Hide Recent Fits" + self.btnRecent.normalBmp = self.recentBmp + + if emitEvent: + sFit = Fit.getInstance() + fits = sFit.getRecentFits() + wx.PostEvent(self.shipBrowser, ImportSelected(fits=fits, back=True, recent=True)) + + def ToggleEmptyGroupsView(self): + if self.shipBrowser.filterShipsWithNoFits: + self.shipBrowser.filterShipsWithNoFits = False + self.btnSwitch.label = "Hide empty ship groups" + self.btnSwitch.normalBmp = self.switchBmpD + else: + self.shipBrowser.filterShipsWithNoFits = True + self.btnSwitch.label = "Show empty ship groups" + self.btnSwitch.normalBmp = self.switchBmp + + stage = self.shipBrowser.GetActiveStage() + + if stage == 1: + wx.PostEvent(self.shipBrowser, Stage1Selected()) + elif stage == 2: + categoryID = self.shipBrowser.GetStageData(stage) + wx.PostEvent(self.shipBrowser, Stage2Selected(categoryID=categoryID, back=True)) + + def ShowNewFitButton(self, show): + self.btnNew.Show(show) + self.Refresh() + + def ShowSwitchEmptyGroupsButton(self, show): + self.btnSwitch.Show(show) + self.Refresh() + + def OnNewFitting(self): + stage = self.Parent.GetActiveStage() + if stage == 3: + shipID = self.Parent.GetStageData(stage) + shipName = self.Parent.GetStage3ShipName() + sFit = Fit.getInstance() + fitID = sFit.newFit(shipID, "%s fit" % shipName) + self.shipBrowser.fitIDMustEditName = fitID + wx.PostEvent(self.Parent, Stage3Selected(shipID=shipID)) + wx.PostEvent(self.mainFrame, FitSelected(fitID=fitID)) + + def OnHistoryReset(self): + self.ToggleRecentShips(False, False) + if self.shipBrowser.browseHist: + self.shipBrowser.browseHist = [] + self.gotoStage(1, 0) + + def OnHistoryBack(self): + self.ToggleRecentShips(False, False) + if len(self.shipBrowser.browseHist) > 0: + stage, data = self.shipBrowser.browseHist.pop() + self.gotoStage(stage, data) + + @staticmethod + def AdjustChannels(bitmap): + img = wx.ImageFromBitmap(bitmap) + img = img.AdjustChannels(1.05, 1.05, 1.05, 1) + return wx.BitmapFromImage(img) + + def UpdateElementsPos(self, mdc): + rect = self.GetRect() + + self.toolbarx = self.padding + self.toolbary = (rect.height - self.toolbar.GetHeight()) / 2 + + mdc.SetFont(self.fontSmall) + + wlabel, hlabel = mdc.GetTextExtent(self.toolbar.hoverLabel) + + self.thoverx = self.toolbar.GetWidth() + self.padding + self.thovery = (rect.height - hlabel) / 2 + self.thoverw = wlabel + + self.browserBoxX = self.thoverx + bEditBoxWidth, bEditBoxHeight = self.BrowserSearchBox.GetSize() + self.browserBoxY = (rect.height - bEditBoxHeight) / 2 + + self.bEditBoxWidth = rect.width - self.browserBoxX - self.padding + + def DrawItem(self, mdc): + rect = self.GetRect() + + windowColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW) + textColor = colorUtils.GetSuitableColor(windowColor, 1) + sepColor = colorUtils.GetSuitableColor(windowColor, 0.2) + + mdc.SetTextForeground(textColor) + + self.UpdateElementsPos(mdc) + self.BrowserSearchBox.SetPosition((self.browserBoxX, self.browserBoxY)) + self.BrowserSearchBox.SetSize(wx.Size(self.bEditBoxWidth, -1)) + + self.toolbar.SetPosition((self.toolbarx, self.toolbary)) + mdc.SetFont(self.fontSmall) + mdc.DrawText(self.toolbar.hoverLabel, self.thoverx, self.thovery) + mdc.SetPen(wx.Pen(sepColor, 1)) + mdc.DrawLine(0, rect.height - 1, rect.width, rect.height - 1) + + def RenderBackground(self): + rect = self.GetRect() + + windowColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW) + + sFactor = 0.1 + + shipGroupsFilter = getattr(self.shipBrowser, "filterShipsWithNoFits", None) + if shipGroupsFilter: + sFactor = 0.15 + mFactor = 0.25 + else: + mFactor = 0.2 + + eFactor = 0.1 + + if self.bkBitmap: + if self.bkBitmap.eFactor == eFactor and self.bkBitmap.sFactor == sFactor and self.bkBitmap.mFactor == mFactor \ + and rect.width == self.bkBitmap.GetWidth() and rect.height == self.bkBitmap.GetHeight(): + return + else: + del self.bkBitmap + + self.bkBitmap = drawUtils.RenderGradientBar(windowColor, rect.width, rect.height, sFactor, eFactor, mFactor, 2) + + self.bkBitmap.sFactor = sFactor + self.bkBitmap.eFactor = eFactor + self.bkBitmap.mFactor = mFactor + + def gotoStage(self, stage, data=None): + self.shipBrowser.recentFits = False + if stage == 1: + wx.PostEvent(self.Parent, Stage1Selected()) + elif stage == 2: + wx.PostEvent(self.Parent, Stage2Selected(categoryID=data, back=True)) + elif stage == 3: + wx.PostEvent(self.Parent, Stage3Selected(shipID=data)) + elif stage == 4: + self.shipBrowser._activeStage = 4 + wx.PostEvent(self.Parent, SearchSelected(text=data, back=True)) + elif stage == 5: + wx.PostEvent(self.Parent, ImportSelected(fits=data)) + else: + wx.PostEvent(self.Parent, Stage1Selected()) + diff --git a/gui/builtinShipBrowser/pfBitmapButton.py b/gui/builtinShipBrowser/pfBitmapButton.py new file mode 100644 index 000000000..647e22deb --- /dev/null +++ b/gui/builtinShipBrowser/pfBitmapButton.py @@ -0,0 +1,14 @@ +import wx +from wx.lib.buttons import GenBitmapButton + + +class PFGenBitmapButton(GenBitmapButton): + def __init__(self, parent, id, bitmap, pos, size, style): + GenBitmapButton.__init__(self, parent, id, bitmap, pos, size, style) + self.bgcolor = wx.Brush(wx.WHITE) + + def SetBackgroundColour(self, color): + self.bgcolor = wx.Brush(color) + + def GetBackgroundBrush(self, dc): + return self.bgcolor diff --git a/gui/builtinShipBrowser/pfBitmapFrame.py b/gui/builtinShipBrowser/pfBitmapFrame.py new file mode 100644 index 000000000..e05e643fc --- /dev/null +++ b/gui/builtinShipBrowser/pfBitmapFrame.py @@ -0,0 +1,59 @@ +import wx + + +class PFBitmapFrame(wx.Frame): + def __init__(self, parent, pos, bitmap): + wx.Frame.__init__(self, parent, id=wx.ID_ANY, title=wx.EmptyString, pos=pos, size=wx.DefaultSize, + style=wx.NO_BORDER | wx.FRAME_NO_TASKBAR | wx.STAY_ON_TOP) + img = bitmap.ConvertToImage() + img = img.ConvertToGreyscale() + bitmap = wx.BitmapFromImage(img) + self.bitmap = bitmap + self.SetSize((bitmap.GetWidth(), bitmap.GetHeight())) + self.Bind(wx.EVT_PAINT, self.OnWindowPaint) + self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnWindowEraseBk) + self.Bind(wx.EVT_TIMER, self.OnTimer) + + self.timer = wx.Timer(self, wx.ID_ANY) + self.direction = 1 + self.transp = 0 + self.SetSize((bitmap.GetWidth(), bitmap.GetHeight())) + + self.SetTransparent(0) + self.Refresh() + + def OnTimer(self, event): + self.transp += 20 * self.direction + if self.transp > 200: + self.transp = 200 + self.timer.Stop() + if self.transp < 0: + self.transp = 0 + self.timer.Stop() + wx.Frame.Show(self, False) + self.Destroy() + return + self.SetTransparent(self.transp) + + def Show(self, showWnd=True): + if showWnd: + wx.Frame.Show(self, showWnd) + self.Parent.SetFocus() + self.direction = 1 + self.timer.Start(5) + else: + self.direction = -1 + self.timer.Start(5) + + def OnWindowEraseBk(self, event): + pass + + def OnWindowPaint(self, event): + rect = self.GetRect() + canvas = wx.EmptyBitmap(rect.width, rect.height) + mdc = wx.BufferedPaintDC(self) + mdc.SelectObject(canvas) + mdc.DrawBitmap(self.bitmap, 0, 0) + mdc.SetPen(wx.Pen("#000000", width=1)) + mdc.SetBrush(wx.TRANSPARENT_BRUSH) + mdc.DrawRectangle(0, 0, rect.width, rect.height) diff --git a/gui/PFListPane.py b/gui/builtinShipBrowser/pfListPane.py similarity index 100% rename from gui/PFListPane.py rename to gui/builtinShipBrowser/pfListPane.py diff --git a/gui/builtinShipBrowser/pfStaticText.py b/gui/builtinShipBrowser/pfStaticText.py new file mode 100644 index 000000000..76640e3de --- /dev/null +++ b/gui/builtinShipBrowser/pfStaticText.py @@ -0,0 +1,23 @@ +# coding: utf-8 + +import wx +from logbook import Logger + +pyfalog = Logger(__name__) + + +class PFStaticText(wx.Panel): + def __init__(self, parent, label=wx.EmptyString): + wx.Panel.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=parent.GetSize()) + self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)) + + mainSizer = wx.BoxSizer(wx.VERTICAL) + text = wx.StaticText(self, wx.ID_ANY, label, wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_CENTRE) + text.Wrap(-1) + mainSizer.Add(text, 1, wx.ALL, 10) + self.SetSizer(mainSizer) + self.Layout() + + @staticmethod + def GetType(): + return -1 \ No newline at end of file diff --git a/gui/builtinShipBrowser/pfWidgetContainer.py b/gui/builtinShipBrowser/pfWidgetContainer.py new file mode 100644 index 000000000..305bd6385 --- /dev/null +++ b/gui/builtinShipBrowser/pfWidgetContainer.py @@ -0,0 +1,35 @@ +from gui.builtinShipBrowser.pfListPane import PFListPane +import gui.mainFrame +import gui.utils.animUtils as animUtils + + +class PFWidgetsContainer(PFListPane): + def __init__(self, parent): + PFListPane.__init__(self, parent) + + self.anim = animUtils.LoadAnimation(self, label="", size=(100, 12)) + self.anim.Stop() + self.anim.Show(False) + + def ShowLoading(self, mode=True): + if mode: + aweight, aheight = self.anim.GetSize() + cweight, cheight = self.GetSize() + ax = (cweight - aweight) / 2 + ay = (cheight - aheight) / 2 + self.anim.SetPosition((ax, ay)) + self.anim.Show() + self.anim.Play() + else: + self.anim.Stop() + self.anim.Show(False) + + def IsWidgetSelectedByContext(self, widget): + mainFrame = gui.mainFrame.MainFrame.getInstance() + stage = self.Parent.GetActiveStage() + fit = mainFrame.getActiveFit() + if stage == 3 or stage == 4: + if self._wList[widget].GetType() == 3: + if fit == self._wList[widget].fitID: + return True + return False diff --git a/gui/builtinShipBrowser/raceSelector.py b/gui/builtinShipBrowser/raceSelector.py new file mode 100644 index 000000000..d045eb8d2 --- /dev/null +++ b/gui/builtinShipBrowser/raceSelector.py @@ -0,0 +1,271 @@ +# coding: utf-8 + +import wx +from logbook import Logger + +import gui.utils.animEffects as animEffects +import gui.utils.colorUtils as colorUtils +import gui.utils.drawUtils as drawUtils +from events import * +from gui.bitmapLoader 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.BitmapFromImage(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.StockCursor(wx.CURSOR_HAND)) + else: + self.SetCursor(wx.StockCursor(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.GetSuitableColor(windowColor, 0.1) + sepColor = colorUtils.GetSuitableColor(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 = wx.ImageFromBitmap(raceBmp) + 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.BitmapFromImage(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.StockCursor(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() + diff --git a/gui/sfBrowserItem.py b/gui/builtinShipBrowser/sfBrowserItem.py similarity index 100% rename from gui/sfBrowserItem.py rename to gui/builtinShipBrowser/sfBrowserItem.py diff --git a/gui/builtinShipBrowser/shipItem.py b/gui/builtinShipBrowser/shipItem.py new file mode 100644 index 000000000..39c6e7589 --- /dev/null +++ b/gui/builtinShipBrowser/shipItem.py @@ -0,0 +1,285 @@ +import re + +import wx +from logbook import Logger + +import gui.builtinShipBrowser.sfBrowserItem as SFItem +import gui.mainFrame +import gui.utils.colorUtils as colorUtils +import gui.utils.drawUtils as drawUtils +import gui.utils.fonts as fonts +from events import * +from gui.bitmapLoader import BitmapLoader +from gui.contextMenu import ContextMenu +from service.fit import Fit +from service.market import Market + +pyfalog = Logger(__name__) + + +class ShipItem(SFItem.SFBrowserItem): + def __init__(self, parent, shipID=None, shipFittingInfo=("Test", "TestTrait", 2), itemData=None, + id=wx.ID_ANY, pos=wx.DefaultPosition, + size=(0, 40), style=0): + SFItem.SFBrowserItem.__init__(self, parent, size=size) + + self.mainFrame = gui.mainFrame.MainFrame.getInstance() + + self._itemData = itemData + + self.shipRace = itemData + + self.shipID = shipID + + self.fontBig = wx.Font(fonts.BIG, wx.SWISS, wx.NORMAL, wx.BOLD) + self.fontNormal = wx.Font(fonts.NORMAL, wx.SWISS, wx.NORMAL, wx.NORMAL) + self.fontSmall = wx.Font(fonts.SMALL, wx.SWISS, wx.NORMAL, wx.NORMAL) + + self.shipBmp = None + if shipID: + self.shipBmp = BitmapLoader.getBitmap(str(shipID), "renders") + if not self.shipBmp: + self.shipBmp = BitmapLoader.getBitmap("ship_no_image_big", "gui") + + self.shipFittingInfo = shipFittingInfo + self.shipName, self.shipTrait, self.shipFits = shipFittingInfo + self.shipTrait = re.sub("<.*?>", " ", self.shipTrait) + + self.newBmp = BitmapLoader.getBitmap("fit_add_small", "gui") + self.acceptBmp = BitmapLoader.getBitmap("faccept_small", "gui") + + self.shipEffBk = BitmapLoader.getBitmap("fshipbk_big", "gui") + + img = wx.ImageFromBitmap(self.shipEffBk) + img = img.Mirror(False) + self.shipEffBkMirrored = wx.BitmapFromImage(img) + + self.raceBmp = BitmapLoader.getBitmap("race_%s_small" % self.shipRace, "gui") + + if not self.raceBmp: + self.raceBmp = BitmapLoader.getBitmap("fit_delete_small", "gui") + + self.raceDropShadowBmp = drawUtils.CreateDropShadowBitmap(self.raceBmp, 0.2) + + sFit = Fit.getInstance() + if self.shipTrait and sFit.serviceFittingOptions["showShipBrowserTooltip"]: + self.SetToolTip(wx.ToolTip(self.shipTrait)) + + self.shipBrowser = self.Parent.Parent + + self.editWidth = 150 + self.padding = 4 + + self.tcFitName = wx.TextCtrl(self, wx.ID_ANY, "%s fit" % self.shipName, wx.DefaultPosition, (120, -1), + wx.TE_PROCESS_ENTER) + self.tcFitName.Show(False) + + self.newBtn = self.toolbar.AddButton(self.newBmp, "New", self.newBtnCB) + + self.tcFitName.Bind(wx.EVT_TEXT_ENTER, self.createNewFit) + self.tcFitName.Bind(wx.EVT_KILL_FOCUS, self.editLostFocus) + self.tcFitName.Bind(wx.EVT_KEY_DOWN, self.editCheckEsc) + + self.animTimerId = wx.NewId() + + self.animTimer = wx.Timer(self, self.animTimerId) + self.animStep = 0 + self.animPeriod = 10 + self.animDuration = 100 + + self.Bind(wx.EVT_CONTEXT_MENU, self.OnShowPopup) + + self.marketInstance = Market.getInstance() + self.baseItem = self.marketInstance.getItem(self.shipID) + + # ===================================================================== + # DISABLED - it will be added as an option in PREFERENCES + + self.animCount = 0 + + # if self.shipBrowser.GetActiveStage() != 4 and self.shipBrowser.GetLastStage() !=2: + # self.Bind(wx.EVT_TIMER, self.OnTimer) + # self.animTimer.Start(self.animPeriod) + # else: + # self.animCount = 0 + # ===================================================================== + + def OnShowPopup(self, event): + pos = event.GetPosition() + pos = self.ScreenToClient(pos) + contexts = [("baseShip", "Ship Basic")] + menu = ContextMenu.getMenu(self.baseItem, *contexts) + self.PopupMenu(menu, pos) + + def OnTimer(self, event): + step = self.OUT_QUAD(self.animStep, 0, 10, self.animDuration) + self.animCount = 10 - step + self.animStep += self.animPeriod + if self.animStep > self.animDuration or self.animCount < 0: + self.animCount = 0 + self.animTimer.Stop() + self.Refresh() + + @staticmethod + def OUT_QUAD(t, b, c, d): + t = float(t) + b = float(b) + c = float(c) + d = float(d) + + t /= d + + return -c * t * (t - 2) + b + + def GetType(self): + return 2 + + def MouseLeftUp(self, event): + if self.tcFitName.IsShown(): + self.tcFitName.Show(False) + self.newBtn.SetBitmap(self.newBmp) + self.Refresh() + else: + shipName, shipTrait, fittings = self.shipFittingInfo + if fittings > 0: + wx.PostEvent(self.shipBrowser, Stage3Selected(shipID=self.shipID, back=True)) + else: + self.newBtnCB() + + def newBtnCB(self): + if self.tcFitName.IsShown(): + self.tcFitName.Show(False) + self.createNewFit() + else: + self.tcFitName.SetValue("%s fit" % self.shipName) + self.tcFitName.Show() + + self.tcFitName.SetFocus() + self.tcFitName.SelectAll() + + self.newBtn.SetBitmap(self.acceptBmp) + + self.Refresh() + + def editLostFocus(self, event): + self.tcFitName.Show(False) + self.newBtn.SetBitmap(self.newBmp) + self.Refresh() + + def editCheckEsc(self, event): + if event.GetKeyCode() == wx.WXK_ESCAPE: + self.tcFitName.Show(False) + else: + event.Skip() + + def createNewFit(self, event=None): + self.tcFitName.Show(False) + + sFit = Fit.getInstance() + fitID = sFit.newFit(self.shipID, self.tcFitName.GetValue()) + + wx.PostEvent(self.shipBrowser, Stage3Selected(shipID=self.shipID, back=False)) + wx.PostEvent(self.mainFrame, FitSelected(fitID=fitID)) + + def UpdateElementsPos(self, mdc): + rect = self.GetRect() + + self.toolbarx = rect.width - self.toolbar.GetWidth() - self.padding + self.toolbary = (rect.height - self.toolbar.GetHeight()) / 2 + + self.toolbarx += self.animCount + + self.shipEffx = self.padding + (rect.height - self.shipEffBk.GetWidth()) / 2 + self.shipEffy = (rect.height - self.shipEffBk.GetHeight()) / 2 + + self.shipEffx -= self.animCount + + self.shipBmpx = self.padding + (rect.height - self.shipBmp.GetWidth()) / 2 + self.shipBmpy = (rect.height - self.shipBmp.GetHeight()) / 2 + + self.shipBmpx -= self.animCount + + self.raceBmpx = self.shipEffx + self.shipEffBk.GetWidth() + self.padding + self.raceBmpy = (rect.height - self.raceBmp.GetHeight()) / 2 + + self.textStartx = self.raceBmpx + self.raceBmp.GetWidth() + self.padding + + self.shipNamey = (rect.height - self.shipBmp.GetHeight()) / 2 + + shipName, shipTrait, fittings = self.shipFittingInfo + + mdc.SetFont(self.fontBig) + wtext, htext = mdc.GetTextExtent(shipName) + + self.fittingsy = self.shipNamey + htext + + mdc.SetFont(self.fontSmall) + + wlabel, hlabel = mdc.GetTextExtent(self.toolbar.hoverLabel) + + self.thoverx = self.toolbarx - self.padding - wlabel + self.thovery = (rect.height - hlabel) / 2 + self.thoverw = wlabel + + def DrawItem(self, mdc): + # rect = self.GetRect() + + windowColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW) + textColor = colorUtils.GetSuitableColor(windowColor, 1) + + mdc.SetTextForeground(textColor) + + self.UpdateElementsPos(mdc) + + self.toolbar.SetPosition((self.toolbarx, self.toolbary)) + + if self.GetState() & SFItem.SB_ITEM_HIGHLIGHTED: + shipEffBk = self.shipEffBkMirrored + else: + shipEffBk = self.shipEffBk + + mdc.DrawBitmap(shipEffBk, self.shipEffx, self.shipEffy, 0) + + mdc.DrawBitmap(self.shipBmp, self.shipBmpx, self.shipBmpy, 0) + + mdc.DrawBitmap(self.raceDropShadowBmp, self.raceBmpx + 1, self.raceBmpy + 1) + mdc.DrawBitmap(self.raceBmp, self.raceBmpx, self.raceBmpy) + + shipName, shipTrait, fittings = self.shipFittingInfo + + if fittings < 1: + fformat = "No fits" + elif fittings == 1: + fformat = "%d fit" + else: + fformat = "%d fits" + + mdc.SetFont(self.fontNormal) + mdc.DrawText(fformat % fittings if fittings > 0 else fformat, self.textStartx, self.fittingsy) + + mdc.SetFont(self.fontSmall) + mdc.DrawText(self.toolbar.hoverLabel, self.thoverx, self.thovery) + + mdc.SetFont(self.fontBig) + + psname = drawUtils.GetPartialText(mdc, shipName, + self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw) + + mdc.DrawText(psname, self.textStartx, self.shipNamey) + + if self.tcFitName.IsShown(): + self.AdjustControlSizePos(self.tcFitName, self.textStartx, self.toolbarx - self.editWidth - self.padding) + + def AdjustControlSizePos(self, editCtl, start, end): + fnEditSize = editCtl.GetSize() + wSize = self.GetSize() + fnEditPosX = end + fnEditPosY = (wSize.height - fnEditSize.height) / 2 + if fnEditPosX < start: + editCtl.SetSize((self.editWidth + fnEditPosX - start, -1)) + editCtl.SetPosition((start, fnEditPosY)) + else: + editCtl.SetSize((self.editWidth, -1)) + editCtl.SetPosition((fnEditPosX, fnEditPosY)) + + diff --git a/gui/builtinViews/fittingView.py b/gui/builtinViews/fittingView.py index 41d3df87f..8358576ce 100644 --- a/gui/builtinViews/fittingView.py +++ b/gui/builtinViews/fittingView.py @@ -25,7 +25,7 @@ import gui.mainFrame import gui.marketBrowser import gui.display as d from gui.contextMenu import ContextMenu -import gui.shipBrowser +from gui.builtinShipBrowser.events import * import gui.multiSwitch from eos.saveddata.mode import Mode from eos.saveddata.module import Module, Slot, Rack @@ -50,7 +50,7 @@ class FitSpawner(gui.multiSwitch.TabSpawner): def __init__(self, multiSwitch): self.multiSwitch = multiSwitch self.mainFrame = mainFrame = gui.mainFrame.MainFrame.getInstance() - mainFrame.Bind(gui.shipBrowser.EVT_FIT_SELECTED, self.fitSelected) + mainFrame.Bind(EVT_FIT_SELECTED, self.fitSelected) self.multiSwitch.tabsContainer.handleDrag = self.handleDrag def fitSelected(self, event): @@ -138,8 +138,8 @@ class FittingView(d.Display): self.Show(False) self.parent = parent self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged) - self.mainFrame.Bind(gui.shipBrowser.EVT_FIT_RENAMED, self.fitRenamed) - self.mainFrame.Bind(gui.shipBrowser.EVT_FIT_REMOVED, self.fitRemoved) + self.mainFrame.Bind(EVT_FIT_RENAMED, self.fitRenamed) + self.mainFrame.Bind(EVT_FIT_REMOVED, self.fitRemoved) self.mainFrame.Bind(gui.marketBrowser.ITEM_SELECTED, self.appendItem) self.Bind(wx.EVT_LEFT_DCLICK, self.removeItem) @@ -210,13 +210,13 @@ class FittingView(d.Display): def handleDrag(self, type, fitID): # Those are drags coming from pyfa sources, NOT builtin wx drags if type == "fit": - wx.PostEvent(self.mainFrame, gui.shipBrowser.FitSelected(fitID=fitID)) + wx.PostEvent(self.mainFrame, FitSelected(fitID=fitID)) def Destroy(self): self.parent.Unbind(EVT_NOTEBOOK_PAGE_CHANGED, handler=self.pageChanged) self.mainFrame.Unbind(GE.FIT_CHANGED, handler=self.fitChanged) - self.mainFrame.Unbind(gui.shipBrowser.EVT_FIT_RENAMED, handler=self.fitRenamed) - self.mainFrame.Unbind(gui.shipBrowser.EVT_FIT_REMOVED, handler=self.fitRemoved) + self.mainFrame.Unbind(EVT_FIT_RENAMED, handler=self.fitRenamed) + self.mainFrame.Unbind(EVT_FIT_REMOVED, handler=self.fitRemoved) self.mainFrame.Unbind(gui.marketBrowser.ITEM_SELECTED, handler=self.appendItem) d.Display.Destroy(self) diff --git a/gui/mainFrame.py b/gui/mainFrame.py index ff86bc433..d61a833f3 100644 --- a/gui/mainFrame.py +++ b/gui/mainFrame.py @@ -48,7 +48,8 @@ from gui.additionsPane import AdditionsPane from gui.marketBrowser import MarketBrowser, ItemSelected from gui.multiSwitch import MultiSwitch from gui.statsPane import StatsPane -from gui.shipBrowser import ShipBrowser, FitSelected, ImportSelected, Stage3Selected +from gui.shipBrowser import ShipBrowser +from gui.builtinShipBrowser.events import FitSelected, ImportSelected, Stage3Selected from gui.characterEditor import CharacterEditor, SaveCharacterAs from gui.characterSelection import CharacterSelection from gui.patternEditor import DmgPatternEditorDlg diff --git a/gui/shipBrowser.py b/gui/shipBrowser.py index b3c4d6cd2..442f3bcde 100644 --- a/gui/shipBrowser.py +++ b/gui/shipBrowser.py @@ -1,589 +1,24 @@ -# coding: utf-8 - -import re -import time - # noinspection PyPackageRequirements import wx +from logbook import Logger # noinspection PyPackageRequirements -from wx.lib.buttons import GenBitmapButton +import gui.globalEvents as GE +import gui.mainFrame +from gui.builtinShipBrowser.categoryItem import CategoryItem +from gui.builtinShipBrowser.fitItem import FitItem +from gui.builtinShipBrowser.shipItem import ShipItem from service.fit import Fit from service.market import Market -import gui.mainFrame -import gui.utils.fonts as fonts -import gui.globalEvents as GE -import gui.sfBrowserItem as SFItem -import gui.utils.colorUtils as colorUtils -import gui.utils.drawUtils as drawUtils -import gui.utils.animUtils as animUtils -import gui.utils.animEffects as animEffects -from gui.PFListPane import PFListPane -from gui.contextMenu import ContextMenu -from gui.bitmapLoader import BitmapLoader -from logbook import Logger + +from gui.builtinShipBrowser.events import * +from gui.builtinShipBrowser.pfWidgetContainer import PFWidgetsContainer +from gui.builtinShipBrowser.navigationPanel import NavigationPanel +from gui.builtinShipBrowser.raceSelector import RaceSelector +from gui.builtinShipBrowser.pfStaticText import PFStaticText + pyfalog = Logger(__name__) -FitRenamed, EVT_FIT_RENAMED = wx.lib.newevent.NewEvent() -FitSelected, EVT_FIT_SELECTED = wx.lib.newevent.NewEvent() -FitRemoved, EVT_FIT_REMOVED = wx.lib.newevent.NewEvent() - -BoosterListUpdated, BOOSTER_LIST_UPDATED = wx.lib.newevent.NewEvent() - -Stage1Selected, EVT_SB_STAGE1_SEL = wx.lib.newevent.NewEvent() -Stage2Selected, EVT_SB_STAGE2_SEL = wx.lib.newevent.NewEvent() -Stage3Selected, EVT_SB_STAGE3_SEL = wx.lib.newevent.NewEvent() -SearchSelected, EVT_SB_SEARCH_SEL = wx.lib.newevent.NewEvent() -ImportSelected, EVT_SB_IMPORT_SEL = wx.lib.newevent.NewEvent() - - -class PFWidgetsContainer(PFListPane): - def __init__(self, parent): - PFListPane.__init__(self, parent) - - self.anim = animUtils.LoadAnimation(self, label="", size=(100, 12)) - self.anim.Stop() - self.anim.Show(False) - - def ShowLoading(self, mode=True): - if mode: - aweight, aheight = self.anim.GetSize() - cweight, cheight = self.GetSize() - ax = (cweight - aweight) / 2 - ay = (cheight - aheight) / 2 - self.anim.SetPosition((ax, ay)) - self.anim.Show() - self.anim.Play() - else: - self.anim.Stop() - self.anim.Show(False) - - def IsWidgetSelectedByContext(self, widget): - mainFrame = gui.mainFrame.MainFrame.getInstance() - stage = self.Parent.GetActiveStage() - fit = mainFrame.getActiveFit() - if stage == 3 or stage == 4: - if self._wList[widget].GetType() == 3: - if fit == self._wList[widget].fitID: - return True - return False - - -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.BitmapFromImage(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.StockCursor(wx.CURSOR_HAND)) - else: - self.SetCursor(wx.StockCursor(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.GetSuitableColor(windowColor, 0.1) - sepColor = colorUtils.GetSuitableColor(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 = wx.ImageFromBitmap(raceBmp) - 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.BitmapFromImage(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.StockCursor(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() - - -class NavigationPanel(SFItem.SFBrowserItem): - def __init__(self, parent, size=(-1, 24)): - SFItem.SFBrowserItem.__init__(self, parent, size=size) - - self.rewBmpH = BitmapLoader.getBitmap("frewind_small", "gui") - self.forwBmp = BitmapLoader.getBitmap("fforward_small", "gui") - self.searchBmpH = BitmapLoader.getBitmap("fsearch_small", "gui") - self.newBmpH = BitmapLoader.getBitmap("fit_add_small", "gui") - self.resetBmpH = BitmapLoader.getBitmap("freset_small", "gui") - self.switchBmpH = BitmapLoader.getBitmap("fit_switch_view_mode_small", "gui") - self.recentBmpH = BitmapLoader.getBitmap("frecent_small", "gui") - - switchImg = BitmapLoader.getImage("fit_switch_view_mode_small", "gui") - switchImg = switchImg.AdjustChannels(1, 1, 1, 0.4) - self.switchBmpD = wx.BitmapFromImage(switchImg) - - recentImg = BitmapLoader.getImage("frecent_small", "gui") - recentImg = recentImg.AdjustChannels(1, 1, 1, 0.4) - self.recentBmpD = wx.BitmapFromImage(recentImg) - - self.resetBmp = self.AdjustChannels(self.resetBmpH) - self.rewBmp = self.AdjustChannels(self.rewBmpH) - self.searchBmp = self.AdjustChannels(self.searchBmpH) - self.switchBmp = self.AdjustChannels(self.switchBmpH) - self.recentBmp = self.AdjustChannels(self.recentBmpH) - self.newBmp = self.AdjustChannels(self.newBmpH) - - self.toolbar.AddButton(self.resetBmp, "Ship groups", clickCallback=self.OnHistoryReset, - hoverBitmap=self.resetBmpH) - self.toolbar.AddButton(self.rewBmp, "Back", clickCallback=self.OnHistoryBack, hoverBitmap=self.rewBmpH) - self.btnNew = self.toolbar.AddButton(self.newBmp, "New fitting", clickCallback=self.OnNewFitting, - hoverBitmap=self.newBmpH, show=False) - self.btnSwitch = self.toolbar.AddButton(self.switchBmpD, "Hide empty ship groups", - clickCallback=self.ToggleEmptyGroupsView, hoverBitmap=self.switchBmpH, - show=False) - self.btnRecent = self.toolbar.AddButton(self.recentBmpD, "Recent Fits", - clickCallback=self.ToggleRecentShips, hoverBitmap=self.recentBmpH, - show=True) - - modifier = "CTRL" if 'wxMac' not in wx.PlatformInfo else "CMD" - self.toolbar.AddButton(self.searchBmp, "Search fittings ({}+F)".format(modifier), clickCallback=self.ToggleSearchBox, - hoverBitmap=self.searchBmpH) - - self.padding = 4 - self.lastSearch = "" - self.recentSearches = [] # not used? - self.inSearch = False - - self.fontSmall = wx.Font(fonts.SMALL, wx.SWISS, wx.NORMAL, wx.NORMAL) - w, h = size - self.BrowserSearchBox = wx.TextCtrl(self, wx.ID_ANY, "", wx.DefaultPosition, - (-1, h - 2 if 'wxGTK' in wx.PlatformInfo else -1), - wx.TE_PROCESS_ENTER | (wx.BORDER_NONE if 'wxGTK' in wx.PlatformInfo else 0)) - self.BrowserSearchBox.Show(False) - - self.BrowserSearchBox.Bind(wx.EVT_TEXT_ENTER, self.OnBrowserSearchBoxEnter) - self.BrowserSearchBox.Bind(wx.EVT_KILL_FOCUS, self.OnBrowserSearchBoxLostFocus) - self.BrowserSearchBox.Bind(wx.EVT_KEY_DOWN, self.OnBrowserSearchBoxEsc) - self.BrowserSearchBox.Bind(wx.EVT_TEXT, self.OnScheduleSearch) - - self.SetMinSize(size) - self.shipBrowser = self.Parent - self.mainFrame = gui.mainFrame.MainFrame.getInstance() - - self.Bind(wx.EVT_SIZE, self.OnResize) - - def OnScheduleSearch(self, event): - search = self.BrowserSearchBox.GetValue() - # Make sure we do not count wildcard as search symbol - realsearch = search.replace("*", "") - if len(realsearch) >= 3: - self.lastSearch = search - wx.PostEvent(self.shipBrowser, SearchSelected(text=search, back=False)) - - def ToggleSearchBox(self): - if self.BrowserSearchBox.IsShown(): - self.BrowserSearchBox.Show(False) - else: - self.BrowserSearchBox.Show(True) - self.BrowserSearchBox.ChangeValue("") - self.BrowserSearchBox.SetFocus() - - def OnBrowserSearchBoxEnter(self, event): - self.OnBrowserSearchBoxLostFocus(None) - - def OnBrowserSearchBoxLostFocus(self, event): - self.BrowserSearchBox.Show(False) - - def OnBrowserSearchBoxEsc(self, event): - if event.GetKeyCode() == wx.WXK_ESCAPE: - self.BrowserSearchBox.Show(False) - else: - event.Skip() - - def OnResize(self, event): - self.Refresh() - - def ToggleRecentShips(self, bool=None, emitEvent=True): - # this is so janky. Need to revaluate pretty much entire ship browser. >.< - toggle = bool if bool is not None else not self.shipBrowser.recentFits - - if not toggle: - self.shipBrowser.recentFits = False - self.btnRecent.label = "Recent Fits" - self.btnRecent.normalBmp = self.recentBmpD - - if emitEvent: - wx.PostEvent(self.shipBrowser, Stage1Selected()) - else: - self.shipBrowser.recentFits = True - self.btnRecent.label = "Hide Recent Fits" - self.btnRecent.normalBmp = self.recentBmp - - if emitEvent: - sFit = Fit.getInstance() - fits = sFit.getRecentFits() - wx.PostEvent(self.shipBrowser, ImportSelected(fits=fits, back=True, recent=True)) - - def ToggleEmptyGroupsView(self): - if self.shipBrowser.filterShipsWithNoFits: - self.shipBrowser.filterShipsWithNoFits = False - self.btnSwitch.label = "Hide empty ship groups" - self.btnSwitch.normalBmp = self.switchBmpD - else: - self.shipBrowser.filterShipsWithNoFits = True - self.btnSwitch.label = "Show empty ship groups" - self.btnSwitch.normalBmp = self.switchBmp - - stage = self.shipBrowser.GetActiveStage() - - if stage == 1: - wx.PostEvent(self.shipBrowser, Stage1Selected()) - elif stage == 2: - categoryID = self.shipBrowser.GetStageData(stage) - wx.PostEvent(self.shipBrowser, Stage2Selected(categoryID=categoryID, back=True)) - - def ShowNewFitButton(self, show): - self.btnNew.Show(show) - self.Refresh() - - def ShowSwitchEmptyGroupsButton(self, show): - self.btnSwitch.Show(show) - self.Refresh() - - def OnNewFitting(self): - stage = self.Parent.GetActiveStage() - if stage == 3: - shipID = self.Parent.GetStageData(stage) - shipName = self.Parent.GetStage3ShipName() - sFit = Fit.getInstance() - fitID = sFit.newFit(shipID, "%s fit" % shipName) - self.shipBrowser.fitIDMustEditName = fitID - wx.PostEvent(self.Parent, Stage3Selected(shipID=shipID)) - wx.PostEvent(self.mainFrame, FitSelected(fitID=fitID)) - - def OnHistoryReset(self): - self.ToggleRecentShips(False, False) - if self.shipBrowser.browseHist: - self.shipBrowser.browseHist = [] - self.gotoStage(1, 0) - - def OnHistoryBack(self): - self.ToggleRecentShips(False, False) - if len(self.shipBrowser.browseHist) > 0: - stage, data = self.shipBrowser.browseHist.pop() - self.gotoStage(stage, data) - - @staticmethod - def AdjustChannels(bitmap): - img = wx.ImageFromBitmap(bitmap) - img = img.AdjustChannels(1.05, 1.05, 1.05, 1) - return wx.BitmapFromImage(img) - - def UpdateElementsPos(self, mdc): - rect = self.GetRect() - - self.toolbarx = self.padding - self.toolbary = (rect.height - self.toolbar.GetHeight()) / 2 - - mdc.SetFont(self.fontSmall) - - wlabel, hlabel = mdc.GetTextExtent(self.toolbar.hoverLabel) - - self.thoverx = self.toolbar.GetWidth() + self.padding - self.thovery = (rect.height - hlabel) / 2 - self.thoverw = wlabel - - self.browserBoxX = self.thoverx - bEditBoxWidth, bEditBoxHeight = self.BrowserSearchBox.GetSize() - self.browserBoxY = (rect.height - bEditBoxHeight) / 2 - - self.bEditBoxWidth = rect.width - self.browserBoxX - self.padding - - def DrawItem(self, mdc): - rect = self.GetRect() - - windowColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW) - textColor = colorUtils.GetSuitableColor(windowColor, 1) - sepColor = colorUtils.GetSuitableColor(windowColor, 0.2) - - mdc.SetTextForeground(textColor) - - self.UpdateElementsPos(mdc) - self.BrowserSearchBox.SetPosition((self.browserBoxX, self.browserBoxY)) - self.BrowserSearchBox.SetSize(wx.Size(self.bEditBoxWidth, -1)) - - self.toolbar.SetPosition((self.toolbarx, self.toolbary)) - mdc.SetFont(self.fontSmall) - mdc.DrawText(self.toolbar.hoverLabel, self.thoverx, self.thovery) - mdc.SetPen(wx.Pen(sepColor, 1)) - mdc.DrawLine(0, rect.height - 1, rect.width, rect.height - 1) - - def RenderBackground(self): - rect = self.GetRect() - - windowColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW) - - sFactor = 0.1 - - shipGroupsFilter = getattr(self.shipBrowser, "filterShipsWithNoFits", None) - if shipGroupsFilter: - sFactor = 0.15 - mFactor = 0.25 - else: - mFactor = 0.2 - - eFactor = 0.1 - - if self.bkBitmap: - if self.bkBitmap.eFactor == eFactor and self.bkBitmap.sFactor == sFactor and self.bkBitmap.mFactor == mFactor \ - and rect.width == self.bkBitmap.GetWidth() and rect.height == self.bkBitmap.GetHeight(): - return - else: - del self.bkBitmap - - self.bkBitmap = drawUtils.RenderGradientBar(windowColor, rect.width, rect.height, sFactor, eFactor, mFactor, 2) - - self.bkBitmap.sFactor = sFactor - self.bkBitmap.eFactor = eFactor - self.bkBitmap.mFactor = mFactor - - def gotoStage(self, stage, data=None): - self.shipBrowser.recentFits = False - if stage == 1: - wx.PostEvent(self.Parent, Stage1Selected()) - elif stage == 2: - wx.PostEvent(self.Parent, Stage2Selected(categoryID=data, back=True)) - elif stage == 3: - wx.PostEvent(self.Parent, Stage3Selected(shipID=data)) - elif stage == 4: - self.shipBrowser._activeStage = 4 - wx.PostEvent(self.Parent, SearchSelected(text=data, back=True)) - elif stage == 5: - wx.PostEvent(self.Parent, ImportSelected(fits=data)) - else: - wx.PostEvent(self.Parent, Stage1Selected()) - class ShipBrowser(wx.Panel): def __init__(self, parent): @@ -1006,1055 +441,5 @@ class ShipBrowser(wx.Panel): self.Layout() -class PFStaticText(wx.Panel): - def __init__(self, parent, label=wx.EmptyString): - wx.Panel.__init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=parent.GetSize()) - self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW)) - mainSizer = wx.BoxSizer(wx.VERTICAL) - text = wx.StaticText(self, wx.ID_ANY, label, wx.DefaultPosition, wx.DefaultSize, wx.ALIGN_CENTRE) - text.Wrap(-1) - mainSizer.Add(text, 1, wx.ALL, 10) - self.SetSizer(mainSizer) - self.Layout() - @staticmethod - def GetType(): - return -1 - - -class PFGenBitmapButton(GenBitmapButton): - def __init__(self, parent, id, bitmap, pos, size, style): - GenBitmapButton.__init__(self, parent, id, bitmap, pos, size, style) - self.bgcolor = wx.Brush(wx.WHITE) - - def SetBackgroundColour(self, color): - self.bgcolor = wx.Brush(color) - - def GetBackgroundBrush(self, dc): - return self.bgcolor - - -class CategoryItem(SFItem.SFBrowserItem): - def __init__(self, parent, categoryID, fittingInfo, size=(0, 16)): - SFItem.SFBrowserItem.__init__(self, parent, size=size) - - if categoryID: - self.shipBmp = BitmapLoader.getBitmap("ship_small", "gui") - else: - self.shipBmp = wx.EmptyBitmap(16, 16) - - self.dropShadowBitmap = drawUtils.CreateDropShadowBitmap(self.shipBmp, 0.2) - - self.categoryID = categoryID - self.fittingInfo = fittingInfo - self.shipBrowser = self.Parent.Parent - - self.padding = 4 - - self.fontBig = wx.Font(fonts.BIG, wx.SWISS, wx.NORMAL, wx.NORMAL) - - self.animTimerId = wx.NewId() - - self.animTimer = wx.Timer(self, self.animTimerId) - self.animStep = 0 - self.animPeriod = 10 - self.animDuration = 100 - - self.Bind(wx.EVT_TIMER, self.OnTimer) - - # ===================================================================== - # Disabled - it will be added as an option to Preferences - self.animCount = 0 - # self.animTimer.Start(self.animPeriod) - # ===================================================================== - - def OnTimer(self, event): - step = self.OUT_QUAD(self.animStep, 0, 10, self.animDuration) - self.animCount = 10 - step - self.animStep += self.animPeriod - if self.animStep > self.animDuration or self.animCount < 0: - self.animCount = 0 - self.animTimer.Stop() - self.Refresh() - - @staticmethod - def OUT_QUAD(t, b, c, d): - t = float(t) - b = float(b) - c = float(c) - d = float(d) - - t /= d - - return -c * t * (t - 2) + b - - def GetType(self): - return 1 - - def MouseLeftUp(self, event): - - categoryID = self.categoryID - wx.PostEvent(self.shipBrowser, Stage2Selected(categoryID=categoryID, back=False)) - - def UpdateElementsPos(self, mdc): - rect = self.GetRect() - self.shipBmpx = self.padding - self.shipBmpy = (rect.height - self.shipBmp.GetWidth()) / 2 - - self.shipBmpx -= self.animCount - - mdc.SetFont(self.fontBig) - categoryName, fittings = self.fittingInfo - wtext, htext = mdc.GetTextExtent(categoryName) - - self.catx = self.shipBmpx + self.shipBmp.GetWidth() + self.padding - self.caty = (rect.height - htext) / 2 - - def DrawItem(self, mdc): - # rect = self.GetRect() - self.UpdateElementsPos(mdc) - - windowColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW) - textColor = colorUtils.GetSuitableColor(windowColor, 1) - - mdc.SetTextForeground(textColor) - mdc.DrawBitmap(self.dropShadowBitmap, self.shipBmpx + 1, self.shipBmpy + 1) - mdc.DrawBitmap(self.shipBmp, self.shipBmpx, self.shipBmpy, 0) - - mdc.SetFont(self.fontBig) - - categoryName, fittings = self.fittingInfo - - mdc.DrawText(categoryName, self.catx, self.caty) - - -# ============================================================================= -# Waiting for total #fits impl in eos/service -# -# mdc.SetFont(wx.Font(8, wx.SWISS, wx.NORMAL, wx.NORMAL, False)) -# -# if fittings <1: -# fformat = "No fits" -# else: -# if fittings == 1: -# fformat = "%d fit" -# else: -# fformat = "%d fits" -# -# if fittings>0: -# xtext, ytext = mdc.GetTextExtent(fformat % fittings) -# ypos = (rect.height - ytext)/2 -# else: -# xtext, ytext = mdc.GetTextExtent(fformat) -# ypos = (rect.height - ytext)/2 -# ============================================================================= - - -class ShipItem(SFItem.SFBrowserItem): - def __init__(self, parent, shipID=None, shipFittingInfo=("Test", "TestTrait", 2), itemData=None, - id=wx.ID_ANY, pos=wx.DefaultPosition, - size=(0, 40), style=0): - SFItem.SFBrowserItem.__init__(self, parent, size=size) - - self.mainFrame = gui.mainFrame.MainFrame.getInstance() - - self._itemData = itemData - - self.shipRace = itemData - - self.shipID = shipID - - self.fontBig = wx.Font(fonts.BIG, wx.SWISS, wx.NORMAL, wx.BOLD) - self.fontNormal = wx.Font(fonts.NORMAL, wx.SWISS, wx.NORMAL, wx.NORMAL) - self.fontSmall = wx.Font(fonts.SMALL, wx.SWISS, wx.NORMAL, wx.NORMAL) - - self.shipBmp = None - if shipID: - self.shipBmp = BitmapLoader.getBitmap(str(shipID), "renders") - if not self.shipBmp: - self.shipBmp = BitmapLoader.getBitmap("ship_no_image_big", "gui") - - self.shipFittingInfo = shipFittingInfo - self.shipName, self.shipTrait, self.shipFits = shipFittingInfo - self.shipTrait = re.sub("<.*?>", " ", self.shipTrait) - - self.newBmp = BitmapLoader.getBitmap("fit_add_small", "gui") - self.acceptBmp = BitmapLoader.getBitmap("faccept_small", "gui") - - self.shipEffBk = BitmapLoader.getBitmap("fshipbk_big", "gui") - - img = wx.ImageFromBitmap(self.shipEffBk) - img = img.Mirror(False) - self.shipEffBkMirrored = wx.BitmapFromImage(img) - - self.raceBmp = BitmapLoader.getBitmap("race_%s_small" % self.shipRace, "gui") - - if not self.raceBmp: - self.raceBmp = BitmapLoader.getBitmap("fit_delete_small", "gui") - - self.raceDropShadowBmp = drawUtils.CreateDropShadowBitmap(self.raceBmp, 0.2) - - sFit = Fit.getInstance() - if self.shipTrait and sFit.serviceFittingOptions["showShipBrowserTooltip"]: - self.SetToolTip(wx.ToolTip(self.shipTrait)) - - self.shipBrowser = self.Parent.Parent - - self.editWidth = 150 - self.padding = 4 - - self.tcFitName = wx.TextCtrl(self, wx.ID_ANY, "%s fit" % self.shipName, wx.DefaultPosition, (120, -1), - wx.TE_PROCESS_ENTER) - self.tcFitName.Show(False) - - self.newBtn = self.toolbar.AddButton(self.newBmp, "New", self.newBtnCB) - - self.tcFitName.Bind(wx.EVT_TEXT_ENTER, self.createNewFit) - self.tcFitName.Bind(wx.EVT_KILL_FOCUS, self.editLostFocus) - self.tcFitName.Bind(wx.EVT_KEY_DOWN, self.editCheckEsc) - - self.animTimerId = wx.NewId() - - self.animTimer = wx.Timer(self, self.animTimerId) - self.animStep = 0 - self.animPeriod = 10 - self.animDuration = 100 - - self.Bind(wx.EVT_CONTEXT_MENU, self.OnShowPopup) - - self.marketInstance = Market.getInstance() - self.baseItem = self.marketInstance.getItem(self.shipID) - - # ===================================================================== - # DISABLED - it will be added as an option in PREFERENCES - - self.animCount = 0 - - # if self.shipBrowser.GetActiveStage() != 4 and self.shipBrowser.GetLastStage() !=2: - # self.Bind(wx.EVT_TIMER, self.OnTimer) - # self.animTimer.Start(self.animPeriod) - # else: - # self.animCount = 0 - # ===================================================================== - - def OnShowPopup(self, event): - pos = event.GetPosition() - pos = self.ScreenToClient(pos) - contexts = [("baseShip", "Ship Basic")] - menu = ContextMenu.getMenu(self.baseItem, *contexts) - self.PopupMenu(menu, pos) - - def OnTimer(self, event): - step = self.OUT_QUAD(self.animStep, 0, 10, self.animDuration) - self.animCount = 10 - step - self.animStep += self.animPeriod - if self.animStep > self.animDuration or self.animCount < 0: - self.animCount = 0 - self.animTimer.Stop() - self.Refresh() - - @staticmethod - def OUT_QUAD(t, b, c, d): - t = float(t) - b = float(b) - c = float(c) - d = float(d) - - t /= d - - return -c * t * (t - 2) + b - - def GetType(self): - return 2 - - def MouseLeftUp(self, event): - if self.tcFitName.IsShown(): - self.tcFitName.Show(False) - self.newBtn.SetBitmap(self.newBmp) - self.Refresh() - else: - shipName, shipTrait, fittings = self.shipFittingInfo - if fittings > 0: - wx.PostEvent(self.shipBrowser, Stage3Selected(shipID=self.shipID, back=True)) - else: - self.newBtnCB() - - def newBtnCB(self): - if self.tcFitName.IsShown(): - self.tcFitName.Show(False) - self.createNewFit() - else: - self.tcFitName.SetValue("%s fit" % self.shipName) - self.tcFitName.Show() - - self.tcFitName.SetFocus() - self.tcFitName.SelectAll() - - self.newBtn.SetBitmap(self.acceptBmp) - - self.Refresh() - - def editLostFocus(self, event): - self.tcFitName.Show(False) - self.newBtn.SetBitmap(self.newBmp) - self.Refresh() - - def editCheckEsc(self, event): - if event.GetKeyCode() == wx.WXK_ESCAPE: - self.tcFitName.Show(False) - else: - event.Skip() - - def createNewFit(self, event=None): - self.tcFitName.Show(False) - - sFit = Fit.getInstance() - fitID = sFit.newFit(self.shipID, self.tcFitName.GetValue()) - - wx.PostEvent(self.shipBrowser, Stage3Selected(shipID=self.shipID, back=False)) - wx.PostEvent(self.mainFrame, FitSelected(fitID=fitID)) - - def UpdateElementsPos(self, mdc): - rect = self.GetRect() - - self.toolbarx = rect.width - self.toolbar.GetWidth() - self.padding - self.toolbary = (rect.height - self.toolbar.GetHeight()) / 2 - - self.toolbarx += self.animCount - - self.shipEffx = self.padding + (rect.height - self.shipEffBk.GetWidth()) / 2 - self.shipEffy = (rect.height - self.shipEffBk.GetHeight()) / 2 - - self.shipEffx -= self.animCount - - self.shipBmpx = self.padding + (rect.height - self.shipBmp.GetWidth()) / 2 - self.shipBmpy = (rect.height - self.shipBmp.GetHeight()) / 2 - - self.shipBmpx -= self.animCount - - self.raceBmpx = self.shipEffx + self.shipEffBk.GetWidth() + self.padding - self.raceBmpy = (rect.height - self.raceBmp.GetHeight()) / 2 - - self.textStartx = self.raceBmpx + self.raceBmp.GetWidth() + self.padding - - self.shipNamey = (rect.height - self.shipBmp.GetHeight()) / 2 - - shipName, shipTrait, fittings = self.shipFittingInfo - - mdc.SetFont(self.fontBig) - wtext, htext = mdc.GetTextExtent(shipName) - - self.fittingsy = self.shipNamey + htext - - mdc.SetFont(self.fontSmall) - - wlabel, hlabel = mdc.GetTextExtent(self.toolbar.hoverLabel) - - self.thoverx = self.toolbarx - self.padding - wlabel - self.thovery = (rect.height - hlabel) / 2 - self.thoverw = wlabel - - def DrawItem(self, mdc): - # rect = self.GetRect() - - windowColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW) - textColor = colorUtils.GetSuitableColor(windowColor, 1) - - mdc.SetTextForeground(textColor) - - self.UpdateElementsPos(mdc) - - self.toolbar.SetPosition((self.toolbarx, self.toolbary)) - - if self.GetState() & SFItem.SB_ITEM_HIGHLIGHTED: - shipEffBk = self.shipEffBkMirrored - else: - shipEffBk = self.shipEffBk - - mdc.DrawBitmap(shipEffBk, self.shipEffx, self.shipEffy, 0) - - mdc.DrawBitmap(self.shipBmp, self.shipBmpx, self.shipBmpy, 0) - - mdc.DrawBitmap(self.raceDropShadowBmp, self.raceBmpx + 1, self.raceBmpy + 1) - mdc.DrawBitmap(self.raceBmp, self.raceBmpx, self.raceBmpy) - - shipName, shipTrait, fittings = self.shipFittingInfo - - if fittings < 1: - fformat = "No fits" - elif fittings == 1: - fformat = "%d fit" - else: - fformat = "%d fits" - - mdc.SetFont(self.fontNormal) - mdc.DrawText(fformat % fittings if fittings > 0 else fformat, self.textStartx, self.fittingsy) - - mdc.SetFont(self.fontSmall) - mdc.DrawText(self.toolbar.hoverLabel, self.thoverx, self.thovery) - - mdc.SetFont(self.fontBig) - - psname = drawUtils.GetPartialText(mdc, shipName, - self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw) - - mdc.DrawText(psname, self.textStartx, self.shipNamey) - - if self.tcFitName.IsShown(): - self.AdjustControlSizePos(self.tcFitName, self.textStartx, self.toolbarx - self.editWidth - self.padding) - - def AdjustControlSizePos(self, editCtl, start, end): - fnEditSize = editCtl.GetSize() - wSize = self.GetSize() - fnEditPosX = end - fnEditPosY = (wSize.height - fnEditSize.height) / 2 - if fnEditPosX < start: - editCtl.SetSize((self.editWidth + fnEditPosX - start, -1)) - editCtl.SetPosition((start, fnEditPosY)) - else: - editCtl.SetSize((self.editWidth, -1)) - editCtl.SetPosition((fnEditPosX, fnEditPosY)) - - -class PFBitmapFrame(wx.Frame): - def __init__(self, parent, pos, bitmap): - wx.Frame.__init__(self, parent, id=wx.ID_ANY, title=wx.EmptyString, pos=pos, size=wx.DefaultSize, - style=wx.NO_BORDER | wx.FRAME_NO_TASKBAR | wx.STAY_ON_TOP) - img = bitmap.ConvertToImage() - img = img.ConvertToGreyscale() - bitmap = wx.BitmapFromImage(img) - self.bitmap = bitmap - self.SetSize((bitmap.GetWidth(), bitmap.GetHeight())) - self.Bind(wx.EVT_PAINT, self.OnWindowPaint) - self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnWindowEraseBk) - self.Bind(wx.EVT_TIMER, self.OnTimer) - - self.timer = wx.Timer(self, wx.ID_ANY) - self.direction = 1 - self.transp = 0 - self.SetSize((bitmap.GetWidth(), bitmap.GetHeight())) - - self.SetTransparent(0) - self.Refresh() - - def OnTimer(self, event): - self.transp += 20 * self.direction - if self.transp > 200: - self.transp = 200 - self.timer.Stop() - if self.transp < 0: - self.transp = 0 - self.timer.Stop() - wx.Frame.Show(self, False) - self.Destroy() - return - self.SetTransparent(self.transp) - - def Show(self, showWnd=True): - if showWnd: - wx.Frame.Show(self, showWnd) - self.Parent.SetFocus() - self.direction = 1 - self.timer.Start(5) - else: - self.direction = -1 - self.timer.Start(5) - - def OnWindowEraseBk(self, event): - pass - - def OnWindowPaint(self, event): - rect = self.GetRect() - canvas = wx.EmptyBitmap(rect.width, rect.height) - mdc = wx.BufferedPaintDC(self) - mdc.SelectObject(canvas) - mdc.DrawBitmap(self.bitmap, 0, 0) - mdc.SetPen(wx.Pen("#000000", width=1)) - mdc.SetBrush(wx.TRANSPARENT_BRUSH) - mdc.DrawRectangle(0, 0, rect.width, rect.height) - - -class FitItem(SFItem.SFBrowserItem): - def __init__(self, parent, fitID=None, shipFittingInfo=("Test", "TestTrait", "cnc's avatar", 0, 0, None), shipID=None, - itemData=None, - id=wx.ID_ANY, pos=wx.DefaultPosition, - size=(0, 40), style=0): - - # ===================================================================== - # animCount should be 10 if we enable animation in Preferences - # ===================================================================== - - self.animCount = 0 - self.selectedDelta = 0 - - SFItem.SFBrowserItem.__init__(self, parent, size=size) - - self.mainFrame = gui.mainFrame.MainFrame.getInstance() - - self._itemData = itemData - - self.fitID = fitID - - self.shipID = shipID - - self.shipBrowser = self.Parent.Parent - - self.shipBmp = None - - self.deleted = False - - if shipID: - self.shipBmp = BitmapLoader.getBitmap(str(shipID), "renders") - - if not self.shipBmp: - self.shipBmp = BitmapLoader.getBitmap("ship_no_image_big", "gui") - - self.shipFittingInfo = shipFittingInfo - self.shipName, self.shipTrait, self.fitName, self.fitBooster, self.timestamp, self.notes = shipFittingInfo - - self.shipTrait = re.sub("<.*?>", " ", self.shipTrait) - # see GH issue #62 - - # Disabling this due to change in gang boosts Nov 2016 - # if self.fitBooster is None: self.fitBooster = False - self.fitBooster = False - - self.boosterBmp = BitmapLoader.getBitmap("fleet_fc_small", "gui") - self.copyBmp = BitmapLoader.getBitmap("fit_add_small", "gui") - self.renameBmp = BitmapLoader.getBitmap("fit_rename_small", "gui") - self.deleteBmp = BitmapLoader.getBitmap("fit_delete_small", "gui") - self.acceptBmp = BitmapLoader.getBitmap("faccept_small", "gui") - self.shipEffBk = BitmapLoader.getBitmap("fshipbk_big", "gui") - - img = wx.ImageFromBitmap(self.shipEffBk) - img = img.Mirror(False) - self.shipEffBkMirrored = wx.BitmapFromImage(img) - - self.dragTLFBmp = None - - self.bkBitmap = None - - self.__setToolTip() - - self.padding = 4 - self.editWidth = 150 - - self.dragging = False - self.dragged = False - self.dragMotionTrail = 5 - self.dragMotionTrigger = self.dragMotionTrail - self.dragWindow = None - - self.fontBig = wx.Font(fonts.BIG, wx.SWISS, wx.NORMAL, wx.BOLD) - self.fontNormal = wx.Font(fonts.NORMAL, wx.SWISS, wx.NORMAL, wx.NORMAL) - self.fontSmall = wx.Font(fonts.SMALL, wx.SWISS, wx.NORMAL, wx.NORMAL) - - self.SetDraggable() - - self.boosterBtn = self.toolbar.AddButton(self.boosterBmp, "Booster", show=self.fitBooster) - self.toolbar.AddButton(self.copyBmp, "Copy", self.copyBtnCB) - self.renameBtn = self.toolbar.AddButton(self.renameBmp, "Rename", self.renameBtnCB) - self.toolbar.AddButton(self.deleteBmp, "Delete", self.deleteBtnCB) - - self.tcFitName = wx.TextCtrl(self, wx.ID_ANY, "%s" % self.fitName, wx.DefaultPosition, (self.editWidth, -1), - wx.TE_PROCESS_ENTER) - - if self.shipBrowser.fitIDMustEditName != self.fitID: - self.tcFitName.Show(False) - else: - self.tcFitName.SetFocus() - self.tcFitName.SelectAll() - self.shipBrowser.fitIDMustEditName = -1 - self.renameBtn.SetBitmap(self.acceptBmp) - - self.tcFitName.Bind(wx.EVT_TEXT_ENTER, self.renameFit) - self.tcFitName.Bind(wx.EVT_KILL_FOCUS, self.editLostFocus) - self.tcFitName.Bind(wx.EVT_KEY_DOWN, self.editCheckEsc) - self.Bind(wx.EVT_MOUSE_CAPTURE_LOST, self.OnMouseCaptureLost) - - self.animTimerId = wx.NewId() - self.animTimer = wx.Timer(self, self.animTimerId) - self.animStep = 0 - self.animPeriod = 10 - self.animDuration = 100 - - self.maxDelta = 48 - - self.Bind(wx.EVT_TIMER, self.OnTimer) - - # ===================================================================== - # DISABLED - it will be added as an option in PREFERENCES - - # if self.shipBrowser.GetActiveStage() != 4 and self.shipBrowser.GetLastStage() !=3: - # self.animTimer.Start(self.animPeriod) - # else: - # self.animCount = 0 - # ===================================================================== - - """ - # Remove this bit as the time stuff is non-functional (works... but not exactly sure what it's meant to do) - self.selTimerID = wx.NewId() - - self.selTimer = wx.Timer(self, self.selTimerID) - self.selTimer.Start(100) - """ - - self.Bind(wx.EVT_RIGHT_UP, self.OnContextMenu) - self.Bind(wx.EVT_MIDDLE_UP, self.OpenNewTab) - - def __setToolTip(self): - sFit = Fit.getInstance() - # show no tooltip if no trait available or setting is disabled - if self.shipTrait and sFit.serviceFittingOptions["showShipBrowserTooltip"]: - notes = "" - if self.notes: - notes = u'─' * 20 + u"\nNotes: {}\n".format( - self.notes[:197] + '...' if len(self.notes) > 200 else self.notes) - self.SetToolTip(wx.ToolTip(u'{}\n{}{}\n{}'.format(self.shipName, notes, u'─' * 20, self.shipTrait))) - - def OnKeyDown(self, event): - if event.GetKeyCode() == 32: # space - self.selectFit(event) - event.Skip() - - def OpenNewTab(self, evt): - self.selectFit(newTab=True) - - def OnToggleBooster(self, event): - sFit = Fit.getInstance() - sFit.toggleBoostFit(self.fitID) - self.fitBooster = not self.fitBooster - self.boosterBtn.Show(self.fitBooster) - self.Refresh() - wx.PostEvent(self.mainFrame, BoosterListUpdated()) - event.Skip() - - def OnProjectToFit(self, event): - activeFit = self.mainFrame.getActiveFit() - if activeFit: - sFit = Fit.getInstance() - projectedFit = sFit.getFit(self.fitID) - sFit.project(activeFit, projectedFit) - wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=activeFit)) - self.mainFrame.additionsPane.select("Projected") - - def OnAddCommandFit(self, event): - activeFit = self.mainFrame.getActiveFit() - if activeFit: - sFit = Fit.getInstance() - commandFit = sFit.getFit(self.fitID) - sFit.addCommandFit(activeFit, commandFit) - wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=activeFit)) - self.mainFrame.additionsPane.select("Command") - - def OnMouseCaptureLost(self, event): - """ Destroy drag information (GH issue #479)""" - if self.dragging and self.dragged: - self.dragging = False - self.dragged = False - if self.HasCapture(): - self.ReleaseMouse() - self.dragWindow.Show(False) - self.dragWindow = None - - def OnContextMenu(self, event): - """ Handles context menu for fit. Dragging is handled by MouseLeftUp() """ - sFit = Fit.getInstance() - fit = sFit.getFit(self.mainFrame.getActiveFit()) - - if not fit: - return - - pos = wx.GetMousePosition() - pos = self.ScreenToClient(pos) - - # Even though we may not select a booster, automatically set this so that the fleet pane knows which fit we're applying - self.mainFrame.additionsPane.gangPage.draggedFitID = self.fitID - - menu = wx.Menu() - # toggleItem = menu.Append(wx.ID_ANY, "Booster Fit", kind=wx.ITEM_CHECK) - # menu.Check(toggleItem.GetId(), self.fitBooster) - # self.Bind(wx.EVT_MENU, self.OnToggleBooster, toggleItem) - - # if fit and not fit.isStructure: - # # If there is an active fit, get menu for setting individual boosters - # menu.AppendSeparator() - # boosterMenu = self.mainFrame.additionsPane.gangPage.buildBoostermenu() - # menu.AppendSubMenu(boosterMenu, 'Set Booster') - - if fit: - newTabItem = menu.Append(wx.ID_ANY, "Open in new tab") - self.Bind(wx.EVT_MENU, self.OpenNewTab, newTabItem) - - projectedItem = menu.Append(wx.ID_ANY, "Project onto Active Fit") - self.Bind(wx.EVT_MENU, self.OnProjectToFit, projectedItem) - - commandItem = menu.Append(wx.ID_ANY, "Add Command Booster") - self.Bind(wx.EVT_MENU, self.OnAddCommandFit, commandItem) - - self.PopupMenu(menu, pos) - - event.Skip() - - def GetType(self): - return 3 - - def OnTimer(self, event): - - # @todo: figure out what exactly this is supposed to accomplish - if self.selTimerID == event.GetId(): - ctimestamp = time.time() - interval = 5 - if ctimestamp < self.timestamp + interval: - delta = (ctimestamp - self.timestamp) / interval - self.selectedDelta = self.CalculateDelta(0x0, self.maxDelta, delta) - self.Refresh() - else: - self.selectedDelta = self.maxDelta - self.selTimer.Stop() - - if self.animTimerId == event.GetId(): - step = self.OUT_QUAD(self.animStep, 0, 10, self.animDuration) - self.animCount = 10 - step - self.animStep += self.animPeriod - if self.animStep > self.animDuration or self.animCount < 0: - self.animCount = 0 - self.animTimer.Stop() - self.Refresh() - - @staticmethod - def CalculateDelta(start, end, delta): - return start + (end - start) * delta - - @staticmethod - def OUT_QUAD(t, b, c, d): - t = float(t) - b = float(b) - c = float(c) - d = float(d) - - t /= d - - return -c * t * (t - 2) + b - - def editLostFocus(self, event): - self.RestoreEditButton() - self.Refresh() - - def editCheckEsc(self, event): - if event.GetKeyCode() == wx.WXK_ESCAPE: - self.RestoreEditButton() - else: - event.Skip() - - def copyBtnCB(self): - if self.tcFitName.IsShown(): - self.RestoreEditButton() - return - - self.copyFit() - - def copyFit(self, event=None): - sFit = Fit.getInstance() - fitID = sFit.copyFit(self.fitID) - self.shipBrowser.fitIDMustEditName = fitID - wx.PostEvent(self.shipBrowser, Stage3Selected(shipID=self.shipID)) - wx.PostEvent(self.mainFrame, FitSelected(fitID=fitID)) - - def renameBtnCB(self): - if self.tcFitName.IsShown(): - self.RestoreEditButton() - self.renameFit() - else: - self.tcFitName.SetValue(self.fitName) - self.tcFitName.Show() - self.renameBtn.SetBitmap(self.acceptBmp) - self.tcFitName.SetFocus() - self.tcFitName.SelectAll() - - self.Refresh() - - def renameFit(self, event=None): - sFit = Fit.getInstance() - self.tcFitName.Show(False) - self.editWasShown = 0 - fitName = self.tcFitName.GetValue() - if fitName: - self.fitName = fitName - sFit.renameFit(self.fitID, self.fitName) - wx.PostEvent(self.mainFrame, FitRenamed(fitID=self.fitID)) - else: - self.tcFitName.SetValue(self.fitName) - - def deleteBtnCB(self): - if self.tcFitName.IsShown(): - self.RestoreEditButton() - return - - # to prevent accidental deletion, give dialog confirmation unless shift is depressed - if wx.GetMouseState().ShiftDown() or wx.GetMouseState().MiddleDown(): - self.deleteFit() - else: - dlg = wx.MessageDialog( - self, - "Do you really want to delete this fit?", - "Confirm Delete", - wx.YES | wx.NO | wx.ICON_QUESTION - ) - - if dlg.ShowModal() == wx.ID_YES: - self.deleteFit() - - def deleteFit(self, event=None): - pyfalog.debug("Deleting ship fit.") - if self.deleted: - return - else: - self.deleted = True - - sFit = Fit.getInstance() - fit = sFit.getFit(self.fitID) - - # need to delete from import cache before actually deleting fit - if self.shipBrowser.GetActiveStage() == 5: - if fit in self.shipBrowser.lastdata: # remove fit from import cache - self.shipBrowser.lastdata.remove(fit) - - sFit.deleteFit(self.fitID) - - # Notify other areas that a fit has been deleted - wx.PostEvent(self.mainFrame, FitRemoved(fitID=self.fitID)) - - # todo: would a simple RefreshList() work here instead of posting that a stage has been selected? - if self.shipBrowser.GetActiveStage() == 5: - wx.PostEvent(self.shipBrowser, ImportSelected(fits=self.shipBrowser.lastdata)) - elif self.shipBrowser.GetActiveStage() == 4: - wx.PostEvent(self.shipBrowser, SearchSelected(text=self.shipBrowser.navpanel.lastSearch, back=True)) - else: - wx.PostEvent(self.shipBrowser, Stage3Selected(shipID=self.shipID)) - - def MouseLeftUp(self, event): - if self.dragging and self.dragged: - self.OnMouseCaptureLost(event) - - targetWnd = wx.FindWindowAtPointer() - - if not targetWnd: - return - - wnd = targetWnd - while wnd is not None: - handler = getattr(wnd, "handleDrag", None) - if handler: - handler("fit", self.fitID) - break - else: - wnd = wnd.Parent - event.Skip() - return - - if self.dragging: - self.dragging = False - - if self.tcFitName.IsShown(): - self.RestoreEditButton() - else: - activeFitID = self.mainFrame.getActiveFit() - if activeFitID != self.fitID: - self.selectFit() - - def MouseLeftDown(self, event): - self.dragging = True - - def MouseMove(self, event): - pos = self.ClientToScreen(event.GetPosition()) - if self.dragging: - if not self.dragged: - if self.dragMotionTrigger < 0: - if not self.HasCapture(): - self.CaptureMouse() - self.dragWindow = PFBitmapFrame(self, pos, self.dragTLFBmp) - self.dragWindow.Show() - self.dragged = True - self.dragMotionTrigger = self.dragMotionTrail - else: - self.dragMotionTrigger -= 1 - if self.dragWindow: - pos.x += 3 - pos.y += 3 - self.dragWindow.SetPosition(pos) - return - - def selectFit(self, event=None, newTab=False): - if newTab: - wx.PostEvent(self.mainFrame, FitSelected(fitID=self.fitID, startup=2)) - else: - wx.PostEvent(self.mainFrame, FitSelected(fitID=self.fitID)) - - def RestoreEditButton(self): - self.tcFitName.Show(False) - self.renameBtn.SetBitmap(self.renameBmp) - self.Refresh() - - def UpdateElementsPos(self, mdc): - rect = self.GetRect() - - self.toolbarx = rect.width - self.toolbar.GetWidth() - self.padding - self.toolbary = (rect.height - self.toolbar.GetHeight()) / 2 - - self.toolbarx += self.animCount - - self.shipEffx = self.padding + (rect.height - self.shipEffBk.GetWidth()) / 2 - self.shipEffy = (rect.height - self.shipEffBk.GetHeight()) / 2 - - self.shipEffx -= self.animCount - - self.shipBmpx = self.padding + (rect.height - self.shipBmp.GetWidth()) / 2 - self.shipBmpy = (rect.height - self.shipBmp.GetHeight()) / 2 - - self.shipBmpx -= self.animCount - - self.textStartx = self.shipEffx + self.shipEffBk.GetWidth() + self.padding - - self.fitNamey = (rect.height - self.shipBmp.GetHeight()) / 2 - - mdc.SetFont(self.fontBig) - wtext, htext = mdc.GetTextExtent(self.fitName) - - self.timestampy = self.fitNamey + htext - - mdc.SetFont(self.fontSmall) - - wlabel, hlabel = mdc.GetTextExtent(self.toolbar.hoverLabel) - - self.thoverx = self.toolbarx - self.padding - wlabel - self.thovery = (rect.height - hlabel) / 2 - self.thoverw = wlabel - - def DrawItem(self, mdc): - rect = self.GetRect() - - windowColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW) - textColor = colorUtils.GetSuitableColor(windowColor, 1) - - mdc.SetTextForeground(textColor) - - self.UpdateElementsPos(mdc) - - self.toolbar.SetPosition((self.toolbarx, self.toolbary)) - - if self.GetState() & SFItem.SB_ITEM_HIGHLIGHTED: - shipEffBk = self.shipEffBkMirrored - else: - shipEffBk = self.shipEffBk - - mdc.DrawBitmap(shipEffBk, self.shipEffx, self.shipEffy, 0) - - mdc.DrawBitmap(self.shipBmp, self.shipBmpx, self.shipBmpy, 0) - - mdc.SetFont(self.fontNormal) - - fitDate = self.timestamp.strftime("%m/%d/%Y %H:%M") - fitLocalDate = fitDate # "%d/%02d/%02d %02d:%02d" % (fitDate[0], fitDate[1], fitDate[2], fitDate[3], fitDate[4]) - pfdate = drawUtils.GetPartialText(mdc, fitLocalDate, - self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw) - - mdc.DrawText(pfdate, self.textStartx, self.timestampy) - - mdc.SetFont(self.fontSmall) - mdc.DrawText(self.toolbar.hoverLabel, self.thoverx, self.thovery) - - mdc.SetFont(self.fontBig) - - psname = drawUtils.GetPartialText(mdc, self.fitName, - self.toolbarx - self.textStartx - self.padding * 2 - self.thoverw) - - mdc.DrawText(psname, self.textStartx, self.fitNamey) - - if self.tcFitName.IsShown(): - self.AdjustControlSizePos(self.tcFitName, self.textStartx, self.toolbarx - self.editWidth - self.padding) - - tdc = wx.MemoryDC() - self.dragTLFBmp = wx.EmptyBitmap((self.toolbarx if self.toolbarx < 200 else 200), rect.height, 24) - tdc.SelectObject(self.dragTLFBmp) - tdc.Blit(0, 0, (self.toolbarx if self.toolbarx < 200 else 200), rect.height, mdc, 0, 0, wx.COPY) - tdc.SelectObject(wx.NullBitmap) - - def AdjustControlSizePos(self, editCtl, start, end): - fnEditSize = editCtl.GetSize() - wSize = self.GetSize() - fnEditPosX = end - fnEditPosY = (wSize.height - fnEditSize.height) / 2 - if fnEditPosX < start: - editCtl.SetSize((self.editWidth + fnEditPosX - start, -1)) - editCtl.SetPosition((start, fnEditPosY)) - else: - editCtl.SetSize((self.editWidth, -1)) - editCtl.SetPosition((fnEditPosX, fnEditPosY)) - - def GetState(self): - activeFitID = self.mainFrame.getActiveFit() - - if self.highlighted and not activeFitID == self.fitID: - state = SFItem.SB_ITEM_HIGHLIGHTED - - else: - if activeFitID == self.fitID: - if self.highlighted: - state = SFItem.SB_ITEM_SELECTED | SFItem.SB_ITEM_HIGHLIGHTED - else: - state = SFItem.SB_ITEM_SELECTED - else: - state = SFItem.SB_ITEM_NORMAL - return state - - def Refresh(self): - activeFit = self.mainFrame.getActiveFit() - if activeFit == self.fitID and not self.deleted: - sFit = Fit.getInstance() - fit = sFit.getFit(activeFit) - if fit is not None: # sometimes happens when deleting fits, dunno why. - self.timestamp = fit.modifiedCoalesce - self.notes = fit.notes - self.__setToolTip() - - SFItem.SFBrowserItem.Refresh(self) - - def RenderBackground(self): - rect = self.GetRect() - - windowColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW) - - # activeFitID = self.mainFrame.getActiveFit() - state = self.GetState() - - sFactor = 0.2 - mFactor = None - eFactor = 0 - - if state == SFItem.SB_ITEM_HIGHLIGHTED: - mFactor = 0.45 - eFactor = 0.30 - - elif state == SFItem.SB_ITEM_SELECTED | SFItem.SB_ITEM_HIGHLIGHTED: - eFactor = 0.3 - mFactor = 0.4 - - elif state == SFItem.SB_ITEM_SELECTED: - eFactor = (self.maxDelta - self.selectedDelta) / 100 + 0.25 - else: - sFactor = 0 - - if self.bkBitmap: - if self.bkBitmap.eFactor == eFactor and self.bkBitmap.sFactor == sFactor and self.bkBitmap.mFactor == mFactor \ - and rect.width == self.bkBitmap.GetWidth() and rect.height == self.bkBitmap.GetHeight(): - return - else: - del self.bkBitmap - - self.bkBitmap = drawUtils.RenderGradientBar(windowColor, rect.width, rect.height, sFactor, eFactor, mFactor) - self.bkBitmap.state = state - self.bkBitmap.sFactor = sFactor - self.bkBitmap.eFactor = eFactor - self.bkBitmap.mFactor = mFactor