securityOfficeWindow.py (18056B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\station\securityOfficeWindow.py 2 import math 3 from carbonui.primitives.frame import Frame 4 from collections import defaultdict 5 import localization 6 import uthread 7 from carbon.common.script.util.timerstuff import AutoTimer 8 from carbonui import TextAlign, TextColor, uiconst 9 from carbonui.primitives.container import Container 10 from carbonui.primitives.containerAutoSize import ContainerAutoSize 11 from carbonui.primitives.fill import Fill 12 from carbonui.primitives.line import Line 13 from carbonui.primitives.sprite import Sprite 14 from carbonui.uicore import uicore 15 from carbonui.util.color import Color 16 from crimewatch.const import securityLevelsPerTagType 17 from crimewatch.util import CalculateTagRequirementsForSecIncrease 18 from eve.client.script.ui.control import eveIcon, eveLabel 19 from carbonui.control.button import Button 20 from carbonui.control.window import Window 21 from eve.client.script.ui.control.themeColored import SpriteThemeColored 22 from eve.client.script.ui.station.securityOfficeConst import BAR_HEIGHT, BAR_PADDING, BAR_WIDTH, BOX_WIDTH, DRAGBAR_COLOR_NOTAVAILABLE, SEC_BAND_DATA, SEC_METER_HEIGHT, SLIDER_COLOR_AVAILABLE, SLIDER_COLOR_AVAILABLE_ALT, SLIDER_COLOR_CURRENT, SLIDER_COLOR_NOTAVAILABLE, SLIDER_COLOR_NOTAVAILABLE_ALT, SLIDER_COLOR_WANTED, SLIDER_COLOR_WANTED_ALT, TAG_BUCKETS, WINDOW_HEIGHT, WINDOW_WIDTH 23 from eve.common.lib import appConst as const 24 from eve.common.script.net import eveMoniker 25 from eveservices.menu import GetMenuService 26 27 def GetBucketAndRatioForSec(secStatus): 28 for i, data in enumerate(TAG_BUCKETS): 29 if data.minSec <= secStatus < data.maxSec: 30 leftover = secStatus - data.minSec 31 ratio = leftover / (data.maxSec - data.minSec) 32 return (i, leftover, ratio) 33 34 return (len(TAG_BUCKETS) - 1, secStatus - TAG_BUCKETS[-1].minSec, 1.0) 35 36 37 class SecurityOfficeWindow(Window): 38 __notifyevents__ = ['OnSecurityForTagSelectionChanged', 39 'OnSecurityStatusUpdate', 40 'OnItemChange', 41 'OnAccountChange'] 42 default_windowID = 'securityoffice' 43 default_fixedHeight = WINDOW_HEIGHT 44 default_fixedWidth = WINDOW_WIDTH 45 default_captionLabelPath = 'UI/SecurityOffice/StationServiceName' 46 default_iconNum = 'res:/UI/Texture/WindowIcons/concord.png' 47 default_scope = uiconst.SCOPE_STATION 48 default_isStackable = False 49 50 def ApplyAttributes(self, attributes): 51 super(SecurityOfficeWindow, self).ApplyAttributes(attributes) 52 self.crimewatchSvc = sm.GetService('crimewatchSvc') 53 self.godmaSvc = sm.GetService('godma') 54 self.walletSvc = sm.GetService('wallet') 55 self.topParent = ContainerAutoSize(name='topParent', parent=self.GetMainArea(), align=uiconst.TOTOP, clipChildren=True, padding=(0, 10, 0, 10)) 56 self.currentSecurityStatus = 0 57 self.targetSecurityStatus = 0 58 self.ConstructLayout() 59 60 def ConstructTopCont(self): 61 eveLabel.EveCaptionMedium(name='caption', parent=self.topParent, text=localization.GetByLabel('UI/SecurityOffice/HeaderCaption'), align=uiconst.TOTOP, textAlign=TextAlign.CENTER) 62 eveLabel.EveLabelMedium(name='subcaption', parent=self.topParent, text=localization.GetByLabel('UI/SecurityOffice/WindowSubheaderDescription'), align=uiconst.TOTOP, textAlign=TextAlign.CENTER, color=TextColor.SECONDARY) 63 64 def ConstructLayout(self): 65 self.ConstructTopCont() 66 self.securityTagBar = SecurityTagBar(parent=self.sr.main) 67 bottomContainer = Container(name='bottomContainer', parent=self.sr.main, align=uiconst.TOBOTTOM, height=40) 68 self.iskCostText = eveLabel.EveLabelMediumBold(parent=bottomContainer, align=uiconst.CENTERLEFT, left=8) 69 self.submitButton = Button(parent=bottomContainer, align=uiconst.CENTERRIGHT, left=8, label=localization.GetByLabel('UI/SecurityOffice/ExchangeTags'), func=self.Submit) 70 self.CreateTextFeedback() 71 72 def CreateTextFeedback(self): 73 self.pveText = eveLabel.EveLabelMedium(parent=self.sr.main, name='goodEffectText', align=uiconst.CENTERBOTTOM, top=66) 74 self.pvpText = eveLabel.EveLabelMedium(parent=self.sr.main, name='badEffectText', align=uiconst.CENTERBOTTOM, top=48) 75 76 def OnSecurityForTagSelectionChanged(self, targetSecurityStatus, tagsToSpend, sufficientTags): 77 self.targetSecurityStatus = targetSecurityStatus 78 self.currentSecurityStatus = self.crimewatchSvc.GetMySecurityStatus() 79 noSelection = targetSecurityStatus == self.currentSecurityStatus 80 if noSelection: 81 self.submitButton.Disable() 82 else: 83 self.submitButton.Enable() 84 iskTotal = 0 85 for typeID, quantity in tagsToSpend.iteritems(): 86 iskTotal += self.godmaSvc.GetTypeAttribute(typeID, const.attributeSecurityProcessingFee, 0) * quantity 87 88 myBalance = self.walletSvc.GetWealth() 89 text = localization.GetByLabel('UI/SecurityOffice/AdditionalCost', cost=iskTotal) 90 if myBalance < iskTotal: 91 text = '<font color=%s>%s</font>' % (SEC_BAND_DATA[3].color.GetHex(), text) 92 self.submitButton.Disable() 93 elif not noSelection: 94 self.submitButton.Enable() 95 if not sufficientTags: 96 self.submitButton.Disable() 97 self.iskCostText.SetText(text) 98 for data in SEC_BAND_DATA: 99 if data.minSec <= targetSecurityStatus < data.maxSec: 100 self.pvpText.SetText(localization.GetByLabel(data.pvpHintLabel)) 101 self.pveText.SetText(localization.GetByLabel(data.pveHintLable)) 102 break 103 else: 104 data = SEC_BAND_DATA[-1] 105 self.pvpText.SetText(localization.GetByLabel(data.pvpHintLabel)) 106 self.pveText.SetText(localization.GetByLabel(data.pveHintLable)) 107 108 def Submit(self, button): 109 try: 110 eveMoniker.CharGetCrimewatchLocation().ApplyTagsForSecStatus(self.targetSecurityStatus, self.currentSecurityStatus) 111 finally: 112 self.UpdateSecurityTagBar() 113 114 def OnItemChange(self, item, change, location): 115 if item.typeID in securityLevelsPerTagType: 116 if item.locationID == session.stationid or change.get(const.ixLocationID) == session.stationid: 117 self.UpdateSecurityTagBar() 118 119 def UpdateSecurityTagBar(self): 120 self.updateTimer = AutoTimer(100, self._UpdateSecurityTagBar) 121 122 def _UpdateSecurityTagBar(self): 123 self.updateTimer = None 124 self.securityTagBar.UpdateCurrentSecAndTags(self.targetSecurityStatus) 125 126 def OnSecurityStatusUpdate(self, newSecurityStatus): 127 self.UpdateSecurityTagBar() 128 129 def OnAccountChange(self, accountKey, ownerID, balance): 130 if accountKey == 'cash' and ownerID == session.charid: 131 self.UpdateSecurityTagBar() 132 133 134 class SecurityTagBar(Container): 135 default_height = 120 136 default_width = BAR_WIDTH 137 default_align = uiconst.TOTOP 138 default_state = uiconst.UI_PICKCHILDREN 139 default_padLeft = 0 140 default_padRight = 0 141 142 def ApplyAttributes(self, attributes): 143 Container.ApplyAttributes(self, attributes) 144 self.crimewatchSvc = sm.GetService('crimewatchSvc') 145 self.securityOfficeSvc = sm.GetService('securityOfficeSvc') 146 self.isDragging = False 147 self.CreateDragBar() 148 self.CreateBar() 149 self.CreateSlider() 150 uthread.new(self.SetCurrentSecStatus, self.crimewatchSvc.GetMySecurityStatus()) 151 152 def GetSecAtMouseOffset(self, mouseOffset): 153 bucketIndex = int(mouseOffset) / BOX_WIDTH 154 if bucketIndex >= len(TAG_BUCKETS): 155 return 10.0 156 elif bucketIndex < 0: 157 return -10.0 158 else: 159 leftover = mouseOffset % BOX_WIDTH 160 ratio = leftover / float(BOX_WIDTH) 161 data = TAG_BUCKETS[bucketIndex] 162 return data.minSec + ratio * (data.maxSec - data.minSec) 163 164 def SetCurrentSecStatus(self, currentSecurityStatus, mouseOffset = 0): 165 self.currentSecStatus = currentSecurityStatus 166 bucketIndex, leftover, ratio = GetBucketAndRatioForSec(currentSecurityStatus) 167 offset = bucketIndex * BOX_WIDTH + ratio * BOX_WIDTH 168 for fill in self.sliderContainer.children[1:]: 169 fill.width = 0 170 171 self.sliderContainer.children[0].width = offset 172 self.locator.left = offset + BAR_PADDING - self.locator.width / 2 173 targetSecurityStatus = self.GetSecAtMouseOffset(mouseOffset) 174 tags = self.securityOfficeSvc.GetTagsInHangar() 175 tagsToSpend = defaultdict(int) 176 altCount = 0 177 secTarget = currentSecurityStatus 178 tempOffset = offset 179 targetOffset = offset 180 targetSliceSec = currentSecurityStatus 181 sufficientTags = True 182 if bucketIndex < 4: 183 allTagsNeeded = CalculateTagRequirementsForSecIncrease(currentSecurityStatus, TAG_BUCKETS[-1].minSec) 184 for i in xrange(bucketIndex, 4): 185 data = TAG_BUCKETS[i] 186 numTagsNeeded = allTagsNeeded.get(data.typeID, 0) 187 numTagsOwned = min(tags.get(data.typeID, 0), numTagsNeeded) 188 for n in xrange(numTagsNeeded): 189 secTarget += const.securityGainPerTag 190 _bucketIndex, _leftover, _ratio = GetBucketAndRatioForSec(secTarget) 191 newOffset = _bucketIndex * BOX_WIDTH + _ratio * BOX_WIDTH 192 sliceWidth = newOffset - tempOffset 193 altColor = altCount % 2 == 1 194 sliceIsWanted = targetSecurityStatus > secTarget 195 tagIsAvailable = n < numTagsOwned 196 if sliceIsWanted: 197 if tagIsAvailable: 198 color = SLIDER_COLOR_WANTED if altColor else SLIDER_COLOR_WANTED_ALT 199 else: 200 color = SLIDER_COLOR_NOTAVAILABLE if altColor else SLIDER_COLOR_NOTAVAILABLE_ALT 201 sufficientTags = False 202 tagsToSpend[data.typeID] += 1 203 targetSliceSec = secTarget 204 targetOffset = newOffset 205 elif tagIsAvailable: 206 color = SLIDER_COLOR_AVAILABLE if altColor else SLIDER_COLOR_AVAILABLE_ALT 207 else: 208 color = None 209 fill = self.sliderContainer.children[1 + altCount] 210 if color is None: 211 fill.color.SetAlpha(0) 212 else: 213 fill.SetRGBA(*color) 214 self.SetDragBarColor(color) 215 fill.width = sliceWidth 216 tempOffset = newOffset 217 altCount += 1 218 219 if sufficientTags: 220 self.SetDragBarColor(None) 221 else: 222 self.SetDragBarColor(DRAGBAR_COLOR_NOTAVAILABLE) 223 self.locator.left = targetOffset + BAR_PADDING - self.locator.width / 2 224 self.sliderSecText.SetText('%2.1f' % targetSliceSec) 225 if targetOffset == 0: 226 self.sliderSecText.SetAlign(uiconst.BOTTOMLEFT) 227 elif targetOffset == BAR_WIDTH: 228 self.sliderSecText.SetAlign(uiconst.BOTTOMRIGHT) 229 else: 230 self.sliderSecText.SetAlign(uiconst.CENTERBOTTOM) 231 for i, data in enumerate(TAG_BUCKETS): 232 if data.typeID is not None: 233 quantity = tagsToSpend[data.typeID] 234 self.buckets[i].SetQuantity(quantity) 235 236 sm.ScatterEvent('OnSecurityForTagSelectionChanged', targetSliceSec, tagsToSpend, sufficientTags) 237 238 def CreateBar(self): 239 self.barContainer = Container(name='barContainer', parent=self, align=uiconst.TOTOP, height=BAR_HEIGHT, padTop=20, padLeft=BAR_PADDING, padRight=BAR_PADDING) 240 Frame(parent=self.barContainer, color=(0.5, 0.5, 0.5, 0.5), offset=1) 241 eveLabel.EveLabelSmallBold(parent=self.barContainer, align=uiconst.TOPLEFT, text='-10', padTop=3, left=1, color=(1, 1, 1, 1)) 242 eveLabel.EveLabelSmallBold(parent=self.barContainer, align=uiconst.TOPRIGHT, text='-8', padTop=3, left=4 * BOX_WIDTH - 3, color=(1, 1, 1, 1)) 243 eveLabel.EveLabelSmallBold(parent=self.barContainer, align=uiconst.TOPRIGHT, text='-5', padTop=3, left=3 * BOX_WIDTH - 3, color=(1, 1, 1, 1)) 244 eveLabel.EveLabelSmallBold(parent=self.barContainer, align=uiconst.TOPRIGHT, text='-2', padTop=3, left=2 * BOX_WIDTH - 3, color=(1, 1, 1, 1)) 245 eveLabel.EveLabelSmallBold(parent=self.barContainer, align=uiconst.TOPRIGHT, text='0', padTop=3, left=BOX_WIDTH - 3, color=(1, 1, 1, 1)) 246 eveLabel.EveLabelSmallBold(parent=self.barContainer, align=uiconst.TOPRIGHT, text='10', padTop=3, left=1, color=(1, 1, 1, 1)) 247 bucketContainer = Container(name='bucketContainer', parent=self.barContainer, align=uiconst.TOPLEFT, height=BAR_HEIGHT, width=BAR_WIDTH) 248 self.buckets = [] 249 for data in TAG_BUCKETS: 250 if data.typeID is None: 251 bucket = LastBucket(parent=bucketContainer) 252 else: 253 bucket = BucketOfTags(parent=bucketContainer, name='bucket_%s' % data.typeID, typeID=data.typeID, minSec=data.minSec, maxSec=data.maxSec) 254 self.buckets.append(bucket) 255 256 self.sliderContainer = Container(name='sliderContainer', parent=self.barContainer, align=uiconst.TOALL) 257 258 def CreateDragBar(self): 259 self.locator = Container(name='locator', parent=self, align=uiconst.TOPLEFT, left=0, width=8, height=self.height, state=uiconst.UI_NORMAL, padLeft=0, cursor=uiconst.UICURSOR_LEFT_RIGHT_DRAG) 260 self.locator.OnMouseDown = (self.OnSliderMouseDown, self.locator) 261 self.locator.OnMouseMove = (self.OnSliderMouseMove, self.locator) 262 Fill(parent=self.locator, color=(1, 1, 1, 1), height=82, width=2, align=uiconst.CENTER) 263 Sprite(name='topTriangle', parent=self.locator, texturePath='res:/ui/texture/icons/105_32_15.png', align=uiconst.CENTER, rotation=math.pi / 2, width=32, height=32, top=-43, state=uiconst.UI_DISABLED) 264 Sprite(name='bottomTriangle', parent=self.locator, texturePath='res:/ui/texture/icons/105_32_15.png', align=uiconst.CENTER, rotation=-math.pi / 2, width=32, height=32, top=43, state=uiconst.UI_DISABLED) 265 self.sliderSecText = eveLabel.EveLabelLargeBold(parent=self.locator, name='secStatus', align=uiconst.CENTERBOTTOM, top=-4) 266 267 def SetDragBarColor(self, color = None): 268 if color is None: 269 color = Color.WHITE 270 self.locator.children[0].SetRGBA(*color) 271 self.locator.children[1].SetRGBA(*color) 272 self.locator.children[2].SetRGBA(*color) 273 274 def CreateSlider(self): 275 for x in xrange(21): 276 Fill(parent=self.sliderContainer, align=uiconst.TOLEFT, width=0, display=True) 277 278 self.sliderContainer.children[0].SetRGBA(*SLIDER_COLOR_CURRENT) 279 280 def OnSliderMouseDown(self, *args): 281 self.isDragging = True 282 283 def OnSliderMouseMove(self, *args): 284 if not (self.isDragging and uicore.uilib.leftbtn): 285 self.isDragging = False 286 return 287 x, y = self.barContainer.GetAbsolutePosition() 288 offset = uicore.uilib.x - x 289 self.SetCurrentSecStatus(self.crimewatchSvc.GetMySecurityStatus(), offset) 290 291 def UpdateCurrentSecAndTags(self, targetSecurityStatus): 292 bucketIndex, leftover, ratio = GetBucketAndRatioForSec(targetSecurityStatus) 293 offset = bucketIndex * BOX_WIDTH + ratio * BOX_WIDTH 294 currentSecurityStatus = self.crimewatchSvc.GetMySecurityStatus() 295 if targetSecurityStatus != currentSecurityStatus: 296 offset += 1 297 self.SetCurrentSecStatus(currentSecurityStatus, offset) 298 299 300 class BucketOfTags(Container): 301 default_width = BOX_WIDTH 302 default_align = uiconst.TOLEFT 303 default_state = uiconst.UI_PICKCHILDREN 304 305 def ApplyAttributes(self, attributes): 306 Container.ApplyAttributes(self, attributes) 307 self.minSec = attributes.minSec 308 self.maxSec = attributes.maxSec 309 self.secRange = self.maxSec - self.minSec 310 self.typeID = attributes.typeID 311 self.numSecSections = int(self.secRange / 0.5) 312 sectionWidth = self.width / self.numSecSections 313 Line(parent=self, align=uiconst.TORIGHT, color=(0, 0, 0, 0.5)) 314 icon = eveIcon.Icon(parent=self, typeID=self.typeID, size=48, align=uiconst.CENTER, ignoreSize=True, OnClick=self.OnIconClick, state=uiconst.UI_NORMAL) 315 icon.GetMenu = lambda : GetMenuService().GetMenuFromItemIDTypeID(None, self.typeID, includeMarketDetails=True) 316 secMeter = Container(parent=self, align=uiconst.TOTOP, height=SEC_METER_HEIGHT) 317 for n in xrange(self.numSecSections): 318 sec = self.minSec + n * const.securityGainPerTag 319 for data in SEC_BAND_DATA: 320 if sec < data.maxSec: 321 break 322 323 if data.altColor is not None and n % 2 == 1: 324 color = data.altColor 325 else: 326 color = data.color 327 Fill(parent=secMeter, align=uiconst.TOLEFT, width=sectionWidth, color=color.GetRGBA(), hint=localization.GetByLabel(data.pveHintLable) + '<br>' + localization.GetByLabel(data.pvpHintLabel), state=uiconst.UI_NORMAL) 328 329 self.quantitySpentText = eveLabel.EveLabelSmallBold(parent=self, align=uiconst.CENTER, top=30, color=(1, 1, 1, 1)) 330 self.SetQuantity(0) 331 332 def SetQuantity(self, quantity): 333 self.quantitySpentText.SetText(str(quantity)) 334 335 def OnIconClick(self): 336 sm.GetService('info').ShowInfo(self.typeID) 337 338 339 class LastBucket(Container): 340 default_width = BOX_WIDTH + 2 341 default_align = uiconst.TOLEFT 342 default_state = uiconst.UI_NORMAL 343 344 def ApplyAttributes(self, attributes): 345 Container.ApplyAttributes(self, attributes) 346 data = SEC_BAND_DATA[-1] 347 Fill(parent=self, align=uiconst.TOTOP, height=SEC_METER_HEIGHT, color=data.color.GetRGBA(), hint=localization.GetByLabel(data.pveHintLable) + '<br>' + localization.GetByLabel(data.pvpHintLabel), state=uiconst.UI_NORMAL)