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
class FitItem(SFItem.SFBrowserItem): def __init__(self, parent, fitID=None, shipFittingInfo=("Test", "TestTrait", "cnc's avatar", 0, 0, None), shipID=None, itemData=None, graphicID=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(graphicID), "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 if config.debug: self.fitName = '({}) {}'.format(self.fitID, self.fitName) 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 = self.shipEffBk.ConvertToImage() img = img.Mirror(False) self.shipEffBkMirrored = wx.Bitmap(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 = '─' * 20 + "\nNotes: {}\n".format( self.notes[:197] + '...' if len(self.notes) > 200 else self.notes) self.SetToolTip( wx.ToolTip('{}\n{}{}\n{}'.format(self.shipName, notes, '─' * 20, self.shipTrait))) def OnKeyUp(self, event): if event.GetKeyCode() in (32, 13): # space and enter 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) if self.mainFrame.command.Submit( cmd.GuiAddProjectedCommand(activeFit, projectedFit.ID, 'fit')): self.mainFrame.additionsPane.select("Projected") def OnAddCommandFit(self, event): activeFit = self.mainFrame.getActiveFit() if activeFit: if self.mainFrame.command.Submit( cmd.GuiAddCommandCommand(activeFit, self.fitID)): 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() event.Skip() 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): self.tcFitName.Show(False) self.editWasShown = 0 fitName = self.tcFitName.GetValue() if fitName: self.fitName = fitName self.mainFrame.command.Submit( cmd.GuiFitRenameCommand(self.fitID, self.fitName)) 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().MiddleIsDown(): 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() # need to delete from import cache before actually deleting fit if self.shipBrowser.GetActiveStage() == 5: for x in self.shipBrowser.lastdata: # remove fit from import cache if x[0] == self.fitID: self.shipBrowser.lastdata.remove(x) break 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, recent=self.shipBrowser.recentFits)) 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.GetSuitable(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.Bitmap( (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