# ToDos

- `Download example`

Shows two array controllers, one to manage the contents of a table view, the other to manage a pop-up menu in a table column. Also shows two value transformers to alter the color of text.

Originally from “Cocoa Bindings Examples and Hints”, converted to PyObjC by u.fiedler.

## Sources

### Category.py

    #
    #  Category.py
    #  ToDos
    #
    #  Converted by u.fiedler on 09.02.05.
    #
    #  The original version was written in Objective-C by Malcolm Crawford
    #  at http://homepage.mac.com/mmalc/CocoaExamples/controllers.html

    import objc
    from Foundation import NSObject

    class Category(NSObject):
        title = objc.ivar("title")
        priority = objc.ivar("priority", objc._C_INT)

        @classmethod
        def allCategories(cls):
            """Predefined global list of categories"""
            return categories

        @classmethod
        def categoryForPriority_(cls, thePriority):
            for category in categories:
                if thePriority >= category.priority:
                    return category
            return None

        @classmethod
        def categoryWithTitle_andPriority_(cls, aTitle, aValue):
            """Convenience constructor"""
            newCategory = Category.alloc().init()
            newCategory.title = aTitle
            newCategory.priority = aValue
            return newCategory

        # NSCoding methods
        # To encode, simply save 'priority'; on decode, replace self with
        # the existing instance from 'allCategories' with the same priority

        def encodeWithCoder_(self, encoder):
            if encoder.allowsKeyedCoding():
                encoder.encodeInt_forKey_(self.priority, "priority")
            else:
                encoder.encodeObject_(self.priority)

        def initWithCoder_(self, decoder):
            if decoder.allowsKeyedCoding():
                thePriority = decoder.decodeIntForKey_("priority")
            else:
                thePriority = decoder.decodeObject()
            return Category.categoryForPriority_(thePriority)

    categories = [
        Category.categoryWithTitle_andPriority_("Vital", 11),
        Category.categoryWithTitle_andPriority_("Very Important", 4),
        Category.categoryWithTitle_andPriority_("Important", 3),
        Category.categoryWithTitle_andPriority_("Not Important", 2),
        Category.categoryWithTitle_andPriority_("Whenever", 0),
    ]

### OverdueTransformer.py

    #
    #  OverdueTransformer.py
    #  ToDos
    #
    #  Converted by u.fiedler on 09.02.05.
    #
    #  The original version was written in Objective-C by Malcolm Crawford
    #  at http://homepage.mac.com/mmalc/CocoaExamples/controllers.html

    from Cocoa import NSColor, NSValueTransformer

    class OverdueTransformer(NSValueTransformer):
        @classmethod
        def transformedValueClass(cls):
            return NSColor

        @classmethod
        def allowsReverseTransformation(cls):
            return False

        def transformedValue_(self, aDate):
            if aDate is None:
                return None
            if aDate.timeIntervalSinceNow() < 0:
                return NSColor.redColor()
            return NSColor.blackColor()

### PriorityToColourTransformer.py

    #
    #  PriorityToColourTransformer.py
    #  ToDos
    #
    #  Converted by u.fiedler on 09.02.05.
    #
    #  The original version was written in Objective-C by Malcolm Crawford
    #  at http://homepage.mac.com/mmalc/CocoaExamples/controllers.html

    from Cocoa import NSColor, NSValueTransformer

    class PriorityToColourTransformer(NSValueTransformer):
        @classmethod
        def transformedValueClass(cls):
            return NSColor

        @classmethod
        def allowsReverseTransformation(cls):
            return False

        def transformedValue_(self, priority):
            if priority is None:
                return NSColor.blackColor()
            elif priority > 4:
                return NSColor.redColor()
            elif priority > 3:
                return NSColor.orangeColor()
            elif priority > 2:
                return NSColor.blueColor()
            elif priority > 1:
                return NSColor.greenColor()
            elif priority > 0:
                return NSColor.brownColor()
            else:
                return NSColor.blackColor()

### ToDos.py

    import ToDosDocument  # noqa: F401

    if __name__ == "__main__":
        from PyObjCTools import AppHelper

        AppHelper.runEventLoop()

### ToDosDocument.py

    #
    #  ToDosDocument.py
    #  ToDos
    #
    #  Converted by u.fiedler on 09.02.05.
    #
    #  The original version was written in Objective-C by Malcolm Crawford
    #  at http://homepage.mac.com/mmalc/CocoaExamples/controllers.html

    import objc
    from Category import Category
    from Cocoa import (
        NSDocument,
        NSKeyedArchiver,
        NSKeyedUnarchiver,
        NSMutableArray,
        NSValueTransformer,
    )
    from objc import super
    from OverdueTransformer import OverdueTransformer
    from PriorityToColourTransformer import PriorityToColourTransformer

    class ToDosDocument(NSDocument):
        nix = objc.IBOutlet()
        toDos = objc.ivar()

        def init(self):
            self = super(ToDosDocument, self).init()
            if self is None:
                return None
            self.toDos = NSMutableArray()
            return self  # if this line is missing you will get the
            # simple message: "Can't create new document"

        def categories(self):
            return Category.allCategories()

        def windowNibName(self):
            return "ToDosDocument"

        def dataRepresentationOfType_(self, aType):
            return NSKeyedArchiver.archivedDataWithRootObject_(self.toDos)

        def loadDataRepresentation_ofType_(self, data, aType):
            self.toDos = NSKeyedUnarchiver.unarchiveObjectWithData_(data)
            return True

    priorityTransformer = PriorityToColourTransformer.alloc().init()
    NSValueTransformer.setValueTransformer_forName_(
        priorityTransformer, "PriorityToColourTransformer"
    )

    overdueTransformer = OverdueTransformer.alloc().init()
    NSValueTransformer.setValueTransformer_forName_(
        overdueTransformer, "OverdueTransformer"
    )

### setup.py

    """
    Script for building the example:

    Usage:
        python3 setup.py py2app
    """
    from setuptools import setup

    plist = {
        "CFBundleDocumentTypes": [
            {
                "CFBundleTypeExtensions": ["ToDos", "*"],
                "CFBundleTypeName": "ToDos File",
                "CFBundleTypeRole": "Editor",
                "NSDocumentClass": "ToDosDocument",
            }
        ]
    }

    setup(
        name="ToDos",
        app=["ToDos.py"],
        data_files=["English.lproj"],
        options={"py2app": {"plist": plist}},
        setup_requires=["py2app", "pyobjc-framework-Cocoa"],
    )