📄 mainframe.py
字号:
import mathfrom objc import YES, NO, nilfrom AppKit import *from Foundation import *from PyObjCTools import NibClassBuilderimport appimport feedimport prefsimport viewsimport configimport folderimport dialogsimport playlistimport resourcesimport eventloopimport searchenginesimport platformutilsNibClassBuilder.extractClasses("MainWindow")###############################################################################class MainFrame: def __init__(self, appl): self.channelsDisplay = None self.mainDisplay = None self.videoInfoDisplay = None # Do this in two steps so that self.controller is set when self.controler.init # is called. That way, init can turn around and call selectDisplay. self.controller = MainController.alloc() self.controller.init(self, appl) def selectDisplay(self, display, area=None): """Install the provided 'display' in the requested area""" self.controller.selectDisplay(display, area) def getDisplay(self, area): return area.hostedDisplay # Internal use: return an estimate of the size of a given display area as # a Cocoa frame object. def getDisplaySizeHint(self, area): return self.controller.getDisplaySizeHint(area) def onSelectedTabChange(self, strings, actionGroups, guideURL, videoFilename): self.controller.onSelectedTabChange(strings, actionGroups, guideURL, videoFilename)###############################################################################class MainController (NibClassBuilder.AutoBaseClass): def init(self, frame, appl): super(MainController, self).init() self.frame = frame self.appl = appl self.menuStrings = dict() self.actionGroups = dict() NSBundle.loadNibNamed_owner_("MainWindow", self) nc = NSNotificationCenter.defaultCenter() nc.addObserver_selector_name_object_( self, 'appWillTerminate:', NSApplicationWillTerminateNotification, NSApplication.sharedApplication()) return self def awakeFromNib(self): from VideoDisplay import VideoDisplayController self.videoDisplayController = VideoDisplayController.getInstance() self.frame.channelsDisplay = self.channelsHostView self.frame.mainDisplay = self.mainHostView self.frame.videoInfoDisplay = self.videoInfoHostView self.frame.videoInfoDisplay.backgroundColor = NSColor.blackColor() self.restoreLayout() self.updateWindowTexture() self.showWindow_(nil) def appWillTerminate_(self, notification): self.saveLayout() def restoreLayout(self): windowFrame = config.get(prefs.MAIN_WINDOW_FRAME) if windowFrame is None: windowFrame = self.window().frame() else: windowFrame = NSRectFromString(windowFrame) screen = self.window().screen() if screen is not None: visibleFrame = screen.visibleFrame() if not NSContainsRect(visibleFrame, windowFrame): print "DTV: Fitting window to screen size" windowFrame = visibleFrame self.window().setFrame_display_(windowFrame, NO) leftFrame = config.get(prefs.LEFT_VIEW_SIZE) rightFrame = config.get(prefs.RIGHT_VIEW_SIZE) if leftFrame is not None and rightFrame is not None: leftFrame = NSRectFromString(leftFrame) rightFrame = NSRectFromString(rightFrame) self.splitView.subviews().objectAtIndex_(0).setFrame_(leftFrame) self.splitView.subviews().objectAtIndex_(1).setFrame_(rightFrame) self.splitView.adjustSubviews() def saveLayout(self): windowFrame = self.window().frame() windowFrame = NSStringFromRect(windowFrame) leftFrame = self.splitView.subviews().objectAtIndex_(0).frame() leftFrame = NSStringFromRect(leftFrame) rightFrame = self.splitView.subviews().objectAtIndex_(1).frame() rightFrame = NSStringFromRect(rightFrame) config.set(prefs.MAIN_WINDOW_FRAME, windowFrame) config.set(prefs.LEFT_VIEW_SIZE, leftFrame) config.set(prefs.RIGHT_VIEW_SIZE, rightFrame) config.save() def updateWindowTexture(self): bgTexture = NSImage.alloc().initWithSize_(self.window().frame().size) bgTexture.lockFocus() topImage = NSImage.imageNamed_(u'wtexture_top') topColor = NSColor.colorWithPatternImage_(topImage) topColor.set() NSGraphicsContext.currentContext().setPatternPhase_(bgTexture.size()) NSRectFill(((0, bgTexture.size().height - topImage.size().height), (bgTexture.size().width, topImage.size().height))) bottomImage = NSImage.imageNamed_(u'wtexture_bottom') bottomColor = NSColor.colorWithPatternImage_(bottomImage) bottomColor.set() NSGraphicsContext.currentContext().setPatternPhase_(bottomImage.size()) NSRectFill(((0, 0), (bgTexture.size().width, bottomImage.size().height))) bgColor = NSColor.colorWithCalibratedWhite_alpha_(195.0/255.0, 1.0) bgColor.set() NSRectFill(((0, bottomImage.size().height), (bgTexture.size().width, bgTexture.size().height - bottomImage.size().height - topImage.size().height))) bgTexture.unlockFocus() self.window().setBackgroundColor_(NSColor.colorWithPatternImage_(bgTexture)) ### Switching displays ### @platformutils.onMainThread def onSelectedTabChange(self, strings, actionGroups, guideURL, videoFilename): app.controller.setGuideURL(guideURL) self.menuStrings = strings self.actionGroups = actionGroups if actionGroups['VideoPlayable']: notification = 'notifyPlayable' else: notification = 'notifyNotPlayable' nc = NSNotificationCenter.defaultCenter() nc.postNotificationName_object_(notification, nil) def selectDisplay(self, display, area): if display is not None: # Tell the display area that the next display it will host once it's # ready is this one. area.setScheduledDisplay(display) # Tell the new display we want to switch to it. It'll call us # back when it's ready to display without flickering. display.callWhenReadyToDisplay(lambda: self.doSelectDisplay(display, area)) @platformutils.onMainThreadWaitingUntilDone def doSelectDisplay(self, display, area): if area is not None: area.setDisplay(display, self.frame) def getDisplaySizeHint(self, area): return area.frame() ### Window resize handler def windowDidResize_(self, notification): self.updateWindowTexture() def windowWillClose_(self, notification): if app.controller.videoDisplay.isPlaying: eventloop.addUrgentCall(app.controller.playbackController.stop, "Stop Playback") ### Size constraints on splitview ### minimumTabListWidth = 160 # pixels minimumContentWidth = 500 # pixels # How far left can the user move the slider? def splitView_constrainMinCoordinate_ofSubviewAt_(self, sender, proposedMin, offset): return proposedMin + self.minimumTabListWidth # How far right can the user move the slider? def splitView_constrainMaxCoordinate_ofSubviewAt_(self, sender, proposedMax, offset): return proposedMax - self.minimumContentWidth # The window was resized; compute new positions of the splitview # children. Rule: resizing the window doesn't change the size of # the tab list unless it's necessary to shrink it to obey the # minimum content area size constraint. def splitView_resizeSubviewsWithOldSize_(self, sender, oldSize): tabBox = self.channelsHostView.superview() contentBox = self.mainHostView.superview() splitViewSize = sender.frame().size tabSize = tabBox.frame().size contentSize = contentBox.frame().size dividerWidth = sender.dividerThickness() tabSize.height = contentSize.height = splitViewSize.height contentSize.width = splitViewSize.width - dividerWidth - tabSize.width if contentSize.width < self.minimumContentWidth: contentSize.width = self.minimumContentWidth tabSize.width = splitViewSize.width - dividerWidth - contentSize.width tabBox.setFrameSize_(tabSize) tabBox.setFrameOrigin_(NSZeroPoint) contentBox.setFrameSize_(contentSize) contentBox.setFrameOrigin_((tabSize.width + dividerWidth, 0)) def splitView_canCollapseSubview_(self, sender, subview): return self.channelsHostView.isDescendantOf_(subview) and app.controller.videoDisplay.isSelected() ### Events ### def keyDown_(self, event): if self.frame.mainDisplay.hostedDisplay is app.controller.videoDisplay and event.characters().characterAtIndex_(0) == 0x20: app.controller.playbackController.playPause() ### Actions ### # File menu # def removeVideos_(self, sender): eventloop.addIdle(app.controller.removeCurrentItems, "Remove Videos") def saveVideoAs_(self, sender): print "NOT IMPLEMENTED" # $$$$$$$$$$$$$$ def copyVideoURL_(self, sender): eventloop.addIdle(app.controller.copyCurrentItemURL, "Copy Video URL") # Edit menu # def deleteSelected_(self, sender): eventloop.addIdle(app.controller.removeCurrentSelection, "Copy Video URL") # Channels menu # def addChannel_(self, sender): def validationCallback(dialog): if dialog.choice == dialogs.BUTTON_OK: url = dialog.value eventloop.addUrgentCall(lambda:app.controller.addAndSelectFeed(url), "Add Feed") title = "Subscribe to Channel" description = "Enter the URL of the channel you would like to subscribe to." prefillCallback = app.delegate.getURLFromClipboard dlog = dialogs.TextEntryDialog(title, description, dialogs.BUTTON_OK, dialogs.BUTTON_CANCEL, prefillCallback) dlog.run(validationCallback) def createSearchChannel_(self, sender): eventloop.addIdle(lambda:app.controller.addSearchFeed(), "Add Search Feed") def createChannelFolder_(self, sender): folder.createNewChannelFolder() def addGuide_(self, sender): eventloop.addIdle(lambda:app.controller.addAndSelectGuide(), "Add Guide")
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -