"""browsepict - Display all "PICT" resources found"""

import FrameWork
import EasyDialogs
from Carbon import Res
from Carbon import Qd
from Carbon import Win
from Carbon import List
import sys
import struct
import macresource

#
# Resource definitions
ID_MAIN=512
MAIN_LIST=1
MAIN_SHOW=2

# Where is the picture window?
LEFT=200
TOP=64

def main():
    macresource.need('DLOG', ID_MAIN, "oldPICTbrowse.rsrc")
    PICTbrowse()

class PICTbrowse(FrameWork.Application):
    def __init__(self):
        # First init menus, etc.
        FrameWork.Application.__init__(self)
        # Next create our dialog
        self.main_dialog = MyDialog(self)
        # Now open the dialog
        contents = self.findPICTresources()
        self.main_dialog.open(ID_MAIN, contents)
        # Finally, go into the event loop
        self.mainloop()

    def makeusermenus(self):
        self.filemenu = m = FrameWork.Menu(self.menubar, "File")
        self.quititem = FrameWork.MenuItem(m, "Quit", "Q", self.quit)

    def quit(self, *args):
        self._quit()

    def showPICT(self, resid):
        w = PICTwindow(self)
        w.open(resid)
        #EasyDialogs.Message('Show PICT %r' % (resid,))

    def findPICTresources(self):
        num = Res.CountResources('PICT')
        rv = []
        for i in range(1, num+1):
            Res.SetResLoad(0)
            try:
                r = Res.GetIndResource('PICT', i)
            finally:
                Res.SetResLoad(1)
            id, type, name = r.GetResInfo()
            rv.append((id, name))
        return rv

class PICTwindow(FrameWork.Window):
    def open(self, (resid, resname)):
        if not resname:
            resname = '#%r' % (resid,)
        self.resid = resid
        picture = Qd.GetPicture(self.resid)
        # Get rect for picture
        print repr(picture.data[:16])
        sz, t, l, b, r = struct.unpack('hhhhh', picture.data[:10])
        print 'pict:', t, l, b, r
        width = r-l
        height = b-t
        if width < 64: width = 64
        elif width > 480: width = 480
        if height < 64: height = 64
        elif height > 320: height = 320
        bounds = (LEFT, TOP, LEFT+width, TOP+height)
        print 'bounds:', bounds

        self.wid = Win.NewWindow(bounds, resname, 1, 0, -1, 1, 0)
        self.wid.SetWindowPic(picture)
        self.do_postopen()

class MyDialog(FrameWork.DialogWindow):
    "Main dialog window for PICTbrowse"

    def open(self, id, contents):
        self.id = id
        FrameWork.DialogWindow.open(self, ID_MAIN)
        self.dlg.SetDialogDefaultItem(MAIN_SHOW)
        tp, h, rect = self.dlg.GetDialogItem(MAIN_LIST)
        rect2 = rect[0]+1, rect[1]+1, rect[2]-17, rect[3]-17    # Scroll bar space
        self.list = List.LNew(rect2, (0, 0, 1, len(contents)), (0,0), 0, self.wid,
                        0, 1, 1, 1)
        self.contents = contents
        self.setlist()

    def setlist(self):
        self.list.LDelRow(0, 0)
        self.list.LSetDrawingMode(0)
        if self.contents:
            self.list.LAddRow(len(self.contents), 0)
            for i in range(len(self.contents)):
                v = repr(self.contents[i][0])
                if self.contents[i][1]:
                    v = v + '"' + self.contents[i][1] + '"'
                self.list.LSetCell(v, (0, i))
        self.list.LSetDrawingMode(1)
        self.list.LUpdate(self.wid.GetWindowPort().visRgn)

    def do_listhit(self, event):
        (what, message, when, where, modifiers) = event
        Qd.SetPort(self.wid)
        where = Qd.GlobalToLocal(where)
        print 'LISTHIT', where
        if self.list.LClick(where, modifiers):
            self.do_show()

    def getselection(self):
        items = []
        point = (0,0)
        while 1:
            ok, point = self.list.LGetSelect(1, point)
            if not ok:
                break
            items.append(point[1])
            point = point[0], point[1]+1
        values = []
        for i in items:
            values.append(self.contents[i])
        return values

    def do_show(self, *args):
        selection = self.getselection()
        for resid in selection:
            self.parent.showPICT(resid)

    def do_rawupdate(self, window, event):
        tp, h, rect = self.dlg.GetDialogItem(MAIN_LIST)
        Qd.SetPort(self.wid)
        Qd.FrameRect(rect)
        self.list.LUpdate(self.wid.GetWindowPort().visRgn)

    def do_activate(self, activate, event):
        self.list.LActivate(activate)

    def do_close(self):
        self.close()

    def do_itemhit(self, item, event):
        if item == MAIN_LIST:
            self.do_listhit(event)
        if item == MAIN_SHOW:
            self.do_show()

main()
