NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

defensePanel.py (21820B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\shared\fittingScreen\fittingPanels\defensePanel.py
      2 import math
      3 import dogma.const
      4 import dogma.data
      5 from carbon.common.script.util.format import FmtAmt
      6 from carbonui import uiconst
      7 from carbonui.primitives.container import Container
      8 from carbonui.primitives.fill import Fill
      9 from carbonui.text.settings import check_convert_font_size
     10 from carbonui.uianimations import animations
     11 from carbonui.util.various_unsorted import IsUnder, GetAttrs
     12 from carbonui.window.underlay import WindowUnderlay
     13 from eve.client.script.ui.control.damageGaugeContainers import DamageGaugeContainerFitting
     14 from eve.client.script.ui.control.eveIcon import Icon
     15 from eve.client.script.ui.control.eveLabel import EveLabelMedium, Label
     16 from eve.client.script.ui.shared.fitting.fittingUtil import PASSIVESHIELDRECHARGE, ARMORREPAIRRATEACTIVE, HULLREPAIRRATEACTIVE, SHIELDBOOSTRATEACTIVE, FONTCOLOR_DEFAULT2, GetDefensiveLayersInfo, GetShipAttributeWithDogmaLocation, PANEL_WIDTH_RIGHT
     17 from eve.client.script.ui.shared.fittingScreen.fittingUtil import GetColoredText
     18 from eve.client.script.ui.station.fitting.fittingTooltipUtils import SetFittingTooltipInfo
     19 from eve.client.script.ui.shared.fittingScreen.fittingPanels.basePanel import BaseMenuPanel
     20 from eve.common.lib.appConst import SEC
     21 from inventorycommon.const import fittingFlags, groupArmorRepairUnit, groupFueledArmorRepairer, groupFueledShieldBooster, groupHullRepairUnit, groupShieldBooster
     22 from localization import GetByLabel, GetByMessageID
     23 from carbonui.uicore import uicore
     24 MAXDEFENCELABELWIDTH = 62
     25 MAXDEFENCELABELHEIGHT = 34
     26 ACTIVE_DEFENSES_TOOLTIP_NAME = 'ActiveDefenses'
     27 MILLION = 1000000
     28 SECONDS_DAY = 86400
     29 ICON_SIZE = 20
     30 resAttributeIDs = ((dogma.const.attributeEmDamageResonance, 'ResistanceHeaderEM', 'res:/UI/Texture/classes/Fitting/StatsIcons/EMResistance.png'),
     31  (dogma.const.attributeThermalDamageResonance, 'ResistanceHeaderThermal', 'res:/UI/Texture/classes/Fitting/StatsIcons/thermalResistance.png'),
     32  (dogma.const.attributeKineticDamageResonance, 'ResistanceHeaderKinetic', 'res:/UI/Texture/classes/Fitting/StatsIcons/kineticResistance.png'),
     33  (dogma.const.attributeExplosiveDamageResonance, 'ResistanceHeaderExplosive', 'res:/UI/Texture/classes/Fitting/StatsIcons/explosiveResistance.png'))
     34 rowsInfo = [('UI/Common/Shield', 'shield', 'res:/UI/Texture/classes/Fitting/StatsIcons/shieldHP.png', 'UI/Fitting/FittingWindow/ShieldHPAndRecharge'), ('UI/Common/Armor', 'armor', 'res:/UI/Texture/classes/Fitting/StatsIcons/armorHP.png', 'UI/Common/Armor'), ('UI/Fitting/Structure', 'structure', 'res:/UI/Texture/classes/Fitting/StatsIcons/structureHP.png', 'UI/Fitting/Structure')]
     35 DATASET_FOR_REPAIRERS = {ARMORREPAIRRATEACTIVE: ('UI/Fitting/FittingWindow/ArmorRepairRate',
     36                          (groupArmorRepairUnit, groupFueledArmorRepairer),
     37                          dogma.const.attributeArmorDamageAmount,
     38                          dogma.const.attributeChargedArmorDamageMultiplier,
     39                          'res:/UI/Texture/classes/Fitting/StatsIcons/armorRepairRate.png'),
     40  HULLREPAIRRATEACTIVE: ('UI/Fitting/FittingWindow/HullRepairRate',
     41                         (groupHullRepairUnit,),
     42                         dogma.const.attributeStructureDamageAmount,
     43                         None,
     44                         'res:/UI/Texture/classes/Fitting/StatsIcons/hullRepairRate.png'),
     45  SHIELDBOOSTRATEACTIVE: ('UI/Fitting/FittingWindow/ShieldBoostRate',
     46                          (groupShieldBooster, groupFueledShieldBooster),
     47                          dogma.const.attributeShieldBonus,
     48                          None,
     49                          'res:/UI/Texture/classes/Fitting/StatsIcons/shieldBoostRate.png'),
     50  PASSIVESHIELDRECHARGE: ('UI/Fitting/FittingWindow/PassiveShieldRecharge', None, None, None, 'res:/UI/Texture/classes/Fitting/StatsIcons/passiveShieldRecharge.png')}
     51 
     52 class DefensePanel(BaseMenuPanel):
     53     col1Width = 90
     54 
     55     def ApplyAttributes(self, attributes):
     56         BaseMenuPanel.ApplyAttributes(self, attributes)
     57 
     58     def LoadPanel(self, initialLoad = False):
     59         self.Flush()
     60         self.ResetStatsDicts()
     61         self.display = True
     62         tRow = Container(name='topRow', parent=self, align=uiconst.TOTOP, height=28, padTop=5, padLeft=3)
     63         self.AddBestRepairPicker(tRow)
     64         self.AddColumnHeaderIcons(tRow)
     65         for idx in xrange(len(rowsInfo)):
     66             self.AddRow(idx)
     67 
     68         BaseMenuPanel.FinalizePanelLoading(self, initialLoad)
     69 
     70     def AddBestRepairPicker(self, tRow):
     71         self.bestRepairPickerPanel = None
     72         bestPar = Container(name='bestPar', parent=tRow, align=uiconst.TOPLEFT, height=32, width=self.col1Width, state=uiconst.UI_NORMAL)
     73         bestPar.OnClick = self.ExpandBestRepair
     74         SetFittingTooltipInfo(targetObject=bestPar, tooltipName=ACTIVE_DEFENSES_TOOLTIP_NAME)
     75         self.expandIcon = Icon(name='expandIcon', icon='ui_38_16_229', parent=bestPar, state=uiconst.UI_DISABLED, align=uiconst.TOPLEFT, rotation=math.pi, pos=(-5, -5, 0, 0))
     76         numPar = Container(name='numPar', parent=bestPar, pos=(0, 0, 11, 11), align=uiconst.BOTTOMLEFT, state=uiconst.UI_DISABLED)
     77         numLabel = EveLabelMedium(text='', parent=numPar, atop=-1, state=uiconst.UI_DISABLED, align=uiconst.CENTER, shadowOffset=(0, 0))
     78         Fill(parent=numPar, color=(0.0, 0.0, 0.0, 0.5))
     79         self.activeBestRepairNumLabel = numLabel
     80         icon = Icon(parent=bestPar, state=uiconst.UI_DISABLED, width=ICON_SIZE, height=ICON_SIZE, align=uiconst.CENTERLEFT)
     81         statusLabel = Label(name='statusLabel', text='', parent=bestPar, left=icon.left + icon.width, state=uiconst.UI_DISABLED, align=uiconst.CENTERLEFT)
     82         statusLabel.SetRightAlphaFade(fadeEnd=self.col1Width - 20, maxFadeWidth=15)
     83         self.activeBestRepairLabel = statusLabel
     84         self.activeBestRepairParent = bestPar
     85         self.activeBestRepairIcon = icon
     86 
     87     def AddColumnHeaderIcons(self, tRow):
     88         step = (PANEL_WIDTH_RIGHT - self.col1Width - 10) / 4.0
     89         left = self.col1Width
     90         counter = 0
     91         for attributeID, tooltipName, texturePath in resAttributeIDs:
     92             contLeft = left + int(counter * step)
     93             cont = Container(parent=tRow, align=uiconst.TOLEFT_NOPUSH, pos=(contLeft,
     94              0,
     95              int(step),
     96              0))
     97             icon = Icon(parent=cont, pos=(-6, 0, 24, 24), idx=0, hint=dogma.data.get_attribute_display_name(attributeID), icon=texturePath, align=uiconst.CENTER)
     98             SetFittingTooltipInfo(icon, tooltipName=tooltipName, includeDesc=True)
     99             counter += 1
    100 
    101     def AddRow(self, idx):
    102         labelPath, what, iconNo, labelHintPath = rowsInfo[idx]
    103         rowName = 'row_%s' % what
    104         row = Container(name='row_%s' % rowName, parent=self, align=uiconst.TOTOP, height=32, padLeft=3)
    105         mainIcon = Icon(icon=iconNo, parent=row, pos=(0,
    106          0,
    107          ICON_SIZE,
    108          ICON_SIZE), ignoreSize=True, align=uiconst.CENTERLEFT)
    109         mainIcon.hint = GetByLabel(labelPath)
    110         statusLabel = Label(text='', parent=row, left=mainIcon.left + mainIcon.width, state=uiconst.UI_NORMAL, align=uiconst.CENTERLEFT, width=62)
    111         statusLabel.hint = GetByLabel(labelHintPath)
    112         self.statsLabelsByIdentifier[what] = statusLabel
    113         dmgContainer = Container(parent=row, name='dmgContainer', left=self.col1Width)
    114         gaugeCont = DamageGaugeContainerFitting(parent=dmgContainer)
    115         self.statsContsByIdentifier[what] = gaugeCont
    116 
    117     def SetEffectiveHpHeader(self):
    118         effectiveHpInfo = self.controller.GetEffectiveHp()
    119         text = GetByLabel('UI/Fitting/FittingWindow/ColoredEffectiveHp', effectiveHp=int(effectiveHpInfo.value))
    120         coloredText = GetColoredText(isBetter=effectiveHpInfo.isBetterThanBefore, text=text)
    121         self.SetStatusText(coloredText)
    122 
    123     def UpdateDefensePanel(self):
    124         self.SetEffectiveHpHeader()
    125         allDefensiveLayersInfo = GetDefensiveLayersInfo(self.controller)
    126         for whatLayer, layerInfo in allDefensiveLayersInfo.iteritems():
    127             hpInfo = layerInfo.hpInfo
    128             isRechargable = layerInfo.isRechargable
    129             layerResistancesInfo = layerInfo.resistances
    130             if not hpInfo:
    131                 continue
    132             self.SetDefenseLayerText(hpInfo, whatLayer, isRechargable)
    133             self.UpdateGaugesForLayer(layerResistancesInfo, whatLayer)
    134 
    135     def UpdateGaugesForLayer(self, layerResistancesInfo, whatLayer):
    136         dmgGaugeCont = self.statsContsByIdentifier.get(whatLayer, None)
    137         for dmgType, valueInfo in layerResistancesInfo.iteritems():
    138             value = valueInfo.value
    139             if self.state != uiconst.UI_HIDDEN and dmgGaugeCont:
    140                 text = GetByLabel('UI/Fitting/FittingWindow/ColoredResistanceLabel', number=100 - int(value * 100))
    141                 coloredText = GetColoredText(isBetter=valueInfo.isBetterThanBefore, text=text)
    142                 attributeInfo = dogma.data.get_attribute(valueInfo.attributeID)
    143                 tooltipTitleID = attributeInfo.tooltipTitleID
    144                 if tooltipTitleID:
    145                     tooltipText = GetByMessageID(attributeInfo.tooltipTitleID)
    146                 else:
    147                     tooltipText = dogma.data.get_attribute_display_name(valueInfo.attributeID)
    148                 info = {'value': 1.0 - value,
    149                  'valueText': coloredText,
    150                  'text': tooltipText,
    151                  'dmgType': dmgType,
    152                  'attributeID': valueInfo.attributeID}
    153                 dmgGaugeCont.UpdateGauge(info, animate=True)
    154 
    155     def SetDefenseLayerText(self, statusInfo, what, isRechargable):
    156         label = self.statsLabelsByIdentifier.get(what, None)
    157         if not label:
    158             return
    159         hpText = self._GetFormattedValue(statusInfo.value)
    160         text = None
    161         if isRechargable:
    162             rechargeTimeInfo = self.controller.GetRechargeRate()
    163             rechargeValue = rechargeTimeInfo.value
    164             if rechargeValue < SECONDS_DAY * SEC:
    165                 text = GetByLabel('UI/Fitting/FittingWindow/ColoredHitpointsAndRechargeTime2', hp=hpText, rechargeTime=int(rechargeValue * 0.001), startColorTag1='', startColorTag2='', endColorTag='')
    166         if text is None:
    167             text = GetByLabel('UI/Fitting/FittingWindow/ColoredHp2', hp=hpText)
    168         coloredText = GetColoredText(isBetter=statusInfo.isBetterThanBefore, text=text)
    169         maxTextHeight = MAXDEFENCELABELHEIGHT
    170         maxTextWidth = MAXDEFENCELABELWIDTH
    171         textWidth, textHeight = label.MeasureTextSize(coloredText)
    172         fontsize = check_convert_font_size(label.default_fontsize)
    173         lineSpacing = -0.2
    174         while textWidth > maxTextWidth or textHeight > maxTextHeight:
    175             fontsize -= 1
    176             textWidth, textHeight = label.MeasureTextSize(coloredText, fontsize=fontsize, lineSpacing=lineSpacing)
    177 
    178         label.fontsize = fontsize
    179         label.lineSpacing = lineSpacing
    180         label.text = coloredText
    181 
    182     def _GetFormattedValue(self, value):
    183         if value > 100 * MILLION:
    184             fmt = 'sn'
    185         else:
    186             fmt = 'ln'
    187         valueText = FmtAmt(int(value), fmt=fmt)
    188         return valueText
    189 
    190     def ExpandBestRepair(self, *args):
    191         if self.bestRepairPickerPanel is not None:
    192             self.PickBestRepair(None)
    193             return
    194         self.sr.bestRepairPickerCookie = uicore.event.RegisterForTriuiEvents(uiconst.UI_MOUSEUP, self.OnGlobalMouseUp_BestRepair)
    195         bestRepairParent = self.activeBestRepairParent
    196         l, t, w, h = bestRepairParent.GetAbsolute()
    197         bestRepairPickerPanel = Container(parent=uicore.desktop, name='bestRepairPickerPanel', align=uiconst.TOPLEFT, width=150, height=100, left=l, top=t + h, state=uiconst.UI_NORMAL, idx=0, clipChildren=1)
    198         subpar = Container(parent=bestRepairPickerPanel, name='subpar', align=uiconst.TOALL, state=uiconst.UI_PICKCHILDREN, pos=(0, 0, 0, 0))
    199         active = settings.user.ui.Get('activeBestRepair', PASSIVESHIELDRECHARGE)
    200         top = 0
    201         mw = 32
    202         for flag in (ARMORREPAIRRATEACTIVE,
    203          HULLREPAIRRATEACTIVE,
    204          PASSIVESHIELDRECHARGE,
    205          SHIELDBOOSTRATEACTIVE):
    206             hintPath, _, _, _, iconNo = self.GetDataSetForRepairers(flag)
    207             hint = GetByLabel(hintPath)
    208             entry = Container(name='entry', parent=subpar, align=uiconst.TOTOP, height=32, state=uiconst.UI_NORMAL)
    209             icon = Icon(icon=iconNo, parent=entry, state=uiconst.UI_DISABLED, pos=(2,
    210              0,
    211              ICON_SIZE,
    212              ICON_SIZE), ignoreSize=True, align=uiconst.CENTERLEFT)
    213             label = Label(text=hint, parent=entry, left=icon.left + icon.width + 2, state=uiconst.UI_DISABLED, align=uiconst.CENTERLEFT)
    214             entry.OnClick = (self.PickBestRepair, entry)
    215             entry.OnMouseEnter = (self.OnMouseEnterBestRepair, entry)
    216             entry.bestRepairFlag = flag
    217             entry.sr.hilite = Fill(parent=entry, state=uiconst.UI_HIDDEN)
    218             if active == flag:
    219                 Fill(parent=entry, color=(1.0, 1.0, 1.0, 0.125))
    220             top += 32
    221             mw = max(label.textwidth + label.left + 6, mw)
    222 
    223         bestRepairPickerPanel.width = mw
    224         bestRepairPickerPanel.height = 32
    225         bestRepairPickerPanel.opacity = 0.0
    226         WindowUnderlay(bgParent=bestRepairPickerPanel)
    227         self.bestRepairPickerPanel = bestRepairPickerPanel
    228         animations.MorphScalar(bestRepairPickerPanel, 'height', endVal=top, duration=0.25)
    229         animations.FadeIn(bestRepairPickerPanel, duration=0.25)
    230         self.RotateExpandIconDown()
    231 
    232     def RotateExpandIconDown(self):
    233         animations.MorphScalar(self.expandIcon, 'rotation', self.expandIcon.rotation, 0, duration=0.25, curveType=uiconst.ANIM_LINEAR)
    234 
    235     def RotateExpandIconUp(self):
    236         animations.MorphScalar(self.expandIcon, 'rotation', self.expandIcon.rotation, math.pi, duration=0.25, curveType=uiconst.ANIM_LINEAR)
    237 
    238     def UpdateBestRepair(self):
    239         if not self.panelLoaded:
    240             return
    241         activeRepairLabel = self.activeBestRepairLabel
    242         activeBestRepairParent = self.activeBestRepairParent
    243         activeBestRepairNumLabel = self.activeBestRepairNumLabel
    244         activeBestRepairIcon = self.activeBestRepairIcon
    245         if not activeRepairLabel:
    246             return
    247         activeBestRepair = settings.user.ui.Get('activeBestRepair', PASSIVESHIELDRECHARGE)
    248         if activeBestRepair == PASSIVESHIELDRECHARGE:
    249             SetFittingTooltipInfo(activeBestRepairParent, ACTIVE_DEFENSES_TOOLTIP_NAME)
    250             return self.UpdatePassiveShieldRecharge()
    251         hintPath, groupIDs, repairAttributeID, chargeMultiplierAttributeID, iconNum = self.GetDataSetForRepairers(activeBestRepair)
    252         hint = GetByLabel(hintPath)
    253         activeBestRepairParent.hint = hint
    254         modulesAndCharges = self.FindModulesAndChargesByGroups(groupIDs)
    255         if modulesAndCharges:
    256             totalHpPerSec = self.GetTotalHpPerSec(modulesAndCharges, repairAttributeID, chargeMultiplierAttributeID)
    257             if totalHpPerSec:
    258                 text = GetByLabel('UI/Fitting/FittingWindow/ColoredPassiveRepairRate', hpPerSec=totalHpPerSec)
    259                 activeRepairLabel.text = text
    260             else:
    261                 activeRepairLabel.text = 0
    262             SetFittingTooltipInfo(activeBestRepairParent, ACTIVE_DEFENSES_TOOLTIP_NAME)
    263             text = GetByLabel('UI/Fitting/FittingWindow/ColoredBestRepairNumber', numberOfModules=len(modulesAndCharges))
    264             activeBestRepairNumLabel.text = text
    265             activeBestRepairNumLabel.bold = True
    266             activeBestRepairNumLabel.parent.state = uiconst.UI_DISABLED
    267         else:
    268             activeRepairLabel.text = GetByLabel('UI/Fitting/FittingWindow/NoModule')
    269             activeBestRepairNumLabel.text = GetByLabel('UI/Fitting/FittingWindow/NoModuleNumber')
    270             SetFittingTooltipInfo(activeBestRepairParent, ACTIVE_DEFENSES_TOOLTIP_NAME, extraHeader=GetByLabel('UI/Fitting/FittingWindow/NoModule'))
    271             activeBestRepairNumLabel.parent.state = uiconst.UI_DISABLED
    272         activeBestRepairIcon.LoadIcon(iconNum, ignoreSize=True)
    273 
    274     def FindModulesAndChargesByGroups(self, groupIDs):
    275         modulesAndCharges = []
    276         modulesByFlagID = self.controller.GetFittedModulesByFlagID()
    277         for eachFlag in fittingFlags:
    278             module = modulesByFlagID.get((eachFlag, False), None)
    279             if not module:
    280                 continue
    281             if module.groupID not in groupIDs:
    282                 continue
    283             charge = modulesByFlagID.get((eachFlag, True), None)
    284             modulesAndCharges.append((module, charge))
    285 
    286         return modulesAndCharges
    287 
    288     def GetDataSetForRepairers(self, activeBestRepair):
    289         return DATASET_FOR_REPAIRERS[activeBestRepair]
    290 
    291     def GetTextWithColor(self, color, text):
    292         activeRepairText = '<color=%s>' % color
    293         activeRepairText += text
    294         activeRepairText += '</color>'
    295         return activeRepairText
    296 
    297     def UpdatePassiveShieldRecharge(self):
    298         passiveRechargeRateInfo = self.controller.GetPassiveRechargeRate()
    299         activeRepairText = GetByLabel('UI/Fitting/FittingWindow/ColoredPassiveRepairRate', hpPerSec=int(passiveRechargeRateInfo.value))
    300         coloredText = GetColoredText(isBetter=passiveRechargeRateInfo.isBetterThanBefore, text=activeRepairText)
    301         self.activeBestRepairLabel.text = coloredText
    302         self.activeBestRepairParent.hint = GetByLabel('UI/Fitting/FittingWindow/PassiveShieldRecharge')
    303         self.activeBestRepairNumLabel.parent.state = uiconst.UI_HIDDEN
    304         _, _, _, _, shieldIconID = self.GetDataSetForRepairers(PASSIVESHIELDRECHARGE)
    305         self.activeBestRepairIcon.LoadIcon(shieldIconID, ignoreSize=True)
    306 
    307     def GetTotalHpPerSec(self, modulesAndCharges, repairAttributeID, chargeMultiplierAttributeID = None):
    308         hpsAndDurations = []
    309         totalPerSec = 0
    310 
    311         def GetHpPerSec(hpValue, durationValue):
    312             return hpValue / (durationValue / 1000.0)
    313 
    314         for module, charges in modulesAndCharges:
    315             dogmaItem = self.dogmaLocation.dogmaItems.get(module.itemID, None)
    316             include = self.IncludeModuleInHpCalculation(dogmaItem)
    317             if not include:
    318                 continue
    319             shipID = self.dogmaLocation.GetCurrentShipID()
    320             if dogmaItem and dogmaItem.locationID == shipID:
    321                 duration = self.dogmaLocation.GetAccurateAttributeValue(dogmaItem.itemID, dogma.const.attributeDuration)
    322                 hp = self.dogmaLocation.GetAccurateAttributeValue(dogmaItem.itemID, repairAttributeID)
    323                 multiplier = 1.0
    324                 if charges and chargeMultiplierAttributeID:
    325                     multiplier = self.dogmaLocation.GetAccurateAttributeValue(dogmaItem.itemID, chargeMultiplierAttributeID)
    326                 hp *= multiplier
    327                 totalPerSec += GetHpPerSec(hp, duration)
    328                 hpsAndDurations.append((hp, duration))
    329             else:
    330                 duration = self.dogmaLocation.dogmaStaticMgr.GetTypeAttribute2(module.typeID, dogma.const.attributeDuration)
    331                 hp = self.dogmaLocation.dogmaStaticMgr.GetTypeAttribute2(module.typeID, repairAttributeID)
    332                 if charges:
    333                     multiplier = self.dogmaLocation.dogmaStaticMgr.GetTypeAttribute2(module.typeID, chargeMultiplierAttributeID)
    334                     hp *= multiplier
    335                 totalPerSec += GetHpPerSec(hp, duration)
    336 
    337         return totalPerSec
    338 
    339     def IncludeModuleInHpCalculation(self, module):
    340         if not sm.GetService('fittingSvc').IsShipSimulated():
    341             return True
    342         if not module:
    343             return False
    344         typeEffectInfo = sm.GetService('ghostFittingSvc').GetDefaultAndOverheatEffect(module.typeID)
    345         if not typeEffectInfo.defaultEffect or not typeEffectInfo.isActivatable:
    346             return True
    347         if not module.IsActive():
    348             return False
    349         return True
    350 
    351     def GetShipAttribute(self, attributeID):
    352         dogmaLocation = self.controller.GetDogmaLocation()
    353         shipID = dogmaLocation.GetCurrentShipID()
    354         return GetShipAttributeWithDogmaLocation(dogmaLocation, shipID, attributeID)
    355 
    356     def OnGlobalMouseUp_BestRepair(self, fromwhere, *etc):
    357         if self.bestRepairPickerPanel:
    358             if uicore.uilib.mouseOver == self.bestRepairPickerPanel or IsUnder(fromwhere, self.bestRepairPickerPanel) or fromwhere == self.activeBestRepairParent:
    359                 import log
    360                 log.LogInfo('Combo.OnGlobalClick Ignoring all clicks from comboDropDown')
    361                 return 1
    362         if self.bestRepairPickerPanel and not self.bestRepairPickerPanel.destroyed:
    363             self.bestRepairPickerPanel.Close()
    364         self.bestRepairPickerPanel = None
    365         if self.sr.bestRepairPickerCookie:
    366             uicore.event.UnregisterForTriuiEvents(self.sr.bestRepairPickerCookie)
    367         self.sr.bestRepairPickerCookie = None
    368         self.RotateExpandIconUp()
    369         return 0
    370 
    371     def PickBestRepair(self, entry):
    372         if entry:
    373             settings.user.ui.Set('activeBestRepair', entry.bestRepairFlag)
    374             self.controller.UpdateStats()
    375         if self.bestRepairPickerPanel and not self.bestRepairPickerPanel.destroyed:
    376             self.bestRepairPickerPanel.Close()
    377         self.bestRepairPickerPanel = None
    378         if self.sr.bestRepairPickerCookie:
    379             uicore.event.UnregisterForTriuiEvents(self.sr.bestRepairPickerCookie)
    380         self.sr.bestRepairPickerCookie = None
    381         self.RotateExpandIconUp()
    382 
    383     def OnMouseEnterBestRepair(self, entry):
    384         for each in entry.parent.children:
    385             if GetAttrs(each, 'sr', 'hilite'):
    386                 each.sr.hilite.state = uiconst.UI_HIDDEN
    387 
    388         entry.sr.hilite.state = uiconst.UI_DISABLED