class NotificationSettingsMainContainer(Container): default_clipChildren = True def ApplyAttributes(self, attributes): Container.ApplyAttributes(self, attributes=attributes) self.isDeveloperMode = attributes.get('developerMode', True) self.basePadLeft = 5 self.dev_simpleHistoryDisplayEnabled = False self.dev_historySettingsEnabled = True self.dev_exportNotificationHistoryEnabled = False self.dev_clearNotificationHistoryEnabled = False self.dev_soundSettingsEnabled = True parentwidth = attributes.get('parentwidth') self.lastVerticalBarEnabledStatus = False self.entryCache = {} self.leftContainer = NotificationSettingList( name='LeftContainer', align=uiconst.TOLEFT, width=parentwidth / 2, padding=4, parent=self, developerMode=self.isDeveloperMode) self.rightContainer = Container(name='RightContainer', align=uiconst.TOALL, padding=(0, 4, 4, 4), parent=self) BumpedUnderlay(name='leftUnderlay', bgParent=self.leftContainer) BumpedUnderlay(name='rightUnderlay', bgParent=self.rightContainer) self.notificationSettingHandler = NotificationSettingHandler() self.notificationSettingData = self.notificationSettingHandler.LoadSettings( ) self._SetupRightSide() self.leftContainer.PopulateScroll() def _SetupRightSide(self): self._SetupPopupArea() if self.dev_historySettingsEnabled: self._SetupHistoryArea() self._SetupUIArea() def _SetupPopupArea(self): self.popupSettingsContainer = ContainerAutoSize( name='PopupSettings', align=uiconst.TOTOP, parent=self.rightContainer, padding=(self.basePadLeft, 5, 10, 0)) EveLabelMediumBold( name='PopupHeader', align=uiconst.TOTOP, parent=self.popupSettingsContainer, text=localization.GetByLabel( 'Notifications/NotificationSettings/PopupsHeader')) self._MakeSeperationLine(self.popupSettingsContainer) Checkbox( name='UsepopupNotifications', text=localization.GetByLabel( 'Notifications/NotificationSettings/UsePopupNotifications'), parent=self.popupSettingsContainer, align=uiconst.TOTOP, checked=self.notificationSettingHandler.GetPopupsEnabled(), callback=self.OnShowPopupNotificationToggle) if self.dev_soundSettingsEnabled: Checkbox(name='Play sound checkbox', text=localization.GetByLabel( 'Notifications/NotificationSettings/PlaySound'), parent=self.popupSettingsContainer, align=uiconst.TOTOP, checked=self.notificationSettingHandler. GetNotificationSoundEnabled(), callback=self.OnPlaySoundToggle) self.MakeSliderTextRow( label=localization.GetByLabel( 'Notifications/NotificationSettings/FadeDelay'), minValue=0, maxValue=10.0, startValue=self.notificationSettingHandler.GetFadeTime(), stepping=0.5, endSliderFunc=self.OnFadeDelaySet) self.MakeSliderTextRow( label=localization.GetByLabel( 'Notifications/NotificationSettings/StackSize'), minValue=1, maxValue=10, startValue=self.notificationSettingHandler.GetStackSize(), stepping=1, endSliderFunc=self.OnStackSizeSet) def OnFadeDelaySet(self, slider): self.notificationSettingHandler.SaveFadeTime(slider.GetValue()) sm.ScatterEvent('OnNotificationFadeTimeChanged', slider.GetValue()) def OnStackSizeSet(self, slider): self.notificationSettingHandler.SaveStackSize(slider.GetValue()) sm.ScatterEvent('OnNotificationStackSizeChanged', slider.GetValue()) def _MakeSeperationLine(self, parent): Line(name='topLine', parent=parent, align=uiconst.TOTOP, weight=1, padBottom=2, opacity=0.3) def OnShowPopupNotificationToggle(self, checkbox): self.notificationSettingHandler.TogglePopupsEnabled() def OnPlaySoundToggle(self, *args): self.notificationSettingHandler.ToggleSoundEnabled() def _SetupHistoryArea(self): self.historySettingsContainer = ContainerAutoSize( name='HistorySettings', align=uiconst.TOTOP, parent=self.rightContainer, alignMode=uiconst.TOTOP, padding=(self.basePadLeft, 0, 0, 0)) EveLabelMediumBold( name='History', align=uiconst.TOTOP, parent=self.historySettingsContainer, text=localization.GetByLabel( 'Notifications/NotificationSettings/HistoryHeader')) self._MakeSeperationLine(self.historySettingsContainer) Button( name='Restore Notification History Button', align=uiconst.TOTOP, label=localization.GetByLabel( 'Notifications/NotificationSettings/RestoreNotificationHistory' ), func=self.OnExportHistoryClick, pos=(0, 0, 100, 20), parent=self.historySettingsContainer, padding=(5, 5, 50, 5)) Button( name='clearNotificationHistoryBtn', align=uiconst.TOTOP, label=localization.GetByLabel( 'Notifications/NotificationSettings/ClearNotificationHistory'), func=self.OnClearHistoryClick, pos=(0, 0, 100, 20), parent=self.historySettingsContainer, padding=(5, 0, 50, 5)) def _SetupUIArea(self): self.UISettingsContainer = ContainerAutoSize( name='HistorySettings', align=uiconst.TOTOP, parent=self.rightContainer, alignMode=uiconst.TOTOP, padLeft=self.basePadLeft) EveLabelMediumBold( name='UI', align=uiconst.TOTOP, parent=self.UISettingsContainer, text=localization.GetByLabel( 'Notifications/NotificationSettings/UISettingHeader')) self._MakeSeperationLine(self.UISettingsContainer) if self.dev_simpleHistoryDisplayEnabled: Checkbox( name='simple history view', text=localization.GetByLabel( 'Notifications/NotificationSettings/SimpleHistoryDisplay'), parent=self.UISettingsContainer, align=uiconst.TOTOP, checked=True) hComboRowContainer = Container(name='ComboBoxRow', parent=self.UISettingsContainer, align=uiconst.TOTOP, alignMode=uiconst.TOTOP, height=40, padRight=10) from eve.client.script.ui.control.eveCombo import Combo Combo(name='H-ExpandCombo', parent=hComboRowContainer, labelleft=120, label=localization.GetByLabel( 'Notifications/NotificationSettings/DefaultHExpand'), hint=localization.GetByLabel( 'Notifications/NotificationSettings/DefaultHExpandToolTip'), options=self.GetHorizontalComboOptions(), align=uiconst.TOTOP, width=self.rightContainer.width, callback=self.OnHorizontalComboSelect, select=self.notificationSettingHandler. GetHorizontalExpandAlignment()) Combo(name='V-ExpandCombo', parent=hComboRowContainer, labelleft=120, label=localization.GetByLabel( 'Notifications/NotificationSettings/DefaultVExpand'), hint=localization.GetByLabel( 'Notifications/NotificationSettings/DefaultVExpandToolTip'), align=uiconst.TOTOP, options=self.GetVerticalComboOptions(), width=self.rightContainer.width, callback=self.OnVerticalComboSelect, select=self.notificationSettingHandler. GetVerticalExpandAlignment()) def OnVerticalComboSelect(self, box, key, value): self.notificationSettingHandler.SetVerticalExpandAlignment(value) def OnHorizontalComboSelect(self, box, key, value): self.notificationSettingHandler.SetHorizontalExpandAlignment(value) def GetHorizontalComboOptions(self): return ((localization.GetByLabel( 'Notifications/NotificationSettings/ExpandDirectionLeft'), ExpandAlignmentConst.EXPAND_ALIGNMENT_HORIZONTAL_LEFT), (localization.GetByLabel( 'Notifications/NotificationSettings/ExpandDirectionRight'), ExpandAlignmentConst.EXPAND_ALIGNMENT_HORIZONTAL_RIGHT)) def GetVerticalComboOptions(self): return ((localization.GetByLabel( 'Notifications/NotificationSettings/ExpandDirectionUp'), ExpandAlignmentConst.EXPAND_ALIGNMENT_VERTICAL_UP), (localization.GetByLabel( 'Notifications/NotificationSettings/ExpandDirectionDown'), ExpandAlignmentConst.EXPAND_ALIGNMENT_VERTICAL_DOWN)) def OnExportHistoryClick(self, *args): sm.GetService('notificationUIService').UnClearHistory() def OnClearHistoryClick(self, *args): sm.GetService('notificationUIService').ClearHistory() def MakeSliderTextRow(self, label, minValue, maxValue, startValue, stepping, setValueFunc=None, endSliderFunc=None): sliderWidth = 100 sliderValueWidth = 30 sliderLabelWidth = 120 rowPadding = (5, 2, 10, 2) size = EveLabelSmall.MeasureTextSize(label, width=sliderLabelWidth) rowHeight = size[1] rowContainer = Container(name='TextRowContainer', parent=self.rightContainer, align=uiconst.TOTOP, alignMode=uiconst.TOTOP, height=rowHeight, padding=rowPadding) EveLabelSmall(name='sliderlabel', align=uiconst.TOLEFT, parent=rowContainer, text=label, width=sliderLabelWidth) increments = [] currentValue = minValue while currentValue <= maxValue: increments.append(currentValue) currentValue = currentValue + stepping valueLabel = EveLabelSmall(name='sliderValuelabel', left=sliderWidth, align=uiconst.CENTERRIGHT, text=str(startValue), width=sliderValueWidth) def UpdateLabel(slider): valueLabel.text = str(slider.GetValue()) Slider(name='niceSlider', align=uiconst.CENTERRIGHT, parent=rowContainer, minValue=minValue, maxValue=maxValue, width=sliderWidth, showLabel=False, startVal=startValue, isEvenIncrementsSlider=True, increments=increments, onsetvaluefunc=UpdateLabel, endsliderfunc=endSliderFunc) rowContainer.children.append(valueLabel) return rowContainer
class NotificationCenter: def __init__(self, onReconstructCallBack, developerMode, audioCallback): self.audioCallback = audioCallback self.listWidth = 300 self.entryHeight = 52 self.constructed = False self.reconstructCallBack = onReconstructCallBack self.widgetWidth = 32 self.widgetHeight = 32 self.popupEntryWidth = 300 self.isDeveloperMode = developerMode def capWidgetPosition(self): self.customY = min(max(0, self.customY), uicore.desktop.height - self.widgetHeight) self.customX = min(max(0, self.customX), uicore.desktop.width - self.widgetWidth) def LoadPositionValues(self): self.customX, self.customY = self.notificationSettingHandler.GetNotificationBadgeOffset( ) self.capWidgetPosition() self.expandEvaluator.SetWidgetInversePosition(self.customX, self.customY) def SavePositionValues(self): self.notificationSettingHandler.SetNotificationBadgeOffset( (self.customX, self.customY)) def _ConstructStackFader(self): isDown = self.verticalAlignment is ExpandAlignmentConst.EXPAND_ALIGNMENT_VERTICAL_DOWN multiplyer = -2 if isDown else 1 self.stackFader = StackFader( container=self.stackFaderContainer, startPosition=(40, 100 * multiplyer), down=isDown, audioCallback=self.audioCallback, maxStackSize=self.notificationSettingHandler.GetStackSize(), stackTimeSeconds=self.notificationSettingHandler.GetFadeTime()) def _initializeVariables(self, neededVerticalAlignment=None, neededHorizontalAlignment=None): self.cacheIsInitialized = False self.layer = uicore.layer.abovemain self.notificationSettingHandler = NotificationSettingHandler() self.badgeContainer = None self.badgeContainerContainer = None self.scrollList = None self.enablePositionDebug = False self.isShowingDrawer = False self.isAnimating = False self.displayingSingleNotification = False self.clickInterruptedByDrag = False self.RegisterForNotifyEvents() self.settingsButton = None self.leftLine = self.rightLine = self.topLine = self.bottomLine = None self.preferredHeight = self.notificationSettingHandler.GetPreferredHeight( ) wantedHorizontalAlignment = self.notificationSettingHandler.GetHorizontalExpandAlignment( ) wantedVerticalAlignment = self.notificationSettingHandler.GetVerticalExpandAlignment( ) self.wantedHorizontalAlignment = wantedHorizontalAlignment self.wantedVerticalAlignment = wantedVerticalAlignment self.neededVerticalAlignment = neededVerticalAlignment self.neededHorizontalAlignment = neededHorizontalAlignment self.verticalAlignment = neededVerticalAlignment if neededVerticalAlignment else wantedVerticalAlignment self.horizontalAlignment = neededHorizontalAlignment if neededHorizontalAlignment else wantedHorizontalAlignment self.expandEvaluator = ExpandEvaluator( screenWidth=uicore.desktop.width, screenHeight=uicore.desktop.height, preferredHeight=self.preferredHeight, minHistoryHeight=self.notificationSettingHandler. MIN_HISTORY_HEIGHT, maxHistoryHeight=self.notificationSettingHandler. MAX_HISTORY_HEIGHT, expandWidth=self.listWidth) self.transitioner = AlignmentTransitioner( verticalAlignment=self.verticalAlignment, horizontalAlignment=self.horizontalAlignment, wantedVertical=self.notificationSettingHandler. GetVerticalExpandAlignment(), wantedHorizontal=self.notificationSettingHandler. GetHorizontalExpandAlignment(), expandEvaluator=self.expandEvaluator) def SetCacheIsInitialized(self, isInitialized): self.cacheIsInitialized = isInitialized if self.cacheIsInitialized: self._EnableUI() else: self._DisableUI() def _DisableUI(self): self.controlBottomContainer.state = uiconst.UI_DISABLED def _EnableUI(self): self.controlBottomContainer.state = uiconst.UI_PICKCHILDREN def Construct(self, notificationProviderFunction, neededVerticalAlignment=None, neededHorizontalAlignment=None): self.notificationProviderFunction = notificationProviderFunction self._initializeVariables(neededVerticalAlignment, neededHorizontalAlignment) self.LoadPositionValues() self.verticalAlignment = self.transitioner.GetActualVerticalAlignment() self.horizontalAlignment = self.transitioner.GetActualHorizontalAlignment( ) self._ConstructUI() self.constructed = True def _GetAdjustedCustomX(self): if self.horizontalAlignment is ExpandAlignmentConst.EXPAND_ALIGNMENT_HORIZONTAL_RIGHT: return self.customX - self.listWidth + self.widgetWidth else: return self.customX def GetCurrentMousePosition(self): return (uicore.uilib.x, uicore.uilib.y) def SetBadgeValue(self, value): if self.badgeContainer: self.badgeContainer.SetBadgeValue(value) def showBadge(self): if self.badgeContainer: self.badgeContainer.ShowBadge() def hideBadge(self): if self.badgeContainer: self.badgeContainer.HideBadge() def GetContainerArea(self): area = self.notificationContainer.GetAbsolute() return area def _AutoPositionNotificationContainer(self, widgetWidth): if self.notificationContainer: self.notificationContainer.left = self.expandEvaluator.actualX - widgetWidth self.notificationContainer.top = self.expandEvaluator.actualY - self.notificationContainer.height def _AutoPositionBadgeContainer(self, widgetWidth): if self.badgeContainerContainer: area = self.GetClosedArea() leftplus = 0 if self.horizontalAlignment is ExpandAlignmentConst.EXPAND_ALIGNMENT_HORIZONTAL_RIGHT: leftplus = widgetWidth self.badgeContainerContainer.left = area[0] + leftplus * 2 + 8 self.badgeContainerContainer.top = area[1] + 6 def _AutoPositionStackFader(self): if self.stackFader: x = self.expandEvaluator.actualX y = self.expandEvaluator.actualY if self.horizontalAlignment is ExpandAlignmentConst.EXPAND_ALIGNMENT_HORIZONTAL_RIGHT: x = x + self.popupEntryWidth - self.widgetWidth if self.verticalAlignment is ExpandAlignmentConst.EXPAND_ALIGNMENT_VERTICAL_UP: self.stackFader.SetAnchorPosition( (x - self.popupEntryWidth, y - self.widgetHeight)) else: self.stackFader.SetAnchorPosition( (x - self.popupEntryWidth, y)) def AutoPositionContainer(self): self._AutoPositionNotificationContainer(self.widgetWidth) self._AutoPositionBadgeContainer(self.widgetWidth) self._AutoPositionStackFader() if self.enablePositionDebug: self._AutoPositionGuidelines() def deconstruct(self): if self.constructed: self.CleanUpNotifyEvents() self.notificationContainer.Close() self.badgeContainerContainer.Close() self.stackFaderContainer.Close() if self.stackFader: self.stackFader.Cleanup() if self.enablePositionDebug: self._DestroyGuideLines() if self.dragMovable: self.dragMovable.StopDragMode() self.dragMovable = None self.constructed = False def CleanUpNotifyEvents(self): for eventname in self.GetNotifyEvents(): sm.UnregisterForNotifyEvent(self, eventname) def RegisterForNotifyEvents(self): for eventname in self.GetNotifyEvents(): sm.RegisterForNotifyEvent(self, eventname) def GetNotifyEvents(self): return [ 'OnNotificationStackSizeChanged', 'OnNotificationFadeTimeChanged', 'OnNotificationAlignmentChanged', 'OnSetDevice', 'OnUIScalingChange', 'OnUIColorsChanged' ] def OnUIColorsChanged(self): if not self.isShowingDrawer: uthread.new(self.HideFrame) def OnUIScalingChange(self, args): self.OnSetDevice() def OnSetDevice(self): savedX = self.expandEvaluator.actualX savedY = self.expandEvaluator.actualY self.expandEvaluator.SetScreenSize(width=uicore.desktop.width, height=uicore.desktop.height) if self.horizontalAlignment == ExpandAlignmentConst.EXPAND_ALIGNMENT_HORIZONTAL_RIGHT: self.expandEvaluator.SetWidgetPositon(savedX, self.expandEvaluator.actualY) self.customX = self.expandEvaluator.customX self.SavePositionValues() if self.verticalAlignment == ExpandAlignmentConst.EXPAND_ALIGNMENT_VERTICAL_DOWN: self.expandEvaluator.SetWidgetPositon(self.expandEvaluator.actualX, savedY) self.customY = self.expandEvaluator.customY self.SavePositionValues() self.dragMovable.customX = self.customX self.dragMovable.customY = self.customY self.AutoPositionContainer() self._adjustAlignment() def GetUnwantedIds(self): unwanted = [] settings = NotificationSettingHandler().LoadSettings() for k, v in settings.iteritems(): if v.showAtAll == False: unwanted.append(k) return unwanted def MakeAndDisplayNormalNotification(self, notification): settingObject = self.notificationSettingHandler.LoadSettings() thisTypeSetting = settingObject.get(notification.typeID) if not thisTypeSetting: from notifications.client.notificationSettings.notificationSettingHandler import NotificationSettingData thisTypeSetting = NotificationSettingData( notificationID=notification.typeID, showPopup=True, showAtAll=True, group=-1) if thisTypeSetting.showPopup and self.notificationSettingHandler.GetPopupsEnabled( ): self.displayingSingleNotification = True entry = None if notification.metaType is Notification.NORMAL_NOTIFICATION: entry = self._ConstructNotificationPopup(notification) elif notification.metaType is Notification.CONTACT_NOTIFICATION: entry = self._ConstructNotificationContactPopup(notification) entry.LoadContent() entry.OnClick = self.GetNotificationAction(entry, notification) self.displayingEntry = entry self.stackFader.AddItem(entry) def DisplaySingleNotification(self, notification): self.MakeAndDisplayNormalNotification(notification) def OpenKillReport(self, notification): import eve.client.script.ui.shared.killReportUtil as killReportUtil kmID, kmHash = KillMailBaseFormatter.GetKillMailIDandHash( notification.data) theRealKm = sm.RemoteSvc('warStatisticMgr').GetKillMail(kmID, kmHash) killReportUtil.OpenKillReport(theRealKm) def OnEntryClick(self, entry, notification): if notification.metaType == Notification.CONTACT_NOTIFICATION: characterID = notification.senderID sm.GetService('info').ShowInfo( cfg.eveowners.Get(characterID).typeID, characterID) elif notification.typeID == notificationConst.notificationTypeSkillFinished: skillIds = notification.data.get('callbackargs', []) sm.StartService( 'charactersheet').ForceShowSkillHistoryHighlighting(skillIds) elif notification.typeID == notificationConst.notificationTypeSkillEmptyQueue or notification.typeID == notificationConst.notificationTypeUnusedSkillPoints: CharacterSheetWindow.OpenSkills() elif notification.typeID == notificationConst.notificationTypeMailSummary: sm.GetService('cmd').OpenMail() elif notification.typeID == notificationConst.notificationTypeNewMailFrom: sm.GetService('mailSvc').OnOpenPopupMail(notification.data['msg']) elif notification.typeID == notificationConst.notificationTypeContractNeedsAttention: contractSvc = sm.GetService('contracts') count = ContractNeedsAttentionFormatter.GetNeedsAttentionFromData( notification.data) if count == 1: contractSvc.ShowContract( ContractNeedsAttentionFormatter.GetFirstContractId( notification.data)) else: isForCorp = ContractNeedsAttentionFormatter.GetIsForCorp( notification.data) contractSvc.OpenJournal(status=0, forCorp=isForCorp) elif notification.typeID == notificationConst.notificationTypeContractAssigned: contractSvc = sm.GetService('contracts') count = ContractAssignedFormatter.GetAssignedCount( notification.data) if count == 1: contractSvc.ShowContract( ContractAssignedFormatter.GetContractID(notification.data)) else: contractSvc.ShowAssignedTo() elif notification.typeID in [ notificationConst.notificationTypeKillReportFinalBlow, notificationConst.notificationTypeKillReportVictim ]: self.OpenKillReport(notification) elif notification.typeID in ( notificationConst.notificationTypeOpportunityFinished, notificationConst.notificationTypeAchievementTaskFinished): AchievementTreeWindow.Open() sm.GetService('experimentClientSvc').LogWindowOpenedActions( 'OpportunityWindowNotificationEntry') elif notification.typeID == notificationConst.notificationTypeCorpAppNewMsg: sm.GetService('corpui').Show('Recruitment', 'corpApplications') elif notification.typeID in ( notificationConst.notificationTypeCorpAppInvitedMsg, notificationConst.notificationTypeCorpAppAcceptMsg, notificationConst.notificationTypeCorpAppRejectMsg, notificationConst.notificationTypeCorpAppRejectCustomMsg): sm.GetService('corpui').Show('Recruitment', 'myApplications') elif notification.typeID in notificationConst.groupTypes[ notificationConst.groupCCPNotifications]: eve.Message('CustomInfo', {'info': notification.data['text']}, modal=False) elif notification.typeID == notificationConst.notificationTypeServerShutdown: eve.Message('CustomInfo', {'info': notification.data['text']}, modal=False) else: MailInteractor().SelectByNotificationID( notification.notificationID, notificationTypeID=notification.typeID) sm.GetService('experimentClientSvc').LogWindowOpenedActions( 'notificationEntryClick') def ClearNotification(self): if self.scrollList and not self.isShowingDrawer: self.scrollList.Flush() def OnWidgetButtonClick(self): self.dragMovable.Interrupt() self.clickedInMeanTime = True if self.clickInterruptedByDrag: self.clickInterruptedByDrag = False return if self.isShowingDrawer: self.CloseDrawer() else: self.OpenDrawer() sm.GetService('experimentClientSvc').LogWindowOpenedActions( 'notificationWidgetClick') def onWidgetDragFinished(self): self.SavePositionValues() self._adjustAlignment() def onWidgetDragEnter(self): self.clickInterruptedByDrag = True def onWidgetDrag(self, x, y): self.customX = x self.customY = y self.capWidgetPosition() self.dragMovable.customX = self.customX self.dragMovable.customY = self.customY self.expandEvaluator.SetWidgetInversePosition(self.customX, self.customY) self.AutoPositionContainer() def OnNotificationAlignmentChanged(self, *args): if self.wantedHorizontalAlignment is not self.notificationSettingHandler.GetHorizontalExpandAlignment( ) or self.wantedVerticalAlignment is not self.notificationSettingHandler.GetVerticalExpandAlignment( ): self.wantedHorizontalAlignment = self.notificationSettingHandler.GetHorizontalExpandAlignment( ) self.wantedVerticalAlignment = self.notificationSettingHandler.GetVerticalExpandAlignment( ) self.transitioner.wantedVerticalAlignment = self.notificationSettingHandler.GetVerticalExpandAlignment( ) self.transitioner.wantedHorizontalAlignment = self.notificationSettingHandler.GetHorizontalExpandAlignment( ) self._adjustAlignment() def OnNotificationFadeTimeChanged(self, value): if self.stackFader: self.stackFader.SetStackTimeSeconds(value) def OnNotificationStackSizeChanged(self, value): if self.stackFader: self.stackFader.SetStackSize(value) def OnResizeLineMouseDown(self, *args): if not self.isShowingDrawer: return self.dragThing = self.notificationContainer self.startDragHeight = self.dragThing.height self.startDragY = uicore.uilib.y self.startDragTop = self.dragThing.top if uicore.uilib.leftbtn: uthread.new(self.OnResizerDrag) def _OnResizerResize(self, diff): wantedHeight = self.startDragHeight + diff adjustedWantedHeight = min( max( wantedHeight, self.notificationSettingHandler.MIN_HISTORY_HEIGHT + self.widgetHeight), self.notificationSettingHandler.MAX_HISTORY_HEIGHT + 2) self.dragThing.height = adjustedWantedHeight self.preferredHeight = adjustedWantedHeight self.expandEvaluator.preferredHeight = adjustedWantedHeight self.notificationSettingHandler.SetPreferredHeight( adjustedWantedHeight) def OnResizerDrag(self, *args): self.isResizing = True self.activeAutoCloser.Pause() x, y, endWidth, endHeightValue = self.GetClosedArea() minY = y - self.notificationSettingHandler.MIN_HISTORY_HEIGHT while uicore.uilib.leftbtn: diff = self.startDragY - uicore.uilib.y if self.verticalAlignment is ExpandAlignmentConst.EXPAND_ALIGNMENT_VERTICAL_DOWN: diff = -diff self._OnResizerResize(diff) if self.verticalAlignment is ExpandAlignmentConst.EXPAND_ALIGNMENT_VERTICAL_UP: self.dragThing.top = min(self.startDragTop - diff, minY) blue.synchro.SleepWallclock(1) self.isResizing = False self.activeAutoCloser.UnPause() def OnSettingsClick(self, *args): from notifications.client.controls.notificationSettingsWindow import NotificationSettingsWindow NotificationSettingsWindow.ToggleOpenClose() def SetupDrawerAutoCloser(self): self.activeAutoCloser = AutoCloser(None, self.OnAutoCloserFire, self.notificationContainer, thresholdInSeconds=1.0, buffer=10) self.activeAutoCloser.monitor() self.watcherThread = uthread.new(self.ScrollWatcherThread) def ScrollWatcherThread(self): while True: nowvalue = self.scrollList.verticalScrollBar.isDragging if nowvalue != self.lastobservedValue: if nowvalue: self.activeAutoCloser.Abort() else: self.SetupDrawerAutoCloser() self.lastobservedValue = self.scrollList.verticalScrollBar.isDragging blue.synchro.Yield() def OnAutoCloserFire(self, autocloser): self.CloseDrawer() def FillWithNotifications(self, notifications): unwantedIDs = self.GetUnwantedIds() maxFill = 999 self.scrollList.EnableEntryLoad() for i, notification in enumerate(notifications): if not self.scrollList or self.scrollList.destroyed or not self.isShowingDrawer: return if notification.typeID in unwantedIDs: continue if i > maxFill: break if notification.metaType is Notification.NORMAL_NOTIFICATION: entry = self._ConstructNormalNotificationListEntry( notification, parent=self.scrollList) entry.OnClick = self.GetNotificationAction(entry, notification) elif notification.metaType is Notification.CONTACT_NOTIFICATION: entry = self._ConstructContactNotificationListEntry( notification, parent=self.scrollList) entry.OnClick = (self.OnEntryClick, entry, notification) blue.pyos.BeNice(250) self.scrollList.LoadVisibleEntries() def GetNotificationAction(self, entry, notification): if hasattr(notification, 'Activate'): return notification.Activate else: return (self.OnEntryClick, entry, notification) def CloseDrawer(self): if self.isAnimating: return self.isAnimating = True self.scrollList.DisableEntryLoad() if self.activeAutoCloser: self.activeAutoCloser.Abort() self.activeAutoCloser = None self.watcherThread.kill() self.watcherThread = None self.isShowingDrawer = False self._frameCloseAnimation() def ReconstructWithAlignments(self, neededVerticalAlignment=None, neededHorizontalAlignment=None, reOpen=False): self.deconstruct() self.Construct(self.notificationProviderFunction, neededVerticalAlignment=neededVerticalAlignment, neededHorizontalAlignment=neededHorizontalAlignment) self.reconstructCallBack() if reOpen: self.OpenDrawer() def _adjustAlignment(self): adjustedV = self.transitioner.GetActualVerticalAlignment() adjustedH = self.transitioner.GetActualHorizontalAlignment() if adjustedV != self.verticalAlignment or adjustedH != self.horizontalAlignment: self.ReconstructWithAlignments() def _realignIfNeeded(self): didRealign = False if self.transitioner.CheckChangeBackNeeded(): willSwitchHAlign = self.transitioner.CheckHorizontalAlignBackNeeded( ) willSwitchVAlign = self.transitioner.CheckVerticalAlignBackNeeded() self.ReconstructWithAlignments( neededVerticalAlignment=willSwitchVAlign, neededHorizontalAlignment=willSwitchHAlign) didRealign = True return didRealign def StartOpenAnimation(self, endHeightValue, endTopValue, obj): widthAnimationDuration = 0.25 heightAnimationDuration = 0.25 heightAnimationWait = 0.0 self.ShowFrame() if endTopValue != obj.top: uicore.animations.MorphScalar(obj, 'top', startVal=obj.top, endVal=endTopValue, duration=heightAnimationDuration, loops=1, curveType=2, callback=None, sleep=False, curveSet=None, timeOffset=heightAnimationWait) uicore.animations.MorphScalar(obj, 'height', startVal=obj.height, endVal=endHeightValue, duration=heightAnimationDuration, loops=1, curveType=2, callback=None, sleep=False, curveSet=None, timeOffset=heightAnimationWait) uicore.animations.MorphScalar(obj, 'width', startVal=obj.width, endVal=self.listWidth, duration=widthAnimationDuration, loops=1, curveType=2, callback=self._postOpenAnimation, sleep=False, curveSet=None, timeOffset=0.0) if self.horizontalAlignment is ExpandAlignmentConst.EXPAND_ALIGNMENT_HORIZONTAL_LEFT: endleftpoint = self.expandEvaluator.actualX - self.listWidth uicore.animations.MorphScalar(obj, 'left', startVal=obj.left, endVal=endleftpoint, duration=widthAnimationDuration, loops=1, curveType=2, callback=None, sleep=False, curveSet=None, timeOffset=0.0) def _frameOpenAnimation(self): self.dragMovable.SetEnabled(False) obj = self.notificationContainer endHeightValue = 400 height = uicore.desktop.height endTopValue = obj.top self.audioCallback('notify_slide_open_play') if True: if self.verticalAlignment is ExpandAlignmentConst.EXPAND_ALIGNMENT_VERTICAL_UP: if self.expandEvaluator.CanExpandUp(): endHeightValue = self.expandEvaluator.GetAdjustedHeightValue( ) endTopValue = height - endHeightValue - self.customY elif self.expandEvaluator.CanExpandDown(): endHeightValue = self.expandEvaluator.GetAdjustedHeightForDownExpand( ) self.StartOpenAnimation(endHeightValue, endTopValue, obj) def ShowFrame(self): uicore.animations.FadeIn(self.historyHeader, duration=0.25) def HideFrame(self): uicore.animations.FadeOut(self.historyHeader, duration=0.25) def _postOpenAnimation(self): notifications = self.notificationProviderFunction() uthread.new(self.FillWithNotifications, notifications) self.FadeInSettingsButton() self._EnableResize() self.isAnimating = False def FadeInSettingsButton(self): if not self.settingsButton: self._ConstructSettingsButton() uicore.animations.FadeIn(self.settingsButton, duration=0.25) def FadeOutSettingsButton(self): if self.settingsButton: uicore.animations.FadeOut(self.settingsButton, duration=0.25) def GetClosedArea(self): obj = self.notificationContainer endWidth = self.widgetWidth endHeight = self.widgetHeight bottomContainerHeight = 0 endHeightValue = endHeight + bottomContainerHeight heightDifference = obj.height - endHeightValue endTopValue = obj.top + heightDifference widthDifference = obj.width - endWidth if self.horizontalAlignment is ExpandAlignmentConst.EXPAND_ALIGNMENT_HORIZONTAL_LEFT: x = obj.left + widthDifference else: x = obj.left y = endTopValue return (x, y, endWidth, endHeightValue) def _frameCloseAnimation(self): self.isClosing = True self.dragMovable.SetEnabled(False) self.FadeOutSettingsButton() widthAnimationDuration = 0.25 heightAnimationDuration = 0.25 heightAnimationWait = 0 uicore.animations.FadeOut(self.historyHeader, duration=0.25) obj = self.notificationContainer x, y, w, h = self.GetClosedArea() self.audioCallback('notify_slide_close_play') uicore.animations.MorphScalar(obj, 'height', startVal=obj.height, endVal=h, duration=heightAnimationDuration, loops=1, curveType=2, callback=None, sleep=False, curveSet=None, timeOffset=0) if self.verticalAlignment is ExpandAlignmentConst.EXPAND_ALIGNMENT_VERTICAL_UP: uicore.animations.MorphScalar(obj, 'top', startVal=obj.top, endVal=y, duration=heightAnimationDuration, loops=1, curveType=2, callback=None, sleep=False, curveSet=None, timeOffset=0) uicore.animations.MorphScalar(obj, 'width', startVal=obj.width, endVal=w, duration=widthAnimationDuration, loops=1, curveType=2, callback=self._postCloseAnimation, sleep=False, curveSet=None, timeOffset=heightAnimationWait) if self.horizontalAlignment is ExpandAlignmentConst.EXPAND_ALIGNMENT_HORIZONTAL_LEFT: uicore.animations.MorphScalar(obj, 'left', startVal=obj.left, endVal=x, duration=widthAnimationDuration, loops=1, curveType=2, callback=None, sleep=False, curveSet=None, timeOffset=heightAnimationWait) def _postCloseAnimation(self): self.HideFrame() self.dragMovable.SetEnabled(True) self._DisableResize() uthread.new(self.__CleanUpDrawer) def __CleanUpDrawer(self): self.ClearNotification() self.isClosing = False self.dragMovable.SetEnabled(True) self.isAnimating = False def OpenDrawer(self): if self.isAnimating: return self.isShowingDrawer = True self.isAnimating = True self._frameOpenAnimation() self.SetupDrawerAutoCloser() def _ConstructUI(self): self.stackFaderContainer = Container(name='notificationPopupContainer', parent=self.layer) self._ConstructStackFader() self._ConstructBadge() self.notificationContainer = Transform(name='NotificationContainer', parent=self.layer, align=uiconst.TOPLEFT, width=self.widgetWidth, height=self.widgetHeight, clipChildren=True) self.subNotificationContainer = Transform( name='SubNotificationContainer', parent=self.notificationContainer, align=uiconst.TOALL, clipChildren=True) self.actualUnderlay = WindowUnderlay( bgParent=self.notificationContainer) self.topContainer = Container(name='topContainer', parent=self.subNotificationContainer, align=uiconst.TOALL, padding=(0, 0, 0, 0)) self.AutoPositionContainer() self._ConstructNotificationArea() if self.enablePositionDebug: self._ConstructGuideLines() self.AutoPositionContainer() self.HideFrame() def _ConstructSettingsButton(self): if self.horizontalAlignment is ExpandAlignmentConst.EXPAND_ALIGNMENT_HORIZONTAL_LEFT: buttonAlignment = uiconst.TOLEFT else: buttonAlignment = uiconst.TORIGHT self.settingsButton = ButtonIcon( name='MyButtonIcon2', parent=self.controlBottomContainer, align=buttonAlignment, width=24, height=24, iconSize=24, texturePath='res:/UI/Texture/Icons/77_32_30.png', func=self.OnSettingsClick, hint=localization.GetByLabel( 'Notifications/NotificationWidget/NotificationSettingsTooltip' ), padding=(5, 0, 5, 0), opacity=0) def _ConstructControlContainer(self): if self.verticalAlignment is ExpandAlignmentConst.EXPAND_ALIGNMENT_VERTICAL_UP: controlContainerAlignment = uiconst.TOBOTTOM else: controlContainerAlignment = uiconst.TOTOP ctop = 0 if self.verticalAlignment is ExpandAlignmentConst.EXPAND_ALIGNMENT_VERTICAL_DOWN: ctop = -self.historyHeader.height - 4 self.controlBottomContainer = Transform( parent=self.windowunderlay, name='buttonControlContainer', align=controlContainerAlignment, height=32, width=32, top=ctop, clipChilren=False) buttonAlignment = uiconst.TORIGHT if self.horizontalAlignment is ExpandAlignmentConst.EXPAND_ALIGNMENT_HORIZONTAL_RIGHT: buttonAlignment = uiconst.TOLEFT self.widgetButton2 = ButtonIcon( name='WidgetIcon', align=buttonAlignment, width=32, height=32, iconSize=32, texturePath='res:/UI/Texture/classes/Notifications/widgetIcon.png', func=self.OnWidgetButtonClick) self.widgetButton2.LoadTooltipPanel = self._LoadWidgetTooltipPanel self.controlBottomContainer.children.append(self.widgetButton2) self.dragMovable = DragMovable( self.notificationContainer, buttonObject=self.widgetButton2, onDrag=self.onWidgetDrag, onDragEnter=self.onWidgetDragEnter, onDragFinished=self.onWidgetDragFinished, startPosition=(self.customX, self.customY)) def _LoadWidgetTooltipPanel(self, tooltipPanel, *args): if self.dragMovable.IsDragging(): return tooltipPanel.LoadGeneric1ColumnTemplate() tooltipPanel.AddLabelShortcut( localization.GetByLabel( 'Notifications/NotificationWidget/NotificationWidgetTooltip'), None) tooltipPanel.AddLabelMedium(text=localization.GetByLabel( 'Notifications/NotificationWidget/NotificationWidgetTooltipDesc'), wrapWidth=200) def _ConstructResizeLine(self): if self.verticalAlignment is ExpandAlignmentConst.EXPAND_ALIGNMENT_VERTICAL_UP: resizeAlignment = uiconst.TOTOP else: resizeAlignment = uiconst.TOBOTTOM self.resizeLineCont = Container(parent=self.windowunderlay, name='resizeLineCont', align=uiconst.TOALL) self.resizeLine = Line(parent=self.resizeLineCont, color=(0, 0, 0, 0), align=resizeAlignment, weight=3, state=uiconst.UI_NORMAL) self.resizeLine.OnMouseDown = self.OnResizeLineMouseDown self.resizeLine.cursor = uiconst.UICURSOR_TOP_BOTTOM_DRAG self._DisableResize() def _DisableResize(self): self.resizeLine.state = uiconst.UI_DISABLED def _EnableResize(self): self.resizeLine.state = uiconst.UI_NORMAL def _ConstructNotificationArea(self): self.windowunderlay = Container(parent=self.topContainer, name='windowUnderlay', align=uiconst.TOALL) self._ConstructResizeLine() self.historyHeader = Container(name='HistoryContainer', parent=self.windowunderlay, align=uiconst.TOTOP, height=13, padding=(0, 4, 0, 0), clipChildren=True, opacity=0.0) self.historyHeaderLabel = EveLabelSmall( name='history', parent=self.historyHeader, align=uiconst.CENTER, text=localization.GetByLabel( 'Notifications/NotificationWidget/NotificationHistoryCaption'), bold=True) self.historyHeader.height = max(self.historyHeader.height, self.historyHeaderLabel.textheight + 2) self._ConstructControlContainer() if self.verticalAlignment == ExpandAlignmentConst.EXPAND_ALIGNMENT_VERTICAL_UP: padding = (5, 0, 5, 0) else: padding = (5, 0, 5, 5) self.scrollList = NotificationScrollContainer( name='myScrollCont', parent=self.windowunderlay, align=uiconst.TOALL, padding=padding) self.lastobservedValue = self.scrollList.verticalScrollBar.isDragging self.underlay = BumpedUnderlay(bgParent=self.scrollList) def _ConstructNormalNotificationListEntry(self, notification, parent=None): entry = NotificationEntry(parent=parent, align=uiconst.NOALIGN, created=notification.created, notification=notification, developerMode=self.isDeveloperMode) return entry def _ConstructContactNotificationListEntry(self, notification, parent=None): entry = NotificationEntry(parent=parent, align=uiconst.NOALIGN, created=notification.created, notification=notification, developerMode=self.isDeveloperMode) return entry def _ConstructNotificationPopup(self, notification, parent=None): entry = NotificationEntry(parent=parent, align=uiconst.TOPLEFT, created=0, title=notification.subject, width=self.popupEntryWidth, notification=notification) return entry def _ConstructNotificationContactPopup(self, notification, parent=None): entry = NotificationEntry(parent=parent, align=uiconst.TOPLEFT, created=0, title=notification.subject, width=self.popupEntryWidth, notification=notification) return entry def _ConstructBadge(self): self.badgeContainerContainer = Container(name='BadgeMasterContainer', align=uiconst.TOPLEFT, parent=self.layer, clipChildren=False, height=20, width=100, left=100, top=100) leftmultiplyer = 1 if self.horizontalAlignment is ExpandAlignmentConst.EXPAND_ALIGNMENT_HORIZONTAL_LEFT else -1 self.badgeContainer = BadgeContainer( name='BadgeContainer', align=uiconst.TOPLEFT, parent=self.badgeContainerContainer, height=20, left=-120 * leftmultiplyer, opacity=0, pointfromleft=self.horizontalAlignment is ExpandAlignmentConst.EXPAND_ALIGNMENT_HORIZONTAL_LEFT) def _MakeGuideLine(self, name, width, height, color): return Line(name=name, align=uiconst.TOPLEFT, weight=2, opacity=1.0, parent=self.layer, width=width, height=height, color=color) def _ConstructGuideLines(self): self.centerDot = Line(name='centerDot', align=uiconst.TOPLEFT, weight=2, opacity=1.0, parent=self.layer, width=2, height=2, color=(0.6, 0.6, 0.6)) self.leftLine = self._MakeGuideLine(name='leftline', width=10, height=2, color=(1, 0, 0)) self.rightLine = self._MakeGuideLine(name='rightline', width=10, height=2, color=(0, 1, 0)) self.topLine = self._MakeGuideLine(name='topLine', width=10, height=2, color=(0, 0, 1)) self.bottomLine = self._MakeGuideLine(name='bottomLine', width=10, height=2, color=(0.5, 0.5, 1)) self.allLines = [ self.leftLine, self.rightLine, self.topLine, self.bottomLine, self.centerDot ] def _AutoPositionGuidelines(self): if self.leftLine: for line in self.allLines: line.left = self.expandEvaluator.actualX line.top = self.expandEvaluator.actualY self.leftLine.left -= 10 self.topLine.top -= 10 self.bottomLine.opacity = float( self.expandEvaluator.CanExpandDown()) self.topLine.opacity = float(self.expandEvaluator.CanExpandUp()) self.leftLine.opacity = float(self.expandEvaluator.CanExpandLeft()) self.rightLine.opacity = float( self.expandEvaluator.CanExpandRight()) def _DestroyGuideLines(self): for line in self.allLines: line.Close() self.allLines = []