PyObjC NSView

comipoli JXA 版の PyObjC 化を進めないと。

An introduction to PyObjC ? PyObjC ? the Python ? Objective-C bridge

Objective-c の関数は JXA ではコロンをキャメルケースで合体だった。
PyObjC ではスネークケース、最後のコロンもアンダーバー。

alloc は関数、JXA では関数に括弧不要だったけどこのほうが理解しやすい。
class の継承は Python の掟どおり、PyGObject と同様。

プロパティは何故か全部 ReadOnly になっている。
getter は関数のように括弧で呼び出し。
setter は全部 set*** メソッドを使ってくれということみたい。

上記には書いていないけど NSArray は添字アクセスできた。
もう少し詳しく解ったらまとめページでも作る、かも。

だいたい解ったところで JXA で書いた ComipoliView を書き換えてみる。

#!/usr/bin/env python3

import objc
from AppKit import *

class ComipoliView(NSView):
    def init(self):
        objc.super(ComipoliView, self).init()
        self.first_page = None
        self.second_page = None
        self.spread = False
        self.l_to_r = False
        return self

    def drawRect_(self, rect):
        NSColor.blackColor().set()
        NSRectFill(rect)
        if self.first_page != None:
            aw = rect.size.width
            ah = rect.size.height
            w = self.first_page.size().width
            h = self.first_page.size().height
            # Horizontal?
            if w - h > 0 or not self.spread:
                # Single Page
                width, height, x, y = 0
                if aw * h > ah * w:
                    width = w * ah / h
                    height = ah
                    x = (aw - width) / 2
                    y = 0
                else:
                    width = aw
                    height = h * aw / w
                    x = 0
                    y = (ah - height) / 2
                r1 = NSMakeRect(x, y, width, height)
                self.first_page.drawInRect_(r1)
            else:
                if self.second_page != None:
                    left = ah * w / h
                    if self.l_to_r:
                        r1 = NSMakeRect(aw / 2 - left, 0, left, ah)
                        self.first_page.drawInRect_(r1)
                        #
                        w2 = self.second_page.size().width
                        h2 = self.second_page.size().height
                        right = ah * w2 / h2
                        r2 = NSMakeRect(aw / 2, 0, right, ah)
                        self.second_page.drawInRect_(r2)
                    else:
                        r1 = NSMakeRect(aw / 2, 0, left, ah)
                        self.first_page.drawInRect_(r1)
                        #
                        w2 = self.second_page.size().width
                        h2 = self.second_page.size().height
                        right = ah * w2 / h2
                        r2 = NSMakeRect(aw / 2 - right, 0, right, ah)
                        self.second_page.drawInRect_(r2)

comipoli_view.py

#!/usr/bin/env python3

import objc
from AppKit import *
from comipoli_view import ComipoliView

class ComipoliWindow(NSWindow):
    def initWithFrame_(self, frame):
        #self = objc.super(ComipoliWindow, self).initWithContentRect_styleMask_backing_defer_(
        objc.super(ComipoliWindow, self).initWithContentRect_styleMask_backing_defer_(
            frame,
            NSTitledWindowMask |
            NSClosableWindowMask |
            NSResizableWindowMask |
            NSMiniaturizableWindowMask,
            NSBackingStoreBuffered,
            False)
        self.setTitle_('日本語')
        self.setDelegate_(self)
        # NSView
        self.view = ComipoliView.new()
        self.view.setFrameSize_(frame.size)
        self.view.first_page = NSImage.alloc().initWithContentsOfFile_('003.png')
        self.view.second_page = NSImage.alloc().initWithContentsOfFile_('004.png')
        self.view.spread = True
        self.contentView().addSubview_(self.view)
        #
        return self

    def windowDidResize_(self, sender):
        aw = self.contentView().frame().size.width
        ah = self.contentView().frame().size.height
        size = NSMakeSize(aw, ah)
        self.view.setFrameSize_(size)

    def windowWillClose_(self, sender):
        NSApp.terminate_(sender)

class AppDelegate(NSObject):
    def applicationDidFinishLaunching_(self, notification):
        pass

NSApplication.sharedApplication()

frame = NSMakeRect(100, 400, 320, 160)
window = ComipoliWindow.alloc().initWithFrame_(frame)
window.makeKeyAndOrderFront_(window)

main_menu = NSMenu.new()
item_app  = NSMenuItem.new()
main_menu.addItem_(item_app)
menu_app = NSMenu.new()
item_app.setSubmenu_(menu_app)
item_quit = NSMenuItem.new()
item_quit.initWithTitle_action_keyEquivalent_('Quit Comipoli', 'terminate:', 'q')
menu_app.addItem_(item_quit)
NSApp.setMainMenu_(main_menu)

NSApp.setDelegate_(AppDelegate.new())
NSApp.activateIgnoringOtherApps_(True)
NSApp.run()

comipoli_window.py

なるほど、これでいいんだ。
ついでに発見したけど、init で self に代入しなくてもいいのね。
というか、self に代入って変だろ。。。。。

どうでもいいおまけ。
NSMatrix ってのがあるんだ、おぉ!って思ったけど。
GTK+ でいう GtkRadioButton の grope 化だった、まぎらわしいYO!