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

pointerPanel.py (21365B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\control\pointerPanel.py
      2 from carbonui.primitives.container import Container
      3 from carbonui.primitives.frame import Frame
      4 from carbonui.primitives.transform import Transform
      5 from carbonui.primitives.layoutGrid import LayoutGrid
      6 import carbonui.const as uiconst
      7 import blue
      8 import weakref
      9 from eve.client.script.ui.control.themeColored import FrameThemeColored, SpriteThemeColored
     10 from carbonui.uicore import uicore
     11 LEFTGROUP = [uiconst.POINT_LEFT_2, uiconst.POINT_LEFT_1, uiconst.POINT_LEFT_3]
     12 RIGHTGROUP = [uiconst.POINT_RIGHT_2, uiconst.POINT_RIGHT_1, uiconst.POINT_RIGHT_3]
     13 TOPGROUP = [uiconst.POINT_TOP_2, uiconst.POINT_TOP_1, uiconst.POINT_TOP_3]
     14 BOTTOMGROUP = [uiconst.POINT_BOTTOM_2, uiconst.POINT_BOTTOM_1, uiconst.POINT_BOTTOM_3]
     15 CORNERGROUP = [uiconst.POINT_TOPLEFT,
     16  uiconst.POINT_TOPRIGHT,
     17  uiconst.POINT_BOTTOMLEFT,
     18  uiconst.POINT_BOTTOMRIGHT]
     19 POINT_CORRECTION = {uiconst.POINT_LEFT_1: LEFTGROUP + RIGHTGROUP + BOTTOMGROUP + TOPGROUP,
     20  uiconst.POINT_LEFT_2: LEFTGROUP + RIGHTGROUP + BOTTOMGROUP + TOPGROUP,
     21  uiconst.POINT_LEFT_3: LEFTGROUP + RIGHTGROUP + BOTTOMGROUP + TOPGROUP,
     22  uiconst.POINT_RIGHT_1: RIGHTGROUP + LEFTGROUP + BOTTOMGROUP + TOPGROUP,
     23  uiconst.POINT_RIGHT_2: RIGHTGROUP + LEFTGROUP + BOTTOMGROUP + TOPGROUP,
     24  uiconst.POINT_RIGHT_3: RIGHTGROUP + LEFTGROUP + BOTTOMGROUP + TOPGROUP,
     25  uiconst.POINT_BOTTOM_1: BOTTOMGROUP + LEFTGROUP + TOPGROUP + RIGHTGROUP,
     26  uiconst.POINT_BOTTOM_2: [uiconst.POINT_LEFT_2] + BOTTOMGROUP + LEFTGROUP + TOPGROUP + RIGHTGROUP,
     27  uiconst.POINT_BOTTOM_3: BOTTOMGROUP + LEFTGROUP + TOPGROUP + RIGHTGROUP,
     28  uiconst.POINT_TOP_1: TOPGROUP + LEFTGROUP + BOTTOMGROUP + RIGHTGROUP,
     29  uiconst.POINT_TOP_2: TOPGROUP + LEFTGROUP + BOTTOMGROUP + RIGHTGROUP,
     30  uiconst.POINT_TOP_3: TOPGROUP + LEFTGROUP + BOTTOMGROUP + RIGHTGROUP}
     31 FRAME_WITH_POINTER_SKIN_GENERAL = 'general'
     32 FRAME_WITH_POINTER_SKIN_BADGE = 'badgeStyle'
     33 
     34 class GeneralFrameWithPointerSkin(object):
     35 
     36     def __init__(self):
     37         self.skinName = 'general'
     38         self.leftTexture = 'res:/UI/Texture/classes/FrameWithPointer/pointer_left_02.png'
     39         self.rightTexture = 'res:/UI/Texture/classes/FrameWithPointer/pointer_right_02.png'
     40         self.topRightTexture = 'res:/UI/Texture/classes/FrameWithPointer/pointer_topright_02.png'
     41         self.topLeftTexture = 'res:/UI/Texture/classes/FrameWithPointer/pointer_topleft_02.png'
     42         self.upTexture = 'res:/UI/Texture/classes/FrameWithPointer/pointer_up_02.png'
     43         self.downTexture = 'res:/UI/Texture/classes/FrameWithPointer/pointer_down_02.png'
     44         self.bottomLeftTexture = 'res:/UI/Texture/classes/FrameWithPointer/pointer_bottomleft_02.png'
     45         self.bottomRightTexture = 'res:/UI/Texture/classes/FrameWithPointer/pointer_bottomright_02.png'
     46         self.backgroundTexture = 'res:/UI/Texture/classes/FrameWithPointer/background_04.png'
     47         self.backgroundOffset = -15
     48         self.backgroundCornerSize = 19
     49 
     50 
     51 class BadgeStyleFrameWithPointerSkin(GeneralFrameWithPointerSkin):
     52 
     53     def __init__(self):
     54         super(BadgeStyleFrameWithPointerSkin, self).__init__()
     55         self.skinName = 'badgeStyle'
     56         self.leftTexture = 'res:/UI/Texture/classes/Notifications/pointer_left_02.png'
     57         self.rightTexture = 'res:/UI/Texture/classes/Notifications/pointer_right_02.png'
     58         self.backgroundTexture = 'res:/UI/Texture/classes/Notifications/newItemsBadgeBase.png'
     59         self.backgroundOffset = -6
     60         self.backgroundCornerSize = 10
     61 
     62 
     63 SKIN_NAME_TO_CLASS = {FRAME_WITH_POINTER_SKIN_GENERAL: GeneralFrameWithPointerSkin,
     64  FRAME_WITH_POINTER_SKIN_BADGE: BadgeStyleFrameWithPointerSkin}
     65 
     66 class PointerPanel(LayoutGrid):
     67     default_state = uiconst.UI_PICKCHILDREN
     68     default_align = uiconst.ABSOLUTE
     69     default_opacity = 0.0
     70     default_cellClipChildren = False
     71     beingDestroyed = False
     72     _owner = None
     73     pointerSize = 9
     74     scaleTransform = None
     75     default_pointerDirection = uiconst.POINT_BOTTOM_2
     76 
     77     def ApplyAttributes(self, attributes):
     78         attributes.align = uiconst.TOPLEFT
     79         LayoutGrid.ApplyAttributes(self, attributes)
     80         self.pointerDirection = attributes.get('pointerDirection', self.default_pointerDirection) or self.default_pointerDirection
     81         self.backgroundFrame = FrameWithPointer(bgParent=self, color=attributes.color)
     82         if attributes.owner:
     83             self.owner = attributes.owner
     84         else:
     85             self.opacity = 1.0
     86 
     87     def SetBackgroundColor(self, color):
     88         self.backgroundFrame.SetColor(color)
     89 
     90     def SetBackgroundAlpha(self, alphaValue):
     91         self.backgroundFrame.SetAlpha(alphaValue)
     92 
     93     @apply
     94     def owner():
     95         doc = "Weakref'd Owner of the panel"
     96 
     97         def fset(self, value):
     98             self._owner = weakref.ref(value)
     99 
    100         def fget(self):
    101             if self._owner:
    102                 owner = self._owner()
    103                 if owner and not owner.destroyed:
    104                     return owner
    105                 self._owner = None
    106 
    107         return property(**locals())
    108 
    109     def Close(self, *args):
    110         LayoutGrid.Close(self, *args)
    111         if getattr(self, 'debugFrame', None):
    112             self.debugFrame.Close()
    113         if self.scaleTransform:
    114             self.scaleTransform.Close()
    115             self.scaleTransform = None
    116 
    117     @apply
    118     def pos():
    119         doc = 'Position of UI element'
    120 
    121         def fget(self):
    122             return (self._left,
    123              self._top,
    124              self._width,
    125              self._height)
    126 
    127         def fset(self, value):
    128             left, top, width, height = value
    129             adjustedLeft = int(round(left))
    130             adjustedTop = int(round(top))
    131             adjustedWidth = int(round(width))
    132             adjustedHeight = int(round(height))
    133             self._left = adjustedLeft
    134             self._top = adjustedTop
    135             self._width = adjustedWidth
    136             self._height = adjustedHeight
    137             self._displayX = uicore.ScaleDpi(adjustedLeft)
    138             self._displayY = uicore.ScaleDpi(adjustedTop)
    139             self._displayWidth = uicore.ScaleDpi(adjustedWidth)
    140             self._displayHeight = uicore.ScaleDpi(adjustedHeight)
    141             ro = self.renderObject
    142             if ro:
    143                 ro.displayX = self._displayX
    144                 ro.displayY = self._displayY
    145                 ro.displayWidth = self._displayWidth
    146                 ro.displayHeight = self._displayHeight
    147             self.UpdateBackgrounds()
    148 
    149         return property(**locals())
    150 
    151     @apply
    152     def left():
    153         doc = 'x-coordinate of UI element'
    154 
    155         def fget(self):
    156             return self._left
    157 
    158         def fset(self, value):
    159             adjustedValue = int(round(value))
    160             if adjustedValue != self._left:
    161                 self._left = adjustedValue
    162                 self._displayX = uicore.ScaleDpi(adjustedValue)
    163                 ro = self.renderObject
    164                 if ro:
    165                     ro.displayX = self._displayX
    166 
    167         return property(**locals())
    168 
    169     @apply
    170     def top():
    171         doc = 'y-coordinate of UI element'
    172 
    173         def fget(self):
    174             return self._top
    175 
    176         def fset(self, value):
    177             adjustedValue = int(round(value))
    178             if adjustedValue != self._top:
    179                 self._top = adjustedValue
    180                 self._displayY = uicore.ScaleDpi(adjustedValue)
    181                 ro = self.renderObject
    182                 if ro:
    183                     ro.displayY = self._displayY
    184 
    185         return property(**locals())
    186 
    187     @apply
    188     def width():
    189         doc = 'Width of UI element'
    190 
    191         def fget(self):
    192             return self._width
    193 
    194         def fset(self, value):
    195             adjustedValue = int(round(value))
    196             if adjustedValue != self._width:
    197                 self._width = adjustedValue
    198                 self._displayWidth = uicore.ScaleDpi(adjustedValue)
    199                 ro = self.renderObject
    200                 if ro:
    201                     ro.displayWidth = self._displayWidth
    202                 self.UpdateBackgrounds()
    203                 owner = self.owner
    204                 if owner is None:
    205                     return
    206                 RefreshPanelPosition(self)
    207 
    208         return property(**locals())
    209 
    210     @apply
    211     def height():
    212         doc = 'Height of UI element'
    213 
    214         def fget(self):
    215             return self._height
    216 
    217         def fset(self, value):
    218             adjustedValue = int(round(value))
    219             if adjustedValue != self._height:
    220                 self._height = adjustedValue
    221                 self._displayHeight = uicore.ScaleDpi(adjustedValue)
    222                 ro = self.renderObject
    223                 if ro:
    224                     ro.displayHeight = self._displayHeight
    225                 self.UpdateBackgrounds()
    226                 owner = self.owner
    227                 if owner is None:
    228                     return
    229                 RefreshPanelPosition(self)
    230 
    231         return property(**locals())
    232 
    233     def GetPointerOffset(self):
    234         return self.backgroundFrame.pointerOffset
    235 
    236     def ShowPanel(self, owner):
    237         blue.synchro.Yield()
    238         if self.destroyed:
    239             return
    240         blue.synchro.SleepWallclock(2)
    241         if self.destroyed:
    242             return
    243         uicore.animations.FadeTo(self, startVal=self.opacity, endVal=1.0, duration=0.05, curveType=uiconst.ANIM_SMOOTH)
    244 
    245 
    246 class FrameWithPointer(Container):
    247     pointerOffset = None
    248     skinCache = {}
    249 
    250     def ApplyAttributes(self, attributes):
    251         Container.ApplyAttributes(self, attributes)
    252         skinName = attributes.get('skinName', 'general')
    253         actualSkinClass = SKIN_NAME_TO_CLASS.get(skinName)
    254         if not FrameWithPointer.skinCache.get(skinName):
    255             FrameWithPointer.skinCache[skinName] = actualSkinClass()
    256         self.skin = FrameWithPointer.skinCache[skinName]
    257         self._pointer = SpriteThemeColored(texturePath='res:/UI/Texture/classes/FrameWithPointer/pointer_down_02.png', parent=self, colorType=attributes.colorType or uiconst.COLORTYPE_UIHILIGHTGLOW, opacity=0.95)
    258         self._background = FrameThemeColored(name='__underlay', bgParent=self, cornerSize=self.skin.backgroundCornerSize, offset=self.skin.backgroundOffset, texturePath=self.skin.backgroundTexture, colorType=attributes.colorType or uiconst.COLORTYPE_UIHILIGHTGLOW, opacity=0.95)
    259 
    260     def SetColor(self, color):
    261         self._background.color = color
    262         self._pointer.color = color
    263 
    264     def SetAlpha(self, alphaValue):
    265         self._background.SetAlpha(alphaValue)
    266         self._pointer.SetAlpha(alphaValue)
    267 
    268     def UpdatePointerPosition(self, positionFlag):
    269         if positionFlag == uiconst.POINTER_NONE:
    270             self._pointer.display = False
    271             return (0, 0)
    272         SIZE = 24
    273         BACKOFFSET = 8
    274         x, y = positionFlag
    275         self._pointer.displayX = [-SIZE + BACKOFFSET,
    276          0,
    277          (self.displayWidth - SIZE) / 2,
    278          self.displayWidth - SIZE,
    279          self.displayWidth - BACKOFFSET][x]
    280         self._pointer.displayY = [-SIZE + BACKOFFSET,
    281          0,
    282          (self.displayHeight - SIZE) / 2,
    283          self.displayHeight - SIZE,
    284          self.displayHeight - BACKOFFSET][y]
    285         self._pointer.displayWidth = SIZE
    286         self._pointer.displayHeight = SIZE
    287         if y == 0:
    288             if x == 0:
    289                 self._pointer.displayX = -11
    290                 self._pointer.displayY = -11
    291                 resPath = self.skin.topLeftTexture
    292                 self.pointerOffset = [self._pointer.displayX + 5, self._pointer.displayY + 5]
    293             elif x == 4:
    294                 self._pointer.displayX = self.displayWidth - 13
    295                 self._pointer.displayY = -11
    296                 resPath = self.skin.topRightTexture
    297                 self.pointerOffset = [self._pointer.displayX + 19, self._pointer.displayY + 5]
    298             else:
    299                 resPath = self.skin.upTexture
    300                 self.pointerOffset = [self._pointer.displayX + SIZE / 2, self._pointer.displayY + 10]
    301         elif y == 4:
    302             if x == 0:
    303                 self._pointer.displayX = -11
    304                 self._pointer.displayY = self.displayHeight - 13
    305                 resPath = self.skin.bottomLeftTexture
    306                 self.pointerOffset = [self._pointer.displayX + 5, self._pointer.displayY + 19]
    307             elif x == 4:
    308                 self._pointer.displayX = self.displayWidth - 13
    309                 self._pointer.displayY = self.displayHeight - 13
    310                 resPath = self.skin.bottomRightTexture
    311                 self.pointerOffset = [self._pointer.displayX + 19, self._pointer.displayY + 19]
    312             else:
    313                 resPath = self.skin.downTexture
    314                 self.pointerOffset = [self._pointer.displayX + SIZE / 2, self._pointer.displayY + 14]
    315         elif x == 0:
    316             resPath = self.skin.leftTexture
    317             self.pointerOffset = [self._pointer.displayX + 10, self._pointer.displayY + SIZE / 2]
    318         elif x == 4:
    319             resPath = self.skin.rightTexture
    320             self.pointerOffset = [self._pointer.displayX + 14, self._pointer.displayY + SIZE / 2]
    321         self._pointer.SetTexturePath(resPath)
    322         self._pointer.display = True
    323         return self.pointerOffset
    324 
    325 
    326 def RefreshPanelPosition(pointerPanel):
    327     owner = pointerPanel.owner
    328     if owner is None or owner.destroyed:
    329         return
    330     panelPosition, isBlocked = GetPanelInterestFromObject(owner, checkIfBlockedByOther=getattr(pointerPanel, 'checkIfBlocked', True))
    331     if isBlocked:
    332         pointer = pointerPanel.pointerDirection
    333     else:
    334         pointer = GetPanelPointerFromOwner(owner)
    335         if pointer is None:
    336             pointer = pointerPanel.pointerDirection
    337     UpdatePanelPosition(pointerPanel, panelPosition, pointer)
    338 
    339 
    340 def GetPanelInterestFromObject(uiObject, checkIfBlockedByOther = True):
    341     if hasattr(uiObject, 'GetTooltipPosition'):
    342         customInterestRect = uiObject.GetTooltipPosition()
    343         if customInterestRect:
    344             return (customInterestRect, False)
    345     if uiObject is uicore.uilib.GetAuxMouseOver() and uicore.uilib.auxiliaryTooltip and uicore.uilib.auxiliaryTooltipPosition:
    346         absolutePosition = uicore.uilib.auxiliaryTooltipPosition
    347     else:
    348         absolutePosition = uiObject.GetAbsolute()
    349     retLeft, retTop, retWidth, retHeight = absolutePosition
    350     retRight = retLeft + retWidth
    351     retBottom = retTop + retHeight
    352     obj = uiObject.parent
    353     while obj:
    354         l, t, w, h = obj.GetAbsolute()
    355         retLeft = max(retLeft, l)
    356         retTop = max(retTop, t)
    357         retRight = min(retRight, l + w)
    358         retBottom = min(retBottom, t + h)
    359         obj = obj.parent
    360 
    361     if checkIfBlockedByOther:
    362         isBlocked = IsPartiallyBlockedByOther(uiObject, (retLeft,
    363          retTop,
    364          retRight,
    365          retBottom))
    366         if isBlocked:
    367             retLeft = max(retLeft, uicore.uilib.x - 8)
    368             retTop = max(retTop, uicore.uilib.y - 8)
    369             retRight = min(retRight, uicore.uilib.x + 8)
    370             retBottom = min(retBottom, uicore.uilib.y + 8)
    371     else:
    372         isBlocked = False
    373     return ((retLeft,
    374       retTop,
    375       retRight - retLeft,
    376       retBottom - retTop), isBlocked)
    377 
    378 
    379 def IsPartiallyBlockedByOther(uiObject, rect):
    380     retLeft, retTop, retRight, retBottom = rect
    381     hierarchyTrace = GetObjectDesktopHierarchyPosition(uiObject)
    382     windows = uicore.registry.GetValidWindows()
    383     for window in windows:
    384         if not window.display or uiObject.IsUnder(window):
    385             continue
    386         windowHierarchyTrace = GetObjectDesktopHierarchyPosition(window)
    387         if hierarchyTrace < windowHierarchyTrace:
    388             continue
    389         l2, t2, w2, h2 = window.GetAbsolute()
    390         overlapx = not (retRight <= l2 or retLeft >= l2 + w2)
    391         overlapy = not (retBottom <= t2 or retTop >= t2 + h2)
    392         if overlapx and overlapy:
    393             return True
    394 
    395     return False
    396 
    397 
    398 def SubtractBlockingUIElements(uiObject, rect):
    399     retLeft, retTop, retRight, retBottom = rect
    400     hierarchyTrace = GetObjectDesktopHierarchyPosition(uiObject)
    401     windows = uicore.registry.GetValidWindows()
    402     for window in windows:
    403         if not window.display or uiObject.IsUnder(window):
    404             continue
    405         windowHierarchyTrace = GetObjectDesktopHierarchyPosition(window)
    406         if hierarchyTrace < windowHierarchyTrace:
    407             continue
    408         l2, t2, w2, h2 = window.GetAbsolute()
    409         overlapx = not (retRight <= l2 or retLeft >= l2 + w2)
    410         overlapy = not (retBottom <= t2 or retTop >= t2 + h2)
    411         if not (overlapx and overlapy):
    412             continue
    413         skipVertical = False
    414         if retLeft < l2 < retRight:
    415             retRight = l2
    416             skipVertical = True
    417         if retLeft < l2 + w2 < retRight:
    418             retLeft = l2 + w2
    419             skipVertical = True
    420         if not skipVertical:
    421             if retTop < t2 < retBottom:
    422                 retBottom = t2
    423             if retTop < t2 + h2 < retBottom:
    424                 retTop = t2 + h2
    425 
    426     return (retLeft,
    427      retTop,
    428      retRight,
    429      retBottom)
    430 
    431 
    432 def GetObjectDesktopHierarchyPosition(uiObject):
    433     trace = []
    434     obj = uiObject
    435     while obj.parent:
    436         idx = obj.parent.children.index(obj)
    437         trace.insert(0, idx)
    438         obj = obj.parent
    439 
    440     return trace
    441 
    442 
    443 def GetPanelPointerFromOwner(uiObject):
    444     if hasattr(uiObject, 'GetTooltipPointer'):
    445         customPointer = uiObject.GetTooltipPointer()
    446         if customPointer is not None:
    447             return customPointer
    448     return getattr(uiObject, 'tooltipPointer', None)
    449 
    450 
    451 def _TryPanelPosition(panel, interestRect, menuPointFlag = None):
    452     if menuPointFlag is None:
    453         menuPointFlag = uiconst.POINT_BOTTOM_2
    454     AlignPointPanelToInterest(panel, menuPointFlag, interestRect)
    455     xClip, yClip = (0, 0)
    456     if panel.left < 0:
    457         xClip = -panel.left
    458     elif panel.left + panel.width > uicore.desktop.width:
    459         xClip = panel.left + panel.width - uicore.desktop.width
    460     if panel.top < 0:
    461         yClip = -panel.top
    462     elif panel.top + panel.height > uicore.desktop.height:
    463         yClip = panel.top + panel.height - uicore.desktop.height
    464     return (xClip, yClip)
    465 
    466 
    467 def SortTwo(a, b):
    468     return (a, b if a > b else b, a)
    469 
    470 
    471 def UpdatePanelPosition(panel, interestRect, menuPointFlag = None, fallbackPointFlags = None):
    472     if fallbackPointFlags is None:
    473         if hasattr(panel.owner, 'GetTooltipPositionFallbacks'):
    474             fallbackPointFlags = panel.owner.GetTooltipPositionFallbacks()
    475         else:
    476             fallbackPointFlags = POINT_CORRECTION.get(menuPointFlag, [])[:]
    477             fallbackPointFlags += CORNERGROUP
    478     xClip, yClip = _TryPanelPosition(panel, interestRect, menuPointFlag)
    479     if not (xClip or yClip):
    480         return
    481     cutDepth = SortTwo(xClip, yClip)
    482     cutDepthToFlag = {cutDepth: menuPointFlag}
    483     while cutDepth and fallbackPointFlags:
    484         tryFlag = fallbackPointFlags.pop(0)
    485         xClip, yClip = _TryPanelPosition(panel, interestRect, menuPointFlag=tryFlag)
    486         cutDepth = SortTwo(xClip, yClip)
    487         if cutDepth not in cutDepthToFlag:
    488             cutDepthToFlag[cutDepth] = tryFlag
    489 
    490     if cutDepth:
    491         shallowestCut = min(cutDepthToFlag)
    492         bestFlag = cutDepthToFlag[shallowestCut]
    493         _TryPanelPosition(panel, interestRect, menuPointFlag=bestFlag)
    494 
    495 
    496 def AlignPointPanelToInterest(panel, menuPointFlag, interestRect):
    497     al, at, aw, ah = interestRect
    498     if getattr(panel, 'debugShowInterest', False):
    499         if getattr(panel, 'debugFrame', None):
    500             panel.debugFrame.Close()
    501         panel.debugFrame = Frame(parent=uicore.layer.main, pos=interestRect, align=uiconst.TOPLEFT, idx=0)
    502     pointerOffset = panel.backgroundFrame.UpdatePointerPosition(menuPointFlag)
    503     px, py = pointerOffset
    504     px = uicore.ReverseScaleDpi(px)
    505     py = uicore.ReverseScaleDpi(py)
    506     fx, fy = menuPointFlag
    507     panel.menuPointFlag = menuPointFlag
    508     if fy == 4:
    509         panel.top = at - panel.height - panel.pointerSize
    510     elif fy == 0:
    511         panel.top = at + ah + panel.pointerSize
    512     else:
    513         panel.top = at + ah / 2 - py
    514     if fx == 4:
    515         panel.left = al - panel.width - panel.pointerSize
    516     elif fx == 0:
    517         panel.left = al + aw + panel.pointerSize
    518     else:
    519         panel.left = al + aw / 2 - px
    520 
    521 
    522 def FadeOutPanelAndClose(panel, duration = 0.2):
    523     if panel.destroyed or panel.beingDestroyed:
    524         return
    525     panel.beingDestroyed = True
    526     if getattr(panel, 'beingDestroyedCallback', None):
    527         panel.beingDestroyedCallback(panel)
    528     duration *= panel.opacity
    529     if not duration:
    530         panel.Close()
    531         return
    532     pointerOffset = panel.backgroundFrame.pointerOffset
    533     if not pointerOffset:
    534         panel.Close()
    535         return
    536     x, y = uicore.ReverseScaleDpi(panel.displayX + pointerOffset[0]), uicore.ReverseScaleDpi(panel.displayY + pointerOffset[1])
    537     panel.scaleTransform = Transform(parent=panel.parent, state=uiconst.UI_DISABLED, align=uiconst.TOALL, scalingCenter=(x / float(uicore.desktop.width), y / float(uicore.desktop.height)))
    538     panel.parent.renderObject.children.remove(panel.renderObject)
    539     panel.scaleTransform.renderObject.children.append(panel.renderObject)
    540     uicore.animations.FadeTo(panel.scaleTransform, startVal=panel.opacity, endVal=0.0, duration=duration * 0.5, curveType=uiconst.ANIM_SMOOTH)
    541     uicore.animations.Tr2DScaleTo(panel.scaleTransform, panel.scaleTransform.scale, (0.0, 0.0), duration=duration, callback=panel.Close)