ControlledPreferences¶
A PyObjC Example without documentation
Sources¶
ControlledPreferences.py¶
#
# ControlledPreferences
#
#
# import classes required to start application
import FontNameToDisplayNameTransformer # noqa: F401
import FontSampleDisplayView # noqa: F401
import PreferencesPanelController # noqa: F401
from PyObjCTools import AppHelper
# start the event loop
AppHelper.runEventLoop()
FontNameToDisplayNameTransformer.py¶
#
# FontNameToDisplayNameTransformer.py
# ControlledPreferences
#
# Converted by u.fiedler on 04.02.05.
# with great help from Bob Ippolito - Thank you Bob!
#
# The original version was written in Objective-C by Malcolm Crawford
# at http://homepage.mac.com/mmalc/CocoaExamples/controllers.html
from Cocoa import NSFont, NSString, NSValueTransformer
class FontNameToDisplayNameTransformer(NSValueTransformer):
"""
Takes as input the fontName of a font as stored in user defaults,
returns the displayed font name of the font to show to the user.
"""
@classmethod
def transformedValueClass(cls):
return NSString
@classmethod
def allowsReverseTransformation(cls):
return False
def transformedValue_(self, aValue):
font = NSFont.fontWithName_size_(aValue, 12)
return font.displayName()
FontSampleDisplayView.py¶
#
# FontSampleDisplayView.py
# ControlledPreferences
#
# Converted by u.fiedler on 04.02.05.
# with great help from Bob Ippolito - Thank you Bob!
#
# The original version was written in Objective-C by Malcolm Crawford
# at http://homepage.mac.com/mmalc/CocoaExamples/controllers.html
from Cocoa import (
NSAttributedString,
NSDrawLightBezel,
NSFont,
NSFontAttributeName,
NSInsetRect,
NSMakePoint,
NSNotificationCenter,
NSRectFill,
NSUnarchiver,
NSUserDefaultsController,
NSUserDefaultsDidChangeNotification,
NSView,
)
from objc import super # noqa: A004
from PyObjCTools.KeyValueCoding import getKey
class FontSampleDisplayView(NSView):
"""
Display WordOfTheDay with the preferred font and color
"""
def drawRect_(self, rect):
defaults = NSUserDefaultsController.sharedUserDefaultsController().values()
favoriteColor = NSUnarchiver.unarchiveObjectWithData_(
getKey(defaults, "FavoriteColor")
)
fontName = getKey(defaults, "FontName")
fontSize = getKey(defaults, "FontSize")
favoriteFont = NSFont.fontWithName_size_(fontName, fontSize)
wordOfTheDay = getKey(defaults, "WordOfTheDay")
# Do the actual drawing
myBounds = self.bounds() # = (x, y), (bw, bh)
NSDrawLightBezel(myBounds, myBounds)
favoriteColor.set()
NSRectFill(NSInsetRect(myBounds, 2, 2))
attrsDictionary = {NSFontAttributeName: favoriteFont}
attrString = NSAttributedString.alloc().initWithString_attributes_(
wordOfTheDay, attrsDictionary
)
attrSize = attrString.size() # = (bw, bh)
attrString.drawAtPoint_(
NSMakePoint(
(attrSize.width / -2) + (myBounds.size.width / 2),
(attrSize.height / -2) + (myBounds.size.height / 2),
)
)
def initWithFrame_(self, frameRect):
self = super().initWithFrame_(frameRect)
dnc = NSNotificationCenter.defaultCenter()
dnc.addObserver_selector_name_object_(
self, "redisplay:", NSUserDefaultsDidChangeNotification, None
)
return self
def redisplay_(self, sender):
self.setNeedsDisplay_(True)
PreferencesPanelController.py¶
#
# PreferencesPanelController.py
# ControlledPreferences
#
# Converted by u.fiedler on 04.02.05.
# with great help from Bob Ippolito - Thank you Bob!
#
# The original version was written in Objective-C by Malcolm Crawford
# at http://homepage.mac.com/mmalc/CocoaExamples/controllers.html
import objc
from Cocoa import (
NSArchiver,
NSColor,
NSFont,
NSFontManager,
NSUserDefaultsController,
NSValueTransformer,
NSWindowController,
)
from FontNameToDisplayNameTransformer import FontNameToDisplayNameTransformer
from PyObjCTools.KeyValueCoding import getKey
class PreferencesPanelController(NSWindowController):
@objc.IBAction
def changeTextFont_(self, sender):
"""The user changed the current font selection, so update the default font"""
# Get font name and size from user defaults
defaults = NSUserDefaultsController.sharedUserDefaultsController().values()
fontName = getKey(defaults, "FontName")
fontSize = getKey(defaults, "FontSize")
# Create font from name and size; initialize font panel
font = NSFont.fontWithName_size_(fontName, fontSize)
if font is None:
font = NSFont.systemFontOfSize_(NSFont.systemFontSize())
NSFontManager.sharedFontManager().setSelectedFont_isMultiple_(font, False)
NSFontManager.sharedFontManager().orderFrontFontPanel_(self)
# Set window as firstResponder so we get changeFont: messages
self.window().makeFirstResponder_(self.window())
@objc.IBAction
def changeFont_(self, sender):
"""This is the message the font panel sends when a new font is selected"""
# Get selected font
fontManager = NSFontManager.sharedFontManager()
selectedFont = fontManager.selectedFont()
if selectedFont is None:
selectedFont = NSFont.systemFontOfSize_(NSFont.systemFontSize())
panelFont = fontManager.convertFont_(selectedFont)
# Get and store details of selected font
# Note: use fontName, not displayName. The font name identifies the font to
# the system, we use a value transformer to show the user the display name
fontSize = panelFont.pointSize()
defaults = NSUserDefaultsController.sharedUserDefaultsController().values()
defaults.setValue_forKey_(panelFont.fontName(), "FontName")
defaults.setValue_forKey_(fontSize, "FontSize")
# Set up initial values for defaults:
# Create dictionary with keys and values for WordOfTheDay, FontName,
# FontSize, and FavoriteColor. Mostly straightforward, but:
#
# Store the fontName of the font as the default; the textfield displays
# the font's displayName using a value transformer.
#
# The color must be archived -- you can't store NSColors directly in NSUserDefaults.
dictionary = {}
dictionary["WordOfTheDay"] = "Today"
systemFont = NSFont.systemFontOfSize_(NSFont.systemFontSize())
dictionary["FontName"] = systemFont.fontName()
dictionary["FontSize"] = systemFont.pointSize()
archivedColor = NSArchiver.archivedDataWithRootObject_(NSColor.greenColor())
dictionary["FavoriteColor"] = archivedColor
NSUserDefaultsController.sharedUserDefaultsController().setInitialValues_(dictionary)
# Create and register font name value transformer
transformer = FontNameToDisplayNameTransformer.alloc().init()
NSValueTransformer.setValueTransformer_forName_(
transformer, "FontNameToDisplayNameTransformer"
)
setup.py¶
"""
Script for building the example:
Usage:
python3 setup.py py2app
"""
from setuptools import setup
setup(
name="ControlledPreferences",
app=["ControlledPreferences.py"],
data_files=["English.lproj"],
setup_requires=["py2app", "pyobjc-framework-Cocoa"],
)