Import Upstream version 2.7.18
161
Mac/Demo/PICTbrowse/ICONbrowse.py
Normal file
@@ -0,0 +1,161 @@
|
||||
"""browsepict - Display all "ICON" resources found"""
|
||||
|
||||
import FrameWork
|
||||
import EasyDialogs
|
||||
from Carbon import Res
|
||||
from Carbon import Qd
|
||||
from Carbon import Win
|
||||
from Carbon import Controls
|
||||
from Carbon import List
|
||||
from Carbon import Icn
|
||||
import macresource
|
||||
|
||||
#
|
||||
# Resource definitions
|
||||
ID_MAIN=512
|
||||
MAIN_LIST=1
|
||||
MAIN_SHOW=2
|
||||
|
||||
# Where is the picture window?
|
||||
LEFT=200
|
||||
TOP=64
|
||||
MINWIDTH=32
|
||||
MINHEIGHT=32
|
||||
MAXWIDTH=320
|
||||
MAXHEIGHT=320
|
||||
|
||||
def main():
|
||||
macresource.need('DLOG', ID_MAIN, "PICTbrowse.rsrc")
|
||||
ICONbrowse()
|
||||
|
||||
class ICONbrowse(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.findICONresources()
|
||||
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 showICON(self, resid):
|
||||
w = ICONwindow(self)
|
||||
w.open(resid)
|
||||
#EasyDialogs.Message('Show ICON %r' % (resid,))
|
||||
|
||||
def findICONresources(self):
|
||||
num = Res.CountResources('ICON')
|
||||
rv = []
|
||||
for i in range(1, num+1):
|
||||
Res.SetResLoad(0)
|
||||
try:
|
||||
r = Res.GetIndResource('ICON', i)
|
||||
finally:
|
||||
Res.SetResLoad(1)
|
||||
id, type, name = r.GetResInfo()
|
||||
rv.append((id, name))
|
||||
return rv
|
||||
|
||||
class ICONwindow(FrameWork.Window):
|
||||
def open(self, (resid, resname)):
|
||||
if not resname:
|
||||
resname = '#%r' % (resid,)
|
||||
self.resid = resid
|
||||
self.picture = Icn.GetIcon(self.resid)
|
||||
l, t, r, b = 0, 0, 32, 32
|
||||
self.pictrect = (l, t, r, b)
|
||||
width = r-l
|
||||
height = b-t
|
||||
if width < MINWIDTH: width = MINWIDTH
|
||||
elif width > MAXWIDTH: width = MAXWIDTH
|
||||
if height < MINHEIGHT: height = MINHEIGHT
|
||||
elif height > MAXHEIGHT: height = MAXHEIGHT
|
||||
bounds = (LEFT, TOP, LEFT+width, TOP+height)
|
||||
|
||||
self.wid = Win.NewWindow(bounds, resname, 1, 0, -1, 1, 0)
|
||||
self.do_postopen()
|
||||
|
||||
def do_update(self, *args):
|
||||
currect = self.fitrect()
|
||||
Icn.PlotIcon(currect, self.picture)
|
||||
|
||||
def fitrect(self):
|
||||
"""Return self.pictrect scaled to fit in window"""
|
||||
graf = self.wid.GetWindowPort()
|
||||
screenrect = graf.GetPortBounds()
|
||||
picwidth = self.pictrect[2] - self.pictrect[0]
|
||||
picheight = self.pictrect[3] - self.pictrect[1]
|
||||
if picwidth > screenrect[2] - screenrect[0]:
|
||||
factor = float(picwidth) / float(screenrect[2]-screenrect[0])
|
||||
picwidth = picwidth / factor
|
||||
picheight = picheight / factor
|
||||
if picheight > screenrect[3] - screenrect[1]:
|
||||
factor = float(picheight) / float(screenrect[3]-screenrect[1])
|
||||
picwidth = picwidth / factor
|
||||
picheight = picheight / factor
|
||||
return (screenrect[0], screenrect[1], screenrect[0]+int(picwidth),
|
||||
screenrect[1]+int(picheight))
|
||||
|
||||
class MyDialog(FrameWork.DialogWindow):
|
||||
"Main dialog window for ICONbrowse"
|
||||
|
||||
def open(self, id, contents):
|
||||
self.id = id
|
||||
FrameWork.DialogWindow.open(self, ID_MAIN)
|
||||
self.dlg.SetDialogDefaultItem(MAIN_SHOW)
|
||||
self.contents = contents
|
||||
self.ctl = self.dlg.GetDialogItemAsControl(MAIN_LIST)
|
||||
h = self.ctl.GetControlData_Handle(Controls.kControlListBoxPart,
|
||||
Controls.kControlListBoxListHandleTag)
|
||||
self.list = List.as_List(h)
|
||||
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 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.showICON(resid)
|
||||
|
||||
def do_close(self):
|
||||
self.close()
|
||||
|
||||
def do_itemhit(self, item, event):
|
||||
if item == MAIN_SHOW:
|
||||
self.do_show()
|
||||
|
||||
main()
|
||||
140
Mac/Demo/PICTbrowse/PICTbrowse.py
Normal file
@@ -0,0 +1,140 @@
|
||||
"""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 Controls
|
||||
from Carbon import List
|
||||
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, "PICTbrowse.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)
|
||||
self.contents = contents
|
||||
self.ctl = self.dlg.GetDialogItemAsControl(MAIN_LIST)
|
||||
h = self.ctl.GetControlData_Handle(Controls.kControlListBoxPart,
|
||||
Controls.kControlListBoxListHandleTag)
|
||||
self.list = List.as_List(h)
|
||||
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 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_close(self):
|
||||
self.close()
|
||||
|
||||
def do_itemhit(self, item, event):
|
||||
if item == MAIN_SHOW:
|
||||
self.do_show()
|
||||
|
||||
main()
|
||||
BIN
Mac/Demo/PICTbrowse/PICTbrowse.rsrc
Normal file
162
Mac/Demo/PICTbrowse/PICTbrowse2.py
Normal file
@@ -0,0 +1,162 @@
|
||||
"""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 Controls
|
||||
from Carbon import List
|
||||
import struct
|
||||
import macresource
|
||||
|
||||
#
|
||||
# Resource definitions
|
||||
ID_MAIN=512
|
||||
MAIN_LIST=1
|
||||
MAIN_SHOW=2
|
||||
|
||||
# Where is the picture window?
|
||||
LEFT=200
|
||||
TOP=64
|
||||
MINWIDTH=64
|
||||
MINHEIGHT=64
|
||||
MAXWIDTH=320
|
||||
MAXHEIGHT=320
|
||||
|
||||
def main():
|
||||
macresource.need('DLOG', ID_MAIN, "PICTbrowse.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
|
||||
self.picture = Qd.GetPicture(self.resid)
|
||||
# Get rect for picture
|
||||
sz, t, l, b, r = struct.unpack('hhhhh', self.picture.data[:10])
|
||||
self.pictrect = (l, t, r, b)
|
||||
width = r-l
|
||||
height = b-t
|
||||
if width < MINWIDTH: width = MINWIDTH
|
||||
elif width > MAXWIDTH: width = MAXWIDTH
|
||||
if height < MINHEIGHT: height = MINHEIGHT
|
||||
elif height > MAXHEIGHT: height = MAXHEIGHT
|
||||
bounds = (LEFT, TOP, LEFT+width, TOP+height)
|
||||
|
||||
self.wid = Win.NewWindow(bounds, resname, 1, 0, -1, 1, 0)
|
||||
self.do_postopen()
|
||||
|
||||
def do_update(self, *args):
|
||||
currect = self.fitrect()
|
||||
Qd.DrawPicture(self.picture, currect)
|
||||
|
||||
def fitrect(self):
|
||||
"""Return self.pictrect scaled to fit in window"""
|
||||
graf = self.dlg.GetWindowPort()
|
||||
screenrect = graf.GetPortBounds()
|
||||
picwidth = self.pictrect[2] - self.pictrect[0]
|
||||
picheight = self.pictrect[3] - self.pictrect[1]
|
||||
if picwidth > screenrect[2] - screenrect[0]:
|
||||
factor = float(picwidth) / float(screenrect[2]-screenrect[0])
|
||||
picwidth = picwidth / factor
|
||||
picheight = picheight / factor
|
||||
if picheight > screenrect[3] - screenrect[1]:
|
||||
factor = float(picheight) / float(screenrect[3]-screenrect[1])
|
||||
picwidth = picwidth / factor
|
||||
picheight = picheight / factor
|
||||
return (screenrect[0], screenrect[1], screenrect[0]+int(picwidth),
|
||||
screenrect[1]+int(picheight))
|
||||
|
||||
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)
|
||||
self.contents = contents
|
||||
self.ctl = self.dlg.GetDialogItemAsControl(MAIN_LIST)
|
||||
h = self.ctl.GetControlData_Handle(Controls.kControlListBoxPart,
|
||||
Controls.kControlListBoxListHandleTag)
|
||||
self.list = List.as_List(h)
|
||||
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 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_close(self):
|
||||
self.close()
|
||||
|
||||
def do_itemhit(self, item, event):
|
||||
if item == MAIN_SHOW:
|
||||
self.do_show()
|
||||
|
||||
main()
|
||||
161
Mac/Demo/PICTbrowse/cicnbrowse.py
Normal file
@@ -0,0 +1,161 @@
|
||||
"""browsepict - Display all "cicn" resources found"""
|
||||
|
||||
import FrameWork
|
||||
import EasyDialogs
|
||||
from Carbon import Res
|
||||
from Carbon import Qd
|
||||
from Carbon import Win
|
||||
from Carbon import Controls
|
||||
from Carbon import List
|
||||
from Carbon import Icn
|
||||
import macresource
|
||||
|
||||
#
|
||||
# Resource definitions
|
||||
ID_MAIN=512
|
||||
MAIN_LIST=1
|
||||
MAIN_SHOW=2
|
||||
|
||||
# Where is the picture window?
|
||||
LEFT=200
|
||||
TOP=64
|
||||
MINWIDTH=32
|
||||
MINHEIGHT=32
|
||||
MAXWIDTH=320
|
||||
MAXHEIGHT=320
|
||||
|
||||
def main():
|
||||
macresource.need('DLOG', ID_MAIN, "PICTbrowse.rsrc")
|
||||
CIconbrowse()
|
||||
|
||||
class CIconbrowse(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.findcicnresources()
|
||||
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 showCIcon(self, resid):
|
||||
w = CIconwindow(self)
|
||||
w.open(resid)
|
||||
#EasyDialogs.Message('Show cicn %r' % (resid,))
|
||||
|
||||
def findcicnresources(self):
|
||||
num = Res.CountResources('cicn')
|
||||
rv = []
|
||||
for i in range(1, num+1):
|
||||
Res.SetResLoad(0)
|
||||
try:
|
||||
r = Res.GetIndResource('cicn', i)
|
||||
finally:
|
||||
Res.SetResLoad(1)
|
||||
id, type, name = r.GetResInfo()
|
||||
rv.append((id, name))
|
||||
return rv
|
||||
|
||||
class CIconwindow(FrameWork.Window):
|
||||
def open(self, (resid, resname)):
|
||||
if not resname:
|
||||
resname = '#%r' % (resid,)
|
||||
self.resid = resid
|
||||
self.picture = Icn.GetCIcon(self.resid)
|
||||
l, t, r, b = 0, 0, 32, 32
|
||||
self.pictrect = (l, t, r, b)
|
||||
width = r-l
|
||||
height = b-t
|
||||
if width < MINWIDTH: width = MINWIDTH
|
||||
elif width > MAXWIDTH: width = MAXWIDTH
|
||||
if height < MINHEIGHT: height = MINHEIGHT
|
||||
elif height > MAXHEIGHT: height = MAXHEIGHT
|
||||
bounds = (LEFT, TOP, LEFT+width, TOP+height)
|
||||
|
||||
self.wid = Win.NewWindow(bounds, resname, 1, 0, -1, 1, 0)
|
||||
self.do_postopen()
|
||||
|
||||
def do_update(self, *args):
|
||||
currect = self.fitrect()
|
||||
Icn.PlotCIcon(currect, self.picture)
|
||||
|
||||
def fitrect(self):
|
||||
"""Return self.pictrect scaled to fit in window"""
|
||||
graf = self.wid.GetWindowPort()
|
||||
screenrect = graf.GetPortBounds()
|
||||
picwidth = self.pictrect[2] - self.pictrect[0]
|
||||
picheight = self.pictrect[3] - self.pictrect[1]
|
||||
if picwidth > screenrect[2] - screenrect[0]:
|
||||
factor = float(picwidth) / float(screenrect[2]-screenrect[0])
|
||||
picwidth = picwidth / factor
|
||||
picheight = picheight / factor
|
||||
if picheight > screenrect[3] - screenrect[1]:
|
||||
factor = float(picheight) / float(screenrect[3]-screenrect[1])
|
||||
picwidth = picwidth / factor
|
||||
picheight = picheight / factor
|
||||
return (screenrect[0], screenrect[1], screenrect[0]+int(picwidth),
|
||||
screenrect[1]+int(picheight))
|
||||
|
||||
class MyDialog(FrameWork.DialogWindow):
|
||||
"Main dialog window for cicnbrowse"
|
||||
|
||||
def open(self, id, contents):
|
||||
self.id = id
|
||||
FrameWork.DialogWindow.open(self, ID_MAIN)
|
||||
self.dlg.SetDialogDefaultItem(MAIN_SHOW)
|
||||
self.contents = contents
|
||||
self.ctl = self.dlg.GetDialogItemAsControl(MAIN_LIST)
|
||||
h = self.ctl.GetControlData_Handle(Controls.kControlListBoxPart,
|
||||
Controls.kControlListBoxListHandleTag)
|
||||
self.list = List.as_List(h)
|
||||
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 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.showCIcon(resid)
|
||||
|
||||
def do_close(self):
|
||||
self.close()
|
||||
|
||||
def do_itemhit(self, item, event):
|
||||
if item == MAIN_SHOW:
|
||||
self.do_show()
|
||||
|
||||
main()
|
||||
158
Mac/Demo/PICTbrowse/oldPICTbrowse.py
Normal file
@@ -0,0 +1,158 @@
|
||||
"""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 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()
|
||||
BIN
Mac/Demo/PICTbrowse/oldPICTbrowse.rsrc
Normal file
362
Mac/Demo/applescript.html
Normal file
@@ -0,0 +1,362 @@
|
||||
<!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
|
||||
<html><head><title>Using the Open Scripting Architecture from Python</title></head>
|
||||
<body>
|
||||
<h1>Using the Open Scripting Architecture from Python</h1>
|
||||
<hr>
|
||||
|
||||
<p><b>NOTE:</b> this document describes the OSA support that is shipped with
|
||||
the core python distribution. Most users are better of with the more
|
||||
userfriendly <a href="http://freespace.virgin.net/hamish.sanderson/appscript.html">appscript library</a>.
|
||||
|
||||
<p>OSA support in Python is still not 100% complete, but
|
||||
there is already enough in place to allow you to do some nifty things
|
||||
with other programs from your python program. </p>
|
||||
|
||||
|
||||
<p>
|
||||
In this example, we will look at a scriptable application, extract its
|
||||
“AppleScript Dictionary,” generate a Python interface package from
|
||||
the dictionary, and use that package to control the application.
|
||||
The application we are going to script is Disk Copy, Apple's standard
|
||||
utility for making copies of floppies, creating files that are mountable
|
||||
as disk images, etc.
|
||||
Because we want
|
||||
to concentrate on the OSA details, we won’t bother with a real
|
||||
user-interface for our application. </p>
|
||||
|
||||
|
||||
<p>
|
||||
<em>When we say “AppleScript” in this document we actually mean
|
||||
“the Open Scripting Architecture.” There is nothing
|
||||
AppleScript-specific in the Python implementation. Most of this document
|
||||
focuses on the classic Mac OS; <a href="#osx">Mac OS X</a> users have some
|
||||
additional tools.</em>
|
||||
</p>
|
||||
|
||||
<h2>Python OSA architecture</h2>
|
||||
|
||||
<p>Open Scripting suites and inheritance can be modelled rather nicely
|
||||
with Python packages, so we generate
|
||||
a package for each application we want to script. Each suite defined in
|
||||
the application becomes a module in the
|
||||
package, and the package main module imports everything from all the
|
||||
submodules and glues together all the classes (in Python terminology—
|
||||
events in OSA terminology or verbs in AppleScript terminology). </p>
|
||||
|
||||
<p>
|
||||
A suite in an OSA application can extend the functionality of a standard
|
||||
suite. This is implemented in Python by importing everything from the
|
||||
module that implements the standard suites and overriding anything that has
|
||||
been extended. The standard suites live in the StdSuite package. </p>
|
||||
|
||||
<p>
|
||||
This all sounds complicated, but the good news is that basic
|
||||
scripting is actually pretty simple. You can do strange and wondrous things
|
||||
with OSA scripting once you fully understand it. </p>
|
||||
|
||||
<h2>Creating the Python interface package</h2>
|
||||
|
||||
|
||||
<p>There is a tool in the standard distribution that can automatically
|
||||
generate the interface packages. This tool is called
|
||||
<code>gensuitemodule.py</code>, and lives in <code>Mac:scripts</code>.
|
||||
It looks through a file
|
||||
for an ‘AETE’ or ‘AEUT’ resource,
|
||||
the internal representation of the
|
||||
AppleScript dictionary, and parses the resource to generate the suite
|
||||
modules.
|
||||
When we start <code>gensuitemodule</code>, it asks us for an input file;
|
||||
for our example,
|
||||
we point it to the Disk Copy executable. </p>
|
||||
|
||||
<p>
|
||||
Next, <code>gensuitemodule</code> wants a folder where it will store the
|
||||
package it is going to generate.
|
||||
Note that this is the package folder, not the parent folder, so we
|
||||
navigate to <code>Python:Mac:Demo:applescript</code>, create a folder
|
||||
<code>Disk_Copy</code>, and select that. </p>
|
||||
|
||||
<p>
|
||||
We next specify the folder from which <code>gensuitemodule</code>
|
||||
should import the standard suites. Here,
|
||||
we always select <code>Python:Mac:Lib:lib-scriptpackages:StdSuites</code>. (There is
|
||||
one exception to this rule: when you are generating <code>StdSuites</code> itself
|
||||
you select <code>_builtinSuites</code>.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
It starts parsing the AETE resource, and for
|
||||
each AppleEvent suite it finds, <code>gensuitemodule.py</code>
|
||||
prompts us for the filename of the
|
||||
resulting python module. Remember to change folders for the first
|
||||
module—you don't want to clutter up, say, the
|
||||
Disk Copy folder
|
||||
with your python
|
||||
interfaces. If you want to skip a suite, press <code>cancel</code> and the process
|
||||
continues with the next suite. </p>
|
||||
|
||||
<h3>Summary</h3>
|
||||
|
||||
<ol>
|
||||
|
||||
<li>Run <code>gensuitemodule</code>.</li>
|
||||
|
||||
<li>Select the application (or OSAX) for which you would like a Python interface.</li>
|
||||
|
||||
<li>Select the package folder where the interface modules should be
|
||||
stored.</li>
|
||||
|
||||
<li>Specify the folder <code>Python:Mac:Lib:lib-scriptpackages:StdSuites</code>
|
||||
to import the standard suites (or <code>_builtinSuites</code> if you are
|
||||
generating <code>StdSuites</code> itself). </li>
|
||||
|
||||
<li>Save the generated suites (use <code>cancel</code> to skip a suite).</li>
|
||||
|
||||
|
||||
</ol>
|
||||
|
||||
|
||||
<h3>Notes</h3>
|
||||
|
||||
|
||||
<ul>
|
||||
|
||||
<li>The interface package may occasionally need some editing by hand. For example,
|
||||
<code>gensuitemodule</code> does not handle all Python reserved words, so
|
||||
if
|
||||
one of the AppleScript verbs is a Python reserved word, a <code>SyntaxError</code>
|
||||
may be raised when the package is imported.
|
||||
Simply rename the class into something acceptable, if this happens;
|
||||
take a look at how the
|
||||
<code>print</code> verb is handled (automatically by <code>gensuitemodule</code>)
|
||||
in the standard suites. But: f you need to edit your package this should be considered a
|
||||
bug in gensuitemodule, so please report it so it can be fixed in future releases.
|
||||
</li>
|
||||
|
||||
|
||||
<li>If you want to re-create the StdSuite modules,
|
||||
you should look in one of two places. With versions of AppleScript older than 1.4.0
|
||||
(which first shipped with OS 9.0), you will find the
|
||||
AEUT resources in <code>System Folder:Extensions:Scripting
|
||||
Additions:Dialects:English Dialect</code>. For newer versions, you will
|
||||
find them in <code>System Folder:Extensions:Applescript</code>.
|
||||
</li>
|
||||
|
||||
<li>Since MacPython 2.0, this new structure, with packages
|
||||
per application and submodules per suite, is used. Older MacPythons had a
|
||||
single level of modules, with uncertain semantics. With the new structure,
|
||||
it is possible for programs to override standard suites, as programs often do.
|
||||
|
||||
</li>
|
||||
|
||||
<li><code>Gensuitemodule.py</code> may ask you questions
|
||||
like “Where is enum 'xyz ' declared?”.
|
||||
This is either due to a misunderstanding on my part or (rather too commonly)
|
||||
bugs in the AETE resources. Pressing <code>cancel</code> is usually the
|
||||
right choice: it will cause the specific enum not to be treated as an enum
|
||||
but as a “normal” type. As things like fsspecs and TEXT strings clearly are
|
||||
not enumerators, this is correct. If someone understands what is really going on
|
||||
here, please let me know.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<h2>The Python interface package contents</h2>
|
||||
|
||||
<p>
|
||||
Let’s glance at the
|
||||
<a href="applescript/Disk_Copy">Disk_Copy</a> package just created. You
|
||||
may want to open Script Editor alongside to see how it
|
||||
interprets the dictionary.
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
The main package module is in <code>__init__.py</code>.
|
||||
The only interesting bit is the <code>Disk_Copy</code> class, which
|
||||
includes the event handling classes from the individual suites. It also
|
||||
inherits <code>aetools.TalkTo</code>, which is a base class that handles all
|
||||
details on how to start the program and talk to it, and a class variable
|
||||
<code>_signature</code> which is the default application this class will talk
|
||||
to (you can override this in various ways when you instantiate your class, see
|
||||
<code>aetools.py</code> for details).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <a href="applescript/Disk_Copy/Special_Events.py">Special_Events</a>
|
||||
module is a nice example of a suite module.
|
||||
The <code>Special_Events_Events</code> class is the bulk of the code
|
||||
generated. For each verb, it contains a method. Each method knows what
|
||||
arguments the verb expects, and it makes use of keyword
|
||||
arguments to present a palatable
|
||||
interface to the python programmer.
|
||||
|
||||
Notice that each method
|
||||
calls some routines from <code>aetools</code>, an auxiliary module
|
||||
living in <code>Mac:Lib</code>.
|
||||
The other thing to notice is that each method calls
|
||||
<code>self.send</code>. This comes from the <code>aetools.TalkTo</code>
|
||||
baseclass. </p>
|
||||
|
||||
|
||||
<p>
|
||||
After the big class, there are a number of little class declarations. These
|
||||
declarations are for the (AppleEvent) classes and properties in the suite.
|
||||
They allow you to create object IDs, which can then be passed to the verbs.
|
||||
For instance,
|
||||
when scripting the popular email program Eudora,
|
||||
you would use <code>mailbox("inbox").message(1).sender</code>
|
||||
to get the name of the sender of the first message in mailbox
|
||||
inbox. It is
|
||||
also possible to specify this as <code>sender(message(1, mailbox("inbox")))</code>,
|
||||
which is sometimes needed because these classes don’t always inherit correctly
|
||||
from baseclasses, so you may have to use a class or property from another
|
||||
suite. </p>
|
||||
|
||||
<p>
|
||||
Next we get the enumeration dictionaries, which allow you to pass
|
||||
english names as arguments to verbs, so you don't have to bother with the 4-letter
|
||||
type code. So, you can say
|
||||
<code>
|
||||
diskcopy.create(..., filesystem="Mac OS Standard")
|
||||
</code>
|
||||
as it is called in Script Editor, instead of the cryptic lowlevel
|
||||
<code>
|
||||
diskcopy.create(..., filesystem="Fhfs")
|
||||
</code></p>
|
||||
|
||||
<p>
|
||||
Finally, we get the “table of contents” of the module, listing all
|
||||
classes and such
|
||||
by code, which is used by <code>gensuitemodule</code> itself: if you use this
|
||||
suite as a base package in a later run this is how it knows what is defined in this
|
||||
suite, and what the Python names are.
|
||||
</p>
|
||||
|
||||
<h3>Notes</h3>
|
||||
|
||||
<ul>
|
||||
|
||||
<li>The <code>aetools</code> module contains some other nifty
|
||||
AppleEvent tools as well. Have a look at it sometime, there is (of
|
||||
course) no documentation yet.
|
||||
</li>
|
||||
|
||||
<li>There are also some older object specifiers for standard objects in aetools.
|
||||
You use these in the form <code>aetools.Word(10,
|
||||
aetools.Document(1))</code>, where the corresponding AppleScript
|
||||
terminology would be <code>word 10 of the first
|
||||
document</code>. Examine
|
||||
<code>aetools</code> and <code>aetools.TalkTo</code>
|
||||
along with
|
||||
the comments at the end of your suite module if you need to create
|
||||
more than the standard object specifiers.
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>Using a Python suite module</h2>
|
||||
|
||||
<p>
|
||||
Now that we have created the suite module, we can use it in a Python script.
|
||||
In older MacPython distributions this used to be a rather
|
||||
complicated affair, but with the package scheme and with the application signature
|
||||
known by the package it is very simple: you import the package and instantiate
|
||||
the class, e.g.
|
||||
<code>
|
||||
talker = Disk_Copy.Disk_Copy(start=1)
|
||||
</code>
|
||||
You will usually specify the <code>start=1</code>: it will run the application if it is
|
||||
not already running.
|
||||
You may want to omit it if you want to talk to the application
|
||||
only if it is already running, or if the application is something like the Finder.
|
||||
Another way to ensure that the application is running is to call <code>talker._start()</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Looking at the sourcefile <a
|
||||
href="applescript/makedisk.py">makedisk.py</a>, we see that it starts
|
||||
with some imports. Naturally, one of these is the Python interface to Disk
|
||||
Copy.</p>
|
||||
|
||||
<p>
|
||||
The main program itself is a wonder of simplicity: we create the
|
||||
object (<code>talker</code>) that talks to Disk Copy,
|
||||
create a disk, and mount it. The bulk of
|
||||
the work is done by <code>talker</code> and the Python interface package we
|
||||
just created.</p>
|
||||
|
||||
<p>
|
||||
The exception handling does warrant a few comments, though. Since
|
||||
AppleScript is basically a connectionless RPC protocol,
|
||||
nothing happens
|
||||
when we create the <code>talker</code> object. Hence, if the destination application
|
||||
is not running, we will not notice until we send our first
|
||||
command (avoid this as described above). There is another thing to note about errors returned by
|
||||
AppleScript calls: <code>MacOS.Error</code> is raised for
|
||||
all of the errors that are known to be <code>OSErr</code>-type errors,
|
||||
while
|
||||
server generated errors raise <code>aetools.Error</code>. </p>
|
||||
|
||||
<h2>Scripting Additions</h2>
|
||||
|
||||
<p>
|
||||
If you want to use any of the scripting additions (or OSAXen, in
|
||||
everyday speech) from a Python program, you can use the same method
|
||||
as for applications, i.e. run <code>gensuitemodule</code> on the
|
||||
OSAX (commonly found in <code>System Folder:Scripting Additions</code>
|
||||
or something similar). There is one minor gotcha: the application
|
||||
signature to use is <code>MACS</code>. You will need to edit the main class
|
||||
in the <code>__init__.py</code> file of the created package and change the value
|
||||
of <code>_signature</code> to <code>MACS</code>, or use a subclass to the
|
||||
same effect.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
There are two minor points to watch out for when using <code>gensuitemodule</code>
|
||||
on OSAXen: they appear all to define the class <code>System_Object_Suite</code>,
|
||||
and a lot of them have the command set in multiple dialects. You have to
|
||||
watch out for name conflicts and make sure you select a reasonable dialect
|
||||
(some of the non-English dialects cause <code>gensuitemodule</code> to generate incorrect
|
||||
Python code). </p>
|
||||
|
||||
Despite these difficulties, OSAXen offer a lot of possibilities. Take a
|
||||
look at some of the OSAXen in the Scripting Additions folder, or
|
||||
<A HREF="http://www.osaxen.com/index.php">download</A> some from the net.
|
||||
|
||||
<h2>Further Reading</h2>
|
||||
|
||||
<p>
|
||||
If you want to look at more involved examples of applescripting, look at the standard
|
||||
modules <code>findertools</code> and <code>nsremote</code>, or (possibly better, as it
|
||||
is more involved) <code>fullbuild</code> from the <code>Mac:scripts</code> folder.
|
||||
</p>
|
||||
|
||||
<h2><a name="alternatives">Alternatives</a></h2>
|
||||
|
||||
<h3><a name="osx">Mac OS X</a></h3>
|
||||
|
||||
<p>
|
||||
Under Mac OS X, the above still works, but with some new difficulties.
|
||||
The application package structure can hide the ‘AETE’ or
|
||||
‘AEUT’ resource from <code>gensuitemodule</code>, so that,
|
||||
for example, it cannot generate an OSA interface to iTunes. Script
|
||||
Editor gets at the dictionary of such programs using a ‘Get
|
||||
AETE’ AppleEvent, if someone wants to donate code to use the same
|
||||
method for gensuitemodule: by all means!
|
||||
</p>
|
||||
|
||||
<p>
|
||||
One alternative is available through the Unix command line version of python.
|
||||
Apple has provided the <code>osacompile</code> and <code>osascript</code> tools,
|
||||
which can be used to compile and execute scripts written in OSA languages. See the
|
||||
man pages for more details.
|
||||
</p>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
424
Mac/Demo/applescript/Disk_Copy/Special_Events.py
Normal file
@@ -0,0 +1,424 @@
|
||||
"""Suite Special Events: Commands for mounting Disk Copy images
|
||||
Level 1, version 1
|
||||
|
||||
Generated from Macintosh HD:Hulpprogramma's:Disk Copy
|
||||
AETE/AEUT resource version 1/0, language 0, script 0
|
||||
"""
|
||||
|
||||
import aetools
|
||||
import MacOS
|
||||
|
||||
_code = 'ddsk'
|
||||
|
||||
class Special_Events_Events:
|
||||
|
||||
_argmap_mount = {
|
||||
'access_mode' : 'Acss',
|
||||
'checksum_verification' : 'VChk',
|
||||
'signature_verification' : 'VSig',
|
||||
'RAM_caching' : 'Cach',
|
||||
}
|
||||
|
||||
def mount(self, _object, _attributes={}, **_arguments):
|
||||
"""mount: Mounts a Disk Copy image as a disk volume
|
||||
Required argument: a reference to the disk image to be mounted
|
||||
Keyword argument access_mode: the access mode for mounted volume (default is "any", i.e. best possible)
|
||||
Keyword argument checksum_verification: Verify the checksum before mounting?
|
||||
Keyword argument signature_verification: Verify the DigiSign<67> signature before mounting?
|
||||
Keyword argument RAM_caching: Cache the disk image in RAM? (if omitted, don't cache)
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: a reference to mounted disk
|
||||
"""
|
||||
_code = 'ddsk'
|
||||
_subcode = 'Moun'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_mount)
|
||||
_arguments['----'] = _object
|
||||
|
||||
aetools.enumsubst(_arguments, 'Acss', _Enum_Acss)
|
||||
aetools.enumsubst(_arguments, 'VChk', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'VSig', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'Cach', _Enum_bool)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_execute_DiskScript = {
|
||||
'checksum_verification' : 'VChk',
|
||||
'signature_verification' : 'VSig',
|
||||
}
|
||||
|
||||
def execute_DiskScript(self, _object, _attributes={}, **_arguments):
|
||||
"""execute DiskScript: Executes a Disk Copy-specific DiskScript
|
||||
Required argument: a reference to the DiskScript to execute
|
||||
Keyword argument checksum_verification: Should checksums be verified when mounting images referenced in the DiskScript?
|
||||
Keyword argument signature_verification: Should the DigiSign<67> signature of the DiskScript and the images it references be verified?
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
"""
|
||||
_code = 'ddsk'
|
||||
_subcode = 'XEQd'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_execute_DiskScript)
|
||||
_arguments['----'] = _object
|
||||
|
||||
aetools.enumsubst(_arguments, 'VChk', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'VSig', _Enum_bool)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
def unmount(self, _object, _attributes={}, **_arguments):
|
||||
"""unmount: Unmount and eject (if necessary) a volume
|
||||
Required argument: a reference to disk to be unmounted (and ejected)
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
"""
|
||||
_code = 'ddsk'
|
||||
_subcode = 'Umnt'
|
||||
|
||||
if _arguments: raise TypeError, 'No optional args expected'
|
||||
_arguments['----'] = _object
|
||||
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_create = {
|
||||
'saving_as' : 'SvAs',
|
||||
'logical_blocks' : 'Blks',
|
||||
'zeroing' : 'Zero',
|
||||
'leave_image_mounted' : 'Moun',
|
||||
'filesystem' : 'Fsys',
|
||||
}
|
||||
|
||||
def create(self, _object, _attributes={}, **_arguments):
|
||||
"""create: Create a new Disk Copy document
|
||||
Required argument: the name of the volume to create
|
||||
Keyword argument saving_as: the disk image to be created
|
||||
Keyword argument logical_blocks: the number of logical blocks
|
||||
Keyword argument zeroing: Should all blocks on the disk be set to zero?
|
||||
Keyword argument leave_image_mounted: Should the image be mounted after it is created?
|
||||
Keyword argument filesystem: file system to use (Mac OS Standard/compatible, Mac OS Enhanced)
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: a reference to newly created disk image (or newly mounted disk)
|
||||
"""
|
||||
_code = 'ddsk'
|
||||
_subcode = 'Crea'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_create)
|
||||
_arguments['----'] = _object
|
||||
|
||||
aetools.enumsubst(_arguments, 'SvAs', _Enum_fss_)
|
||||
aetools.enumsubst(_arguments, 'Blks', _Enum_long)
|
||||
aetools.enumsubst(_arguments, 'Zero', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'Moun', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'Fsys', _Enum_Fsys)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
def verify_checksum(self, _object, _attributes={}, **_arguments):
|
||||
"""verify checksum: Verify the checksum of a Disk Copy 4.2 or a Disk Copy 6.0 read-only document
|
||||
Required argument: the disk image to be verified
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: the result of the checksum verification
|
||||
"""
|
||||
_code = 'ddsk'
|
||||
_subcode = 'Vcrc'
|
||||
|
||||
if _arguments: raise TypeError, 'No optional args expected'
|
||||
_arguments['----'] = _object
|
||||
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
def verify_signature(self, _object, _attributes={}, **_arguments):
|
||||
"""verify signature: Verify the DigiSign<67> signature for a Disk Copy document
|
||||
Required argument: the disk image to be verified
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: Is the DigiSign<67> signature valid?
|
||||
"""
|
||||
_code = 'ddsk'
|
||||
_subcode = 'Vsig'
|
||||
|
||||
if _arguments: raise TypeError, 'No optional args expected'
|
||||
_arguments['----'] = _object
|
||||
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_sign_image = {
|
||||
'using_signer' : 'Sinr',
|
||||
}
|
||||
|
||||
def sign_image(self, _object, _attributes={}, **_arguments):
|
||||
"""sign image: Add a DigiSign<67> signature to a Disk Copy document
|
||||
Required argument: the disk image to be signed
|
||||
Keyword argument using_signer: a reference to signer file to use
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
"""
|
||||
_code = 'ddsk'
|
||||
_subcode = 'Asig'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_sign_image)
|
||||
_arguments['----'] = _object
|
||||
|
||||
aetools.enumsubst(_arguments, 'Sinr', _Enum_alis)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_create_a_floppy_from = {
|
||||
'signature_verification' : 'VSig',
|
||||
'erase_confirmation' : 'Cfrm',
|
||||
'make_multiple_floppies' : 'Mult',
|
||||
}
|
||||
|
||||
def create_a_floppy_from(self, _object, _attributes={}, **_arguments):
|
||||
"""create a floppy from: create a floppy disk from a Disk Copy document
|
||||
Required argument: the disk image to make a floppy from
|
||||
Keyword argument signature_verification: Should the DigiSign<67> signature be verified before creating a floppy disk?
|
||||
Keyword argument erase_confirmation: Should the user be asked to confirm the erasure of the previous contents of floppy disks?
|
||||
Keyword argument make_multiple_floppies: Should the user be prompted to create multiple floppy disks?
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
"""
|
||||
_code = 'ddsk'
|
||||
_subcode = 'Bfpy'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_create_a_floppy_from)
|
||||
_arguments['----'] = _object
|
||||
|
||||
aetools.enumsubst(_arguments, 'VSig', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'Cfrm', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'Mult', _Enum_bool)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_check_image = {
|
||||
'details' : 'ChDe',
|
||||
}
|
||||
|
||||
def check_image(self, _object, _attributes={}, **_arguments):
|
||||
"""check image: Check the disk image<67>s internal data structures for any inconsistencies. Works on NDIF, Disk Copy 4.2, DART<52>, or DiskSet images.
|
||||
Required argument: the disk image to be verified
|
||||
Keyword argument details: Should the disk image details be displayed?
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: a record containing a boolean (true/false) value if the image passes consistency tests, and the numbers of warnings and errors
|
||||
"""
|
||||
_code = 'ddsk'
|
||||
_subcode = 'Chek'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_check_image)
|
||||
_arguments['----'] = _object
|
||||
|
||||
aetools.enumsubst(_arguments, 'ChDe', _Enum_bool)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_segment_image = {
|
||||
'segment_count' : 'SGCT',
|
||||
'segment_size' : 'SGSZ',
|
||||
'segment_name' : 'SGNM',
|
||||
'image_ID' : 'SGID',
|
||||
}
|
||||
|
||||
def segment_image(self, _object, _attributes={}, **_arguments):
|
||||
"""segment image: Segment a NDIF R/W or R/O image into smaller pieces
|
||||
Required argument: the disk image to be segmented
|
||||
Keyword argument segment_count: the number of image segments to create
|
||||
Keyword argument segment_size: the size of image segments (in blocks) to create
|
||||
Keyword argument segment_name: the root name for each image segment file
|
||||
Keyword argument image_ID: string used to generate a unique image ID to group the segments
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: a list of references to the image segments created
|
||||
"""
|
||||
_code = 'ddsk'
|
||||
_subcode = 'SGMT'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_segment_image)
|
||||
_arguments['----'] = _object
|
||||
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_create_SMI = {
|
||||
'source_images' : 'SMI1',
|
||||
'launching_application' : 'SMI2',
|
||||
'launching_document' : 'SMI3',
|
||||
'version_string' : 'SMI4',
|
||||
'checksum_verification' : 'VChk',
|
||||
'signature_verification' : 'VSig',
|
||||
'image_signing' : 'SImg',
|
||||
}
|
||||
|
||||
def create_SMI(self, _object, _attributes={}, **_arguments):
|
||||
"""create SMI: Creates a self-mounting image (SMI) from a list of NDIF disk images
|
||||
Required argument: the self-mounting image to create
|
||||
Keyword argument source_images: a list of references to sources images
|
||||
Keyword argument launching_application: the path to an application to launch
|
||||
Keyword argument launching_document: the path to a document to open
|
||||
Keyword argument version_string: sets the 'vers' 1 resource of the self-mounting image
|
||||
Keyword argument checksum_verification: Should the checksum of the source images be verified before creating the SMI?
|
||||
Keyword argument signature_verification: Should the DigiSign<67> signature of the source images be verified before creating the SMI?
|
||||
Keyword argument image_signing: Should the SMI be given a digital signature when it is created?
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: a reference to the self-mounting image created
|
||||
"""
|
||||
_code = 'ddsk'
|
||||
_subcode = 'MSMI'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_create_SMI)
|
||||
_arguments['----'] = _object
|
||||
|
||||
aetools.enumsubst(_arguments, 'VChk', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'VSig', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'SImg', _Enum_bool)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
|
||||
class Verify_Checksum_reply_record(aetools.ComponentItem):
|
||||
"""Verify Checksum reply record - """
|
||||
want = 'Rcrc'
|
||||
class validity(aetools.NProperty):
|
||||
"""validity - true if checksum is valid """
|
||||
which = 'Vlid'
|
||||
want = 'bool'
|
||||
class expected_checksum(aetools.NProperty):
|
||||
"""expected checksum - checksum value stored in the image header (in hexadecimal) """
|
||||
which = 'crcE'
|
||||
want = 'TEXT'
|
||||
class calculated_checksum(aetools.NProperty):
|
||||
"""calculated checksum - checksum value actually calculated (in hexadecimal) """
|
||||
which = 'crcA'
|
||||
want = 'TEXT'
|
||||
|
||||
class Check_Image_reply_record(aetools.ComponentItem):
|
||||
"""Check Image reply record - """
|
||||
want = 'Rchk'
|
||||
class consistency(aetools.NProperty):
|
||||
"""consistency - Does the image pass consistency checks? """
|
||||
which = 'Rch1'
|
||||
want = 'bool'
|
||||
class error_count(aetools.NProperty):
|
||||
"""error count - the number of errors recorded """
|
||||
which = 'Rch2'
|
||||
want = 'long'
|
||||
class warning_count(aetools.NProperty):
|
||||
"""warning count - the number of warnings recorded """
|
||||
which = 'Rch3'
|
||||
want = 'long'
|
||||
Verify_Checksum_reply_record._propdict = {
|
||||
'validity' : validity,
|
||||
'expected_checksum' : expected_checksum,
|
||||
'calculated_checksum' : calculated_checksum,
|
||||
}
|
||||
Verify_Checksum_reply_record._elemdict = {
|
||||
}
|
||||
Check_Image_reply_record._propdict = {
|
||||
'consistency' : consistency,
|
||||
'error_count' : error_count,
|
||||
'warning_count' : warning_count,
|
||||
}
|
||||
Check_Image_reply_record._elemdict = {
|
||||
}
|
||||
_Enum_Acss = {
|
||||
'read_and_write' : 'RdWr', # read/write access
|
||||
'read_only' : 'Rdxx', # read-only access
|
||||
'any' : 'Anyx', # best possible access
|
||||
}
|
||||
|
||||
_Enum_Fsys = {
|
||||
'Mac_OS_Standard' : 'Fhfs', # classic HFS file system
|
||||
'compatible_Mac_OS_Extended' : 'Fhf+', # new HFS+ file system
|
||||
}
|
||||
|
||||
_Enum_alis = None # XXXX enum alis not found!!
|
||||
_Enum_fss_ = None # XXXX enum fss not found!!
|
||||
_Enum_long = None # XXXX enum long not found!!
|
||||
_Enum_bool = None # XXXX enum bool not found!!
|
||||
|
||||
#
|
||||
# Indices of types declared in this module
|
||||
#
|
||||
_classdeclarations = {
|
||||
'Rchk' : Check_Image_reply_record,
|
||||
'Rcrc' : Verify_Checksum_reply_record,
|
||||
}
|
||||
|
||||
_propdeclarations = {
|
||||
'crcE' : expected_checksum,
|
||||
'Rch2' : error_count,
|
||||
'crcA' : calculated_checksum,
|
||||
'Rch3' : warning_count,
|
||||
'Vlid' : validity,
|
||||
'Rch1' : consistency,
|
||||
}
|
||||
|
||||
_compdeclarations = {
|
||||
}
|
||||
|
||||
_enumdeclarations = {
|
||||
'Acss' : _Enum_Acss,
|
||||
'Fsys' : _Enum_Fsys,
|
||||
}
|
||||
477
Mac/Demo/applescript/Disk_Copy/Standard_Suite.py
Normal file
@@ -0,0 +1,477 @@
|
||||
"""Suite Standard Suite: Common terms for most applications
|
||||
Level 1, version 1
|
||||
|
||||
Generated from Macintosh HD:Hulpprogramma's:Disk Copy
|
||||
AETE/AEUT resource version 1/0, language 0, script 0
|
||||
"""
|
||||
|
||||
import aetools
|
||||
import MacOS
|
||||
|
||||
_code = 'Core'
|
||||
|
||||
class Standard_Suite_Events:
|
||||
|
||||
_argmap_save = {
|
||||
'_in' : 'kfil',
|
||||
'using_format' : 'SvAs',
|
||||
'checksum_verification' : 'VChk',
|
||||
'signature_verification' : 'VSig',
|
||||
'image_signing' : 'SImg',
|
||||
'leave_image_mounted' : 'Moun',
|
||||
'percent_free_space' : 'Slop',
|
||||
'logical_blocks' : 'Blks',
|
||||
'zeroing' : 'Zero',
|
||||
}
|
||||
|
||||
def save(self, _object, _attributes={}, **_arguments):
|
||||
"""save: Save an object
|
||||
Required argument: the source object
|
||||
Keyword argument _in: the target object
|
||||
Keyword argument using_format: the format for the target
|
||||
Keyword argument checksum_verification: Should the checksum be verified before saving?
|
||||
Keyword argument signature_verification: Should the DigiSign<67> signature be verified before saving?
|
||||
Keyword argument image_signing: Should the image be signed?
|
||||
Keyword argument leave_image_mounted: Should the image be mounted after saving?
|
||||
Keyword argument percent_free_space: percent free space to reserve (for image folder operation, 0-255%)
|
||||
Keyword argument logical_blocks: number of logical blocks in the image (for image folder operation)
|
||||
Keyword argument zeroing: Should all the blocks in the image be set to zeros? (for image folder operation)
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: the result of the save operation
|
||||
"""
|
||||
_code = 'core'
|
||||
_subcode = 'save'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_save)
|
||||
_arguments['----'] = _object
|
||||
|
||||
aetools.enumsubst(_arguments, 'kfil', _Enum_obj_)
|
||||
aetools.enumsubst(_arguments, 'SvAs', _Enum_SvAs)
|
||||
aetools.enumsubst(_arguments, 'VChk', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'VSig', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'SImg', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'Moun', _Enum_bool)
|
||||
aetools.enumsubst(_arguments, 'Slop', _Enum_long)
|
||||
aetools.enumsubst(_arguments, 'Blks', _Enum_long)
|
||||
aetools.enumsubst(_arguments, 'Zero', _Enum_bool)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
def do_script(self, _object, _attributes={}, **_arguments):
|
||||
"""do script: Execute an attached script located in the folder "Scripts"
|
||||
Required argument: the script to be executed
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
"""
|
||||
_code = 'core'
|
||||
_subcode = 'dosc'
|
||||
|
||||
if _arguments: raise TypeError, 'No optional args expected'
|
||||
_arguments['----'] = _object
|
||||
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
|
||||
class application(aetools.ComponentItem):
|
||||
"""application - The Disk Copy application """
|
||||
want = 'capp'
|
||||
class version(aetools.NProperty):
|
||||
"""version - the version of this application """
|
||||
which = 'vers'
|
||||
want = 'vers'
|
||||
class name(aetools.NProperty):
|
||||
"""name - the name of this application """
|
||||
which = 'pnam'
|
||||
want = 'TEXT'
|
||||
class comment(aetools.NProperty):
|
||||
"""comment - the comment associated with the application """
|
||||
which = 'comt'
|
||||
want = 'TEXT'
|
||||
class driver_version(aetools.NProperty):
|
||||
"""driver version - the version of the disk image driver """
|
||||
which = 'dVer'
|
||||
want = 'vers'
|
||||
class nonejectable_mode(aetools.NProperty):
|
||||
"""nonejectable mode - Should mounted images be non-ejectable? """
|
||||
which = 'otto'
|
||||
want = 'bool'
|
||||
class save_log_file(aetools.NProperty):
|
||||
"""save log file - Should the log file be saved on disk? """
|
||||
which = 'PSaL'
|
||||
want = 'bool'
|
||||
class use_speech(aetools.NProperty):
|
||||
"""use speech - Should Disk Copy use spoken feedback? """
|
||||
which = 'PTlk'
|
||||
want = 'bool'
|
||||
class smart_Save_As(aetools.NProperty):
|
||||
"""smart Save As - Should the Save As... dialog box automatically go to the right folder? """
|
||||
which = 'PSSP'
|
||||
want = 'bool'
|
||||
class checksum_verification(aetools.NProperty):
|
||||
"""checksum verification - Should image checksums be verified? """
|
||||
which = 'PVeC'
|
||||
want = 'bool'
|
||||
class signature_verification(aetools.NProperty):
|
||||
"""signature verification - Should digital signatures be verified? """
|
||||
which = 'PVeS'
|
||||
want = 'bool'
|
||||
class exclude_DiskScripts(aetools.NProperty):
|
||||
"""exclude DiskScripts - Should images referenced in DiskScripts/DiskSets be excluded from verification? """
|
||||
which = 'PExD'
|
||||
want = 'bool'
|
||||
class exclude_remote_images(aetools.NProperty):
|
||||
"""exclude remote images - Should images that are located on network volumes be excluded from verification? """
|
||||
which = 'PExR'
|
||||
want = 'bool'
|
||||
class image_signing(aetools.NProperty):
|
||||
"""image signing - Should images be signed with a digital signature? """
|
||||
which = 'PSiI'
|
||||
want = 'bool'
|
||||
class leave_image_mounted(aetools.NProperty):
|
||||
"""leave image mounted - Should images be mounted after they are created? """
|
||||
which = 'PMoA'
|
||||
want = 'bool'
|
||||
class erase_confirmation(aetools.NProperty):
|
||||
"""erase confirmation - Should the user be required to confirm commands that erase disks? """
|
||||
which = 'PCoE'
|
||||
want = 'bool'
|
||||
class zeroing(aetools.NProperty):
|
||||
"""zeroing - Should all blocks of a new image be set to zero? """
|
||||
which = 'PZeB'
|
||||
want = 'bool'
|
||||
class default_create_size(aetools.NProperty):
|
||||
"""default create size - the default size for a new image, in blocks (512 bytes per block) """
|
||||
which = 'PDeS'
|
||||
want = 'long'
|
||||
class default_create_name(aetools.NProperty):
|
||||
"""default create name - the default volume name for a new image """
|
||||
which = 'PDeN'
|
||||
want = 'TEXT'
|
||||
class make_multiple_floppies(aetools.NProperty):
|
||||
"""make multiple floppies - Should the user be prompted to make multiple floppy disk images at a time? """
|
||||
which = 'PBuM'
|
||||
want = 'bool'
|
||||
class auto_image_upon_insert(aetools.NProperty):
|
||||
"""auto image upon insert - Should a newly-inserted disk automatically be processed into an image? """
|
||||
which = 'Paim'
|
||||
want = 'bool'
|
||||
class eject_after_auto_image(aetools.NProperty):
|
||||
"""eject after auto image - Should auto-imaged disks be ejected afterwards? """
|
||||
which = 'Pejc'
|
||||
want = 'bool'
|
||||
class auto_copy_upon_floppy_insert(aetools.NProperty):
|
||||
"""auto copy upon floppy insert - Instead of auto-imaging, should newly-inserted floppy disks be copied? """
|
||||
which = 'Pcpf'
|
||||
want = 'bool'
|
||||
class volume_suffix(aetools.NProperty):
|
||||
"""volume suffix - the default volume name suffix """
|
||||
which = 'PDiE'
|
||||
want = 'TEXT'
|
||||
class image_suffix(aetools.NProperty):
|
||||
"""image suffix - the default image name suffix """
|
||||
which = 'PImE'
|
||||
want = 'TEXT'
|
||||
class default_file_system(aetools.NProperty):
|
||||
"""default file system - the default file system type for new blank images """
|
||||
which = 'Pfsy'
|
||||
want = 'Fsys'
|
||||
class default_image_format(aetools.NProperty):
|
||||
"""default image format - the default image file format """
|
||||
which = 'Pdfm'
|
||||
want = 'SvAs'
|
||||
|
||||
class disk(aetools.ComponentItem):
|
||||
"""disk - A mounted volume """
|
||||
want = 'Disk'
|
||||
|
||||
name = name
|
||||
|
||||
comment = comment
|
||||
class locked(aetools.NProperty):
|
||||
"""locked - Is the disk locked? """
|
||||
which = 'islk'
|
||||
want = 'bool'
|
||||
class creation_date(aetools.NProperty):
|
||||
"""creation date - the creation date of disk """
|
||||
which = 'ascd'
|
||||
want = 'ldt '
|
||||
class modification_date(aetools.NProperty):
|
||||
"""modification date - the modification date of disk """
|
||||
which = 'asmo'
|
||||
want = 'ldt '
|
||||
class crc32_checksum(aetools.NProperty):
|
||||
"""crc32 checksum - the crc-32 checksum of the disk """
|
||||
which = 'Xcrc'
|
||||
want = 'TEXT'
|
||||
class disk_copy_4_2e_2_checksum(aetools.NProperty):
|
||||
"""disk copy 4.2 checksum - the Disk Copy 4.2 checksum of the disk """
|
||||
which = 'Xc42'
|
||||
want = 'TEXT'
|
||||
class block_count(aetools.NProperty):
|
||||
"""block count - the number of blocks on disk """
|
||||
which = 'Xblk'
|
||||
want = 'long'
|
||||
class file_system(aetools.NProperty):
|
||||
"""file system - the file system used on disk """
|
||||
which = 'Xfsi'
|
||||
want = 'TEXT'
|
||||
|
||||
class folder(aetools.ComponentItem):
|
||||
"""folder - A folder or directory on a disk """
|
||||
want = 'Fold'
|
||||
|
||||
name = name
|
||||
|
||||
comment = comment
|
||||
|
||||
creation_date = creation_date
|
||||
|
||||
modification_date = modification_date
|
||||
|
||||
class disk_image(aetools.ComponentItem):
|
||||
"""disk image - A disk image file """
|
||||
want = 'DImg'
|
||||
|
||||
name = name
|
||||
|
||||
comment = comment
|
||||
|
||||
locked = locked
|
||||
|
||||
creation_date = creation_date
|
||||
|
||||
modification_date = modification_date
|
||||
class file_format(aetools.NProperty):
|
||||
"""file format - the format of the disk image file """
|
||||
which = 'Ifmt'
|
||||
want = 'TEXT'
|
||||
class signed(aetools.NProperty):
|
||||
"""signed - Does the disk image have a DigiSign<67> signature? """
|
||||
which = 'Isin'
|
||||
want = 'bool'
|
||||
class compressed(aetools.NProperty):
|
||||
"""compressed - Is the disk image compressed? """
|
||||
which = 'Icom'
|
||||
want = 'bool'
|
||||
class segmented(aetools.NProperty):
|
||||
"""segmented - Is the disk image segmented? """
|
||||
which = 'Iseg'
|
||||
want = 'bool'
|
||||
class segments(aetools.NProperty):
|
||||
"""segments - a list of references to other segments that make up a complete image """
|
||||
which = 'Isg#'
|
||||
want = 'fss '
|
||||
class disk_name(aetools.NProperty):
|
||||
"""disk name - the name of the disk this image represents """
|
||||
which = 'Idnm'
|
||||
want = 'TEXT'
|
||||
|
||||
crc32_checksum = crc32_checksum
|
||||
|
||||
disk_copy_4_2e_2_checksum = disk_copy_4_2e_2_checksum
|
||||
|
||||
block_count = block_count
|
||||
|
||||
file_system = file_system
|
||||
class data_fork_size(aetools.NProperty):
|
||||
"""data fork size - the size (in bytes) of the data fork of the disk image """
|
||||
which = 'Idfk'
|
||||
want = 'long'
|
||||
class resource_fork_size(aetools.NProperty):
|
||||
"""resource fork size - the size (in bytes) of the resource fork of the disk image """
|
||||
which = 'Irfk'
|
||||
want = 'long'
|
||||
|
||||
class Save_reply_record(aetools.ComponentItem):
|
||||
"""Save reply record - Result from the save operation """
|
||||
want = 'cpyR'
|
||||
class resulting_target_object(aetools.NProperty):
|
||||
"""resulting target object - a reference to the target object after it has been saved """
|
||||
which = 'rcpO'
|
||||
want = 'obj '
|
||||
class copy_type(aetools.NProperty):
|
||||
"""copy type - the way in which the target object was saved """
|
||||
which = 'rcpT'
|
||||
want = 'rcpT'
|
||||
application._propdict = {
|
||||
'version' : version,
|
||||
'name' : name,
|
||||
'comment' : comment,
|
||||
'driver_version' : driver_version,
|
||||
'nonejectable_mode' : nonejectable_mode,
|
||||
'save_log_file' : save_log_file,
|
||||
'use_speech' : use_speech,
|
||||
'smart_Save_As' : smart_Save_As,
|
||||
'checksum_verification' : checksum_verification,
|
||||
'signature_verification' : signature_verification,
|
||||
'exclude_DiskScripts' : exclude_DiskScripts,
|
||||
'exclude_remote_images' : exclude_remote_images,
|
||||
'image_signing' : image_signing,
|
||||
'leave_image_mounted' : leave_image_mounted,
|
||||
'erase_confirmation' : erase_confirmation,
|
||||
'zeroing' : zeroing,
|
||||
'default_create_size' : default_create_size,
|
||||
'default_create_name' : default_create_name,
|
||||
'make_multiple_floppies' : make_multiple_floppies,
|
||||
'auto_image_upon_insert' : auto_image_upon_insert,
|
||||
'eject_after_auto_image' : eject_after_auto_image,
|
||||
'auto_copy_upon_floppy_insert' : auto_copy_upon_floppy_insert,
|
||||
'volume_suffix' : volume_suffix,
|
||||
'image_suffix' : image_suffix,
|
||||
'default_file_system' : default_file_system,
|
||||
'default_image_format' : default_image_format,
|
||||
}
|
||||
application._elemdict = {
|
||||
}
|
||||
disk._propdict = {
|
||||
'name' : name,
|
||||
'comment' : comment,
|
||||
'locked' : locked,
|
||||
'creation_date' : creation_date,
|
||||
'modification_date' : modification_date,
|
||||
'crc32_checksum' : crc32_checksum,
|
||||
'disk_copy_4_2e_2_checksum' : disk_copy_4_2e_2_checksum,
|
||||
'block_count' : block_count,
|
||||
'file_system' : file_system,
|
||||
}
|
||||
disk._elemdict = {
|
||||
}
|
||||
folder._propdict = {
|
||||
'name' : name,
|
||||
'comment' : comment,
|
||||
'creation_date' : creation_date,
|
||||
'modification_date' : modification_date,
|
||||
}
|
||||
folder._elemdict = {
|
||||
}
|
||||
disk_image._propdict = {
|
||||
'name' : name,
|
||||
'comment' : comment,
|
||||
'locked' : locked,
|
||||
'creation_date' : creation_date,
|
||||
'modification_date' : modification_date,
|
||||
'file_format' : file_format,
|
||||
'signed' : signed,
|
||||
'compressed' : compressed,
|
||||
'segmented' : segmented,
|
||||
'segments' : segments,
|
||||
'disk_name' : disk_name,
|
||||
'crc32_checksum' : crc32_checksum,
|
||||
'disk_copy_4_2e_2_checksum' : disk_copy_4_2e_2_checksum,
|
||||
'block_count' : block_count,
|
||||
'file_system' : file_system,
|
||||
'data_fork_size' : data_fork_size,
|
||||
'resource_fork_size' : resource_fork_size,
|
||||
}
|
||||
disk_image._elemdict = {
|
||||
}
|
||||
Save_reply_record._propdict = {
|
||||
'resulting_target_object' : resulting_target_object,
|
||||
'copy_type' : copy_type,
|
||||
}
|
||||
Save_reply_record._elemdict = {
|
||||
}
|
||||
_Enum_UIAc = {
|
||||
'never_interact' : 'eNvr', # Don<6F>t allow any interaction at all
|
||||
'interact_with_self' : 'eInS', # Only allow interaction from internal events
|
||||
'interact_with_local' : 'eInL', # Allow interaction from any event originating on this machine
|
||||
'interact_with_all' : 'eInA', # Allow interaction from network events
|
||||
}
|
||||
|
||||
_Enum_SvAs = {
|
||||
'NDIF_RW' : 'RdWr', # read/write NDIF disk image
|
||||
'NDIF_RO' : 'Rdxx', # read-only NDIF disk image
|
||||
'NDIF_Compressed' : 'ROCo', # compressed NDIF disk image
|
||||
'Disk_Copy_4_2e_2' : 'DC42', # Disk Copy 4.2 disk image
|
||||
}
|
||||
|
||||
_Enum_rcpT = {
|
||||
'block_disk_copy' : 'cpBl', # block-by-block disk-level copy
|
||||
'files_and_file_ID_copy' : 'cpID', # all files including desktop databases and file ID<49>s
|
||||
'files_and_desktop_info' : 'cpDT', # all files and most desktop information
|
||||
'files_only' : 'cpFI', # all files but no desktop information
|
||||
'disk_image_conversion' : 'cpCV', # disk image format conversion
|
||||
'disk_image_creation' : 'cpCR', # disk image creation
|
||||
}
|
||||
|
||||
_Enum_long = None # XXXX enum long not found!!
|
||||
_Enum_bool = None # XXXX enum bool not found!!
|
||||
_Enum_obj_ = None # XXXX enum obj not found!!
|
||||
|
||||
#
|
||||
# Indices of types declared in this module
|
||||
#
|
||||
_classdeclarations = {
|
||||
'DImg' : disk_image,
|
||||
'capp' : application,
|
||||
'Disk' : disk,
|
||||
'Fold' : folder,
|
||||
'cpyR' : Save_reply_record,
|
||||
}
|
||||
|
||||
_propdeclarations = {
|
||||
'Xcrc' : crc32_checksum,
|
||||
'PDeS' : default_create_size,
|
||||
'Idnm' : disk_name,
|
||||
'PSSP' : smart_Save_As,
|
||||
'Pcpf' : auto_copy_upon_floppy_insert,
|
||||
'pnam' : name,
|
||||
'Isin' : signed,
|
||||
'otto' : nonejectable_mode,
|
||||
'PExD' : exclude_DiskScripts,
|
||||
'Iseg' : segmented,
|
||||
'islk' : locked,
|
||||
'asmo' : modification_date,
|
||||
'PTlk' : use_speech,
|
||||
'Pfsy' : default_file_system,
|
||||
'PVeC' : checksum_verification,
|
||||
'Xc42' : disk_copy_4_2e_2_checksum,
|
||||
'rcpO' : resulting_target_object,
|
||||
'Paim' : auto_image_upon_insert,
|
||||
'comt' : comment,
|
||||
'PCoE' : erase_confirmation,
|
||||
'dVer' : driver_version,
|
||||
'PDeN' : default_create_name,
|
||||
'PBuM' : make_multiple_floppies,
|
||||
'rcpT' : copy_type,
|
||||
'PDiE' : volume_suffix,
|
||||
'Ifmt' : file_format,
|
||||
'Pdfm' : default_image_format,
|
||||
'ascd' : creation_date,
|
||||
'Pejc' : eject_after_auto_image,
|
||||
'PZeB' : zeroing,
|
||||
'PExR' : exclude_remote_images,
|
||||
'PImE' : image_suffix,
|
||||
'PVeS' : signature_verification,
|
||||
'PSaL' : save_log_file,
|
||||
'Xblk' : block_count,
|
||||
'PMoA' : leave_image_mounted,
|
||||
'Isg#' : segments,
|
||||
'Irfk' : resource_fork_size,
|
||||
'Icom' : compressed,
|
||||
'Xfsi' : file_system,
|
||||
'Idfk' : data_fork_size,
|
||||
'vers' : version,
|
||||
'PSiI' : image_signing,
|
||||
}
|
||||
|
||||
_compdeclarations = {
|
||||
}
|
||||
|
||||
_enumdeclarations = {
|
||||
'SvAs' : _Enum_SvAs,
|
||||
'UIAc' : _Enum_UIAc,
|
||||
'rcpT' : _Enum_rcpT,
|
||||
}
|
||||
213
Mac/Demo/applescript/Disk_Copy/Utility_Events.py
Normal file
@@ -0,0 +1,213 @@
|
||||
"""Suite Utility Events: Commands that allow the user to select Disk Copy files
|
||||
Level 1, version 1
|
||||
|
||||
Generated from Macintosh HD:Hulpprogramma's:Disk Copy
|
||||
AETE/AEUT resource version 1/0, language 0, script 0
|
||||
"""
|
||||
|
||||
import aetools
|
||||
import MacOS
|
||||
|
||||
_code = 'ddsk'
|
||||
|
||||
class Utility_Events_Events:
|
||||
|
||||
_argmap_select_disk_image = {
|
||||
'with_prompt' : 'SELp',
|
||||
}
|
||||
|
||||
def select_disk_image(self, _no_object=None, _attributes={}, **_arguments):
|
||||
"""select disk image: Prompt the user to select a disk image
|
||||
Keyword argument with_prompt: the prompt string to be displayed
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: a reference to a disk image
|
||||
"""
|
||||
_code = 'UTIL'
|
||||
_subcode = 'SEL1'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_select_disk_image)
|
||||
if _no_object is not None: raise TypeError, 'No direct arg expected'
|
||||
|
||||
aetools.enumsubst(_arguments, 'SELp', _Enum_TEXT)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_select_DiskScript = {
|
||||
'with_prompt' : 'SELp',
|
||||
}
|
||||
|
||||
def select_DiskScript(self, _no_object=None, _attributes={}, **_arguments):
|
||||
"""select DiskScript: Prompt the user to select a DiskScript
|
||||
Keyword argument with_prompt: the prompt string to be displayed
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: a reference to a DiskScript
|
||||
"""
|
||||
_code = 'UTIL'
|
||||
_subcode = 'SEL2'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_select_DiskScript)
|
||||
if _no_object is not None: raise TypeError, 'No direct arg expected'
|
||||
|
||||
aetools.enumsubst(_arguments, 'SELp', _Enum_TEXT)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_select_disk_image_or_DiskScript = {
|
||||
'with_prompt' : 'SELp',
|
||||
}
|
||||
|
||||
def select_disk_image_or_DiskScript(self, _no_object=None, _attributes={}, **_arguments):
|
||||
"""select disk image or DiskScript: Prompt the user to select a disk image or DiskScript
|
||||
Keyword argument with_prompt: the prompt string to be displayed
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: a reference to disk image or a DiskScript
|
||||
"""
|
||||
_code = 'UTIL'
|
||||
_subcode = 'SEL3'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_select_disk_image_or_DiskScript)
|
||||
if _no_object is not None: raise TypeError, 'No direct arg expected'
|
||||
|
||||
aetools.enumsubst(_arguments, 'SELp', _Enum_TEXT)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_select_floppy_disk_image = {
|
||||
'with_prompt' : 'SELp',
|
||||
}
|
||||
|
||||
def select_floppy_disk_image(self, _no_object=None, _attributes={}, **_arguments):
|
||||
"""select floppy disk image: Prompt the user to select a floppy disk image
|
||||
Keyword argument with_prompt: the prompt string to be displayed
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: a reference to a floppy disk image
|
||||
"""
|
||||
_code = 'UTIL'
|
||||
_subcode = 'SEL4'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_select_floppy_disk_image)
|
||||
if _no_object is not None: raise TypeError, 'No direct arg expected'
|
||||
|
||||
aetools.enumsubst(_arguments, 'SELp', _Enum_TEXT)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_select_disk = {
|
||||
'with_prompt' : 'SELp',
|
||||
}
|
||||
|
||||
def select_disk(self, _no_object=None, _attributes={}, **_arguments):
|
||||
"""select disk: Prompt the user to select a disk volume
|
||||
Keyword argument with_prompt: the prompt string to be displayed
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: a reference to the disk
|
||||
"""
|
||||
_code = 'UTIL'
|
||||
_subcode = 'SEL5'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_select_disk)
|
||||
if _no_object is not None: raise TypeError, 'No direct arg expected'
|
||||
|
||||
aetools.enumsubst(_arguments, 'SELp', _Enum_TEXT)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_select_folder = {
|
||||
'with_prompt' : 'SELp',
|
||||
}
|
||||
|
||||
def select_folder(self, _no_object=None, _attributes={}, **_arguments):
|
||||
"""select folder: Prompt the user to select a folder
|
||||
Keyword argument with_prompt: the prompt string to be displayed
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
Returns: a reference to the folder
|
||||
"""
|
||||
_code = 'UTIL'
|
||||
_subcode = 'SEL6'
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_select_folder)
|
||||
if _no_object is not None: raise TypeError, 'No direct arg expected'
|
||||
|
||||
aetools.enumsubst(_arguments, 'SELp', _Enum_TEXT)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_argmap_log = {
|
||||
'time_stamp' : 'TSMP',
|
||||
}
|
||||
|
||||
def log(self, _object, _attributes={}, **_arguments):
|
||||
"""log: Add a string to the log window
|
||||
Required argument: the string to add to the log window
|
||||
Keyword argument time_stamp: Should the log entry be time-stamped? (false if not supplied)
|
||||
Keyword argument _attributes: AppleEvent attribute dictionary
|
||||
"""
|
||||
_code = 'UTIL'
|
||||
_subcode = 'LOG '
|
||||
|
||||
aetools.keysubst(_arguments, self._argmap_log)
|
||||
_arguments['----'] = _object
|
||||
|
||||
aetools.enumsubst(_arguments, 'TSMP', _Enum_bool)
|
||||
|
||||
_reply, _arguments, _attributes = self.send(_code, _subcode,
|
||||
_arguments, _attributes)
|
||||
if _arguments.has_key('errn'):
|
||||
raise aetools.Error, aetools.decodeerror(_arguments)
|
||||
# XXXX Optionally decode result
|
||||
if _arguments.has_key('----'):
|
||||
return _arguments['----']
|
||||
|
||||
_Enum_TEXT = None # XXXX enum TEXT not found!!
|
||||
_Enum_bool = None # XXXX enum bool not found!!
|
||||
|
||||
#
|
||||
# Indices of types declared in this module
|
||||
#
|
||||
_classdeclarations = {
|
||||
}
|
||||
|
||||
_propdeclarations = {
|
||||
}
|
||||
|
||||
_compdeclarations = {
|
||||
}
|
||||
|
||||
_enumdeclarations = {
|
||||
}
|
||||
35
Mac/Demo/applescript/Disk_Copy/__init__.py
Normal file
@@ -0,0 +1,35 @@
|
||||
"""
|
||||
Package generated from Macintosh HD:Hulpprogramma's:Disk Copy
|
||||
Resource aete resid 0
|
||||
"""
|
||||
import aetools
|
||||
Error = aetools.Error
|
||||
import Standard_Suite
|
||||
import Special_Events
|
||||
import Utility_Events
|
||||
|
||||
|
||||
_code_to_module = {
|
||||
'Core' : Standard_Suite,
|
||||
'ddsk' : Special_Events,
|
||||
'ddsk' : Utility_Events,
|
||||
}
|
||||
|
||||
|
||||
|
||||
_code_to_fullname = {
|
||||
'Core' : ('Disk_Copy.Standard_Suite', 'Standard_Suite'),
|
||||
'ddsk' : ('Disk_Copy.Special_Events', 'Special_Events'),
|
||||
'ddsk' : ('Disk_Copy.Utility_Events', 'Utility_Events'),
|
||||
}
|
||||
|
||||
from Standard_Suite import *
|
||||
from Special_Events import *
|
||||
from Utility_Events import *
|
||||
|
||||
|
||||
class Disk_Copy(Standard_Suite_Events,
|
||||
Special_Events_Events,
|
||||
Utility_Events_Events,
|
||||
aetools.TalkTo):
|
||||
_signature = 'ddsk'
|
||||
15
Mac/Demo/applescript/makedisk.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import Disk_Copy
|
||||
import macfs
|
||||
import sys
|
||||
|
||||
talker = Disk_Copy.Disk_Copy(start=1)
|
||||
talker.activate()
|
||||
filespec = macfs.FSSpec('my disk image.img')
|
||||
try:
|
||||
objref = talker.create('my disk image', saving_as=filespec, leave_image_mounted=1)
|
||||
except Disk_Copy.Error, arg:
|
||||
print "ERROR: my disk image:", arg
|
||||
else:
|
||||
print 'objref=', objref
|
||||
print 'Type return to exit-'
|
||||
sys.stdin.readline()
|
||||
75
Mac/Demo/example0.html
Normal file
@@ -0,0 +1,75 @@
|
||||
<HTML><HEAD><TITLE>Using python to create Macintosh applications, part zero</TITLE></HEAD>
|
||||
<BODY>
|
||||
<H1>Using python to create Macintosh applications, part zero</H1>
|
||||
<HR>
|
||||
|
||||
This document will show you how to create a simple mac-style
|
||||
application using Python. We will glance at how to use file dialogs and
|
||||
messages. <p>
|
||||
|
||||
Our example program <a href="example0/checktext.py">checktext.py</a> asks
|
||||
the user for a text file and checks what style end-of-lines the file has.
|
||||
This may need a little explanation: ASCII text files are almost identical
|
||||
on different machines, with one exception:
|
||||
<ul>
|
||||
<li> Unix systems terminate lines with the "linefeed" character, <code>0x0a</code>,
|
||||
<li> Macintoshes terminate lines with the "carriage return" character,
|
||||
<code>0x0d</code> and
|
||||
<li> MSDOS and Windows terminate lines with first a carriage return and then a linefeed.
|
||||
</ul>
|
||||
|
||||
Let us have a look at the program. The first interesting statement in the main
|
||||
program is the call to <code>macfs.PromptGetFile</code>. This is one of the routines
|
||||
that allow you to ask the user to specify a file. You pass it one required
|
||||
argument, the prompt string. There are up to four optional MacOS <em>file type</em> arguments
|
||||
you can pass, as 4-byte strings. Specifying no file
|
||||
type will allow the user to select any file, specifying one or more types restricts
|
||||
the user to files of this type. File types are explained in most books on the Mac. <p>
|
||||
|
||||
<code>PromptGetFile</code> returns two values: an <em>FSSpec</em> object and a
|
||||
success indicator. The FSSpec object is the "official" MacOS way of specifying a
|
||||
file, more on it later. The success indicator tells you whether the user clicked OK
|
||||
or Cancel. In the event of Cancel we simply exit back to the finder. <p>
|
||||
|
||||
<code>PromptGetFile</code> has a number of friends that do similar things:
|
||||
<ul>
|
||||
<li> <code>StandardGetFile</code> is identical to <code>PromptGetFile</code> but
|
||||
without the prompt. It has up to four optional filetype arguments.
|
||||
<li> <code>StandardPutFile</code> asks the user for an output file. It will
|
||||
warn the user when she tries to overwrite an existing file. The routine has one
|
||||
mandatory argument: a prompt string. Pass the empty string if you do not want a prompt.
|
||||
<li> <code>GetDirectory</code> asks the user for a folder (or directory, in unix terms).
|
||||
It has one optional argument: a prompt string.
|
||||
</ul>
|
||||
All routines return an FSSpec and a success indicator. <p>
|
||||
|
||||
There are many things you can do with FSSpec objects (see the
|
||||
<a href="http://www.python.org/doc/lib/macfs.html">macfs</a> section in the
|
||||
<a href="http://www.python.org/doc/lib/Top.html">Python Library Reference</a>
|
||||
for details), but passing them to <code>open</code> is not
|
||||
one of them. For this, we first have to convert the FSSpec object to a pathname, with
|
||||
the <code>as_pathname</code> method. This returns a standard MacOS-style pathname with
|
||||
colon-separated components. This can then be passed to <code>open</code>. Note that
|
||||
we call open with mode parameter <code>'rb'</code>: we want to read the file in binary
|
||||
mode. Python, like C and C++, uses unix-style line endings internally and opening a
|
||||
file in text mode (<code>'r'</code>) would result in conversion of carriage-returns to
|
||||
linefeeds upon reading. This is something that Mac and DOS programmers are usually aware
|
||||
of but that never ceases to amaze unix buffs. <p>
|
||||
|
||||
After we open the file we attempt to read all data into memory. If this fails we use
|
||||
<code>EasyDialogs.Message</code> to display a message in a standard dialog box and exit.
|
||||
The EasyDialogs module has a few more useful simple dialog routines, more on that in
|
||||
<a href="example1.html">example 1</a>. <p>
|
||||
|
||||
The rest of the code is pretty straightforward: we check that the file actually contains
|
||||
data, count the number of linefeeds and returns and display a message with our guess of the
|
||||
end-of-line convention used in the file. <p>
|
||||
|
||||
The <a href="example0">example0</a> folder has three text files in Mac, Unix and DOS style
|
||||
for you to try the program on. After that, you can continue with <a href="example1.html">example 1</a>
|
||||
or go back to the <a href="index.html">index</a> to find another interesting topic. <p>
|
||||
|
||||
<HR>
|
||||
<A HREF="http://www.cwi.nl/~jack">Jack Jansen</A>,
|
||||
<A HREF="mailto:jack@cwi.nl">jack@cwi.nl</A>, 18-July-1996.
|
||||
</BODY></HTML>
|
||||
35
Mac/Demo/example0/checktext.py
Normal file
@@ -0,0 +1,35 @@
|
||||
"""checktext - Check that a text file has macintosh-style newlines"""
|
||||
|
||||
import sys
|
||||
import EasyDialogs
|
||||
import string
|
||||
|
||||
def main():
|
||||
pathname = EasyDialogs.AskFileForOpen(message='File to check end-of-lines in:')
|
||||
if not pathname:
|
||||
sys.exit(0)
|
||||
fp = open(pathname, 'rb')
|
||||
try:
|
||||
data = fp.read()
|
||||
except MemoryError:
|
||||
EasyDialogs.Message('Sorry, file is too big.')
|
||||
sys.exit(0)
|
||||
if len(data) == 0:
|
||||
EasyDialogs.Message('File is empty.')
|
||||
sys.exit(0)
|
||||
number_cr = string.count(data, '\r')
|
||||
number_lf = string.count(data, '\n')
|
||||
if number_cr == number_lf == 0:
|
||||
EasyDialogs.Message('File contains no lines.')
|
||||
if number_cr == 0:
|
||||
EasyDialogs.Message('File has unix-style line endings')
|
||||
elif number_lf == 0:
|
||||
EasyDialogs.Message('File has mac-style line endings')
|
||||
elif number_cr == number_lf:
|
||||
EasyDialogs.Message('File probably has MSDOS-style line endings')
|
||||
else:
|
||||
EasyDialogs.Message('File has no recognizable line endings (binary file?)')
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
193
Mac/Demo/example1.html
Normal file
@@ -0,0 +1,193 @@
|
||||
<HTML><HEAD><TITLE>Using python to create Macintosh applications, part one</TITLE></HEAD>
|
||||
<BODY>
|
||||
|
||||
<H1>Using python to create Macintosh applications, part one</H1>
|
||||
<HR>
|
||||
|
||||
This document will show you how to create a simple mac-style
|
||||
application using Python. We will glance at how to use dialogs and
|
||||
resources. <p>
|
||||
|
||||
The example application we look at will be a simple program with a
|
||||
dialog that allows you to perform domain name lookups on IP addresses
|
||||
and hostnames.
|
||||
The <A HREF="example1/dnslookup-1.py">source code</A> and
|
||||
<A HREF="example1/dnslookup-1.rsrc">resource file</A>
|
||||
for this application are available in the <A
|
||||
HREF="example1">example1</A> folder (which you will have to download
|
||||
if you are reading this document over the net and if you want to look
|
||||
at the resources). <p>
|
||||
|
||||
We will use the builtin module "socket" that allows a
|
||||
Python program to perform all sorts of networking functions, and we
|
||||
will create the user interface around that. You should be able to run
|
||||
the sample code with the standard Python distribution.<p>
|
||||
|
||||
<CITE>
|
||||
If you are interested in building your own extensions to python you
|
||||
should check out the companion document <A
|
||||
HREF="plugins.html">Creating Macintosh Python C extensions</A>,
|
||||
which tells you how to build your own C extension.
|
||||
<p>
|
||||
</CITE>
|
||||
|
||||
<H2><A NAME="dialog-resources">Creating dialog resources</A></H2>
|
||||
|
||||
Let us start with the creative bit: building the dialogs and creating
|
||||
an icon for our program. For this you need ResEdit, and a reasonable
|
||||
working knowledge of how to use it. "Inside Mac" or various books on
|
||||
macintosh programming will help here. <p>
|
||||
|
||||
There is one fine point that deserves to be mentioned here: <A
|
||||
NAME="resource-numbering">resource numbering</A>. Because often your
|
||||
resources will be combined with those that the Python interpreter and
|
||||
various standard modules need you should give your DLOG and DITL
|
||||
resources numbers above 512. 128 and below are reserved for Apple,
|
||||
128-228 are for extensions like Tk,
|
||||
228-255 for the Python interpreter and 256-511 for standard
|
||||
modules. If you are writing a module that you will be distributing for
|
||||
inclusion in other people's programs you may want to register a number
|
||||
in the 256-511 range, contact Guido or myself or whoever you think is
|
||||
"in charge" of Python for the Macintosh at the moment. Even though the
|
||||
application we are writing at the moment will keep its resources in a
|
||||
separate resource file it is still a good idea to make sure that no
|
||||
conflicts arise: once you have opened your resource file any attempt
|
||||
by the interpreter to open a dialog will also search your resource
|
||||
file. <p>
|
||||
|
||||
Okay, let's have a look at dnslookup-1.rsrc, our resource file.
|
||||
The DLOG and accompanying DITL resource both have number 512. Since
|
||||
ResEdit creates both with default ID=128 you should take care to
|
||||
change the number on both. The dialog itself is pretty basic: two
|
||||
buttons (Lookup and Quit), two labels and
|
||||
two text entry areas, one of which is used for output only. Here's what
|
||||
the dialog will look like at run time<p>
|
||||
<div align=center>
|
||||
<img width=324 height=189 src="example1/dnslookup-1.gif" alt="dialog image">
|
||||
</div>
|
||||
<p>
|
||||
|
||||
<H2><A NAME="modal-dialog">An application with a modal dialog</A></H2>
|
||||
|
||||
Next, we will have to write the actual application. For this example,
|
||||
we will use a modal dialog. This means that we will put up the dialog
|
||||
and go into a loop asking the dialog manager for events (buttons
|
||||
pushed). We handle the actions requested by the user until the Quit
|
||||
button is pressed, upon which we exit our loop (and the program). This
|
||||
way of structuring your program is actually rather antisocial, since
|
||||
you force the user to do whatever you, the application writer, happen
|
||||
to want. A modal dialog leaves no way of escape whatsoever (except
|
||||
command-option-escape), and is usually not a good way to structure
|
||||
anything but the most simple questions. Even then: how often have you
|
||||
been confronted with a dialog asking a question that you could not
|
||||
answer because the data you needed was obscured by the dialog itself?
|
||||
In the next example we will look at an application that does pretty
|
||||
much the same as this one but in a more user-friendly way. <p>
|
||||
|
||||
The code itself is contained in the file <A
|
||||
HREF="example1/dnslookup-1.py"> dnslookup-1.py</A>. Have
|
||||
a copy handy before you read on. The file starts off with a
|
||||
textstring giving a short description. Not many tools do anything with
|
||||
this as yet, but at some point in the future we <EM>will</EM> have all
|
||||
sorts of nifty class browser that will display this string, so just
|
||||
include it. Just put a short description at the start of each module,
|
||||
class, method and function. After the initial description and some
|
||||
comments, we import the modules we need. <p>
|
||||
|
||||
<A NAME="easydialogs"><CODE>EasyDialogs</CODE></A> is a handy standard
|
||||
module that provides you with routines that put up common text-only
|
||||
modal dialogs:
|
||||
<UL>
|
||||
<LI> <CODE>Message(str)</CODE>
|
||||
displays the message "str" and an OK button,
|
||||
<LI> <CODE>AskString(prompt, default)</CODE>
|
||||
asks for a string, displays OK and Cancel buttons,
|
||||
<LI> <CODE>AskYesNoCancel(question, default)</CODE>
|
||||
displays a question and Yes, No and Cancel buttons.
|
||||
</UL>
|
||||
|
||||
<A NAME="res"><CODE>Res</CODE></A> is a pretty complete interface to
|
||||
the MacOS Resource Manager, described fully in Inside Mac. There is
|
||||
currently no documentation of it, but the Apple documentation (or
|
||||
Think Ref) will help you on your way if you remember two points:
|
||||
<UL>
|
||||
<LI> Resources are implemented as Python objects, and each routine
|
||||
with a resource first argument is implemented as a python method.
|
||||
<LI> When in doubt about the arguments examine the routines docstring,
|
||||
as in <CODE>print Res.OpenResFile.__doc__</CODE>
|
||||
</UL>
|
||||
|
||||
Similarly, <A NAME="dlg"><CODE>Dlg</CODE></A> is an interface to the
|
||||
Dialog manager (with Dialogs being implemented as python objects and
|
||||
routines with Dialog arguments being methods). The sys module you
|
||||
know, I hope. The string module is an often used module that enables
|
||||
you to perform many string related operations. In this case however, we
|
||||
are only using the "digits" constant from the string module. We could
|
||||
have simply defined "digits" as "0123456789". The socket module enables
|
||||
us to perform the domain name lookups. We
|
||||
use two calls from it:
|
||||
<UL>
|
||||
<LI> <CODE>gethostbyaddr()</CODE>
|
||||
returns the hostname associated with an IP address
|
||||
<LI> <CODE>gethostbyname()</CODE>
|
||||
returns the IP address associated with a hostname
|
||||
</UL>
|
||||
|
||||
Next in the source file we get definitions for our dialog resource
|
||||
number and for the item numbers in our dialog. These should match the
|
||||
situation in our resource file dnslookup-1.rsrc,
|
||||
obviously.<p>
|
||||
|
||||
On to the main program. We start off with opening our resource file,
|
||||
which should live in the same folder as the python source. If we
|
||||
cannot open it we use <CODE>EasyDialogs</CODE> to print a message and
|
||||
exit. You can try it: just move the resource file somewhere else for a
|
||||
moment. Then we call do_dialog() to do the real work. <p>
|
||||
|
||||
<CODE>Do_dialog()</CODE> uses <CODE>Dlg.GetNewDialog()</CODE> to open
|
||||
a dialog window initialized from 'DLOG' resource ID_MAIN and putting
|
||||
it on screen in the frontmost position. Next, we go into a loop,
|
||||
calling <CODE>Dlg.ModalDialog()</CODE> to wait for the next user
|
||||
action. <CODE>ModalDialog()</CODE> will return us the item number that
|
||||
the user has clicked on (or otherwise activated). It will handle a few
|
||||
slightly more complicated things also, like the user typing into
|
||||
simple textfields, but it will <EM>not</EM> do things like updating
|
||||
the physical appearance of radio buttons, etc. See Inside Mac or
|
||||
another programming guide for how to handle this
|
||||
yourself. Fortunately, our simple application doesn't have to bother with this,
|
||||
since buttons and textfields are the only active elements we have. So, we do a
|
||||
simple switch on item number and call the appropriate routine to implement the
|
||||
action requested. Upon the user pressing "Quit" we simply leave the loop and,
|
||||
hence, <CODE>do_dialog()</CODE>. This will cause the python dialog object
|
||||
<CODE>my_dlg</CODE> to be deleted and the on-screen dialog to disappear. <p>
|
||||
|
||||
<A NAME="dialog-warning">Time for a warning</A>: be very careful what
|
||||
you do as long as a dialog is on-screen. Printing something, for
|
||||
instance, may suddenly cause the standard output window to appear over
|
||||
the dialog, and since we took no measures to redraw the dialog it will
|
||||
become very difficult to get out of the dialog. Also, command-period
|
||||
may or may not work in this situation. I have also seen crashes in
|
||||
such a situation, probably due to the multiple event loops involved or
|
||||
some oversight in the interpreter. You have been warned. <p>
|
||||
|
||||
The implementation of the "Lookup" command can use a bit more
|
||||
explaining: we get the necessary information with <CODE>dnslookup()</CODE>
|
||||
but now we have to update the on-screen dialog to present this
|
||||
information to the user. The <CODE>GetDialogItem()</CODE> method of
|
||||
the dialog returns three bits of information about the given item: its
|
||||
type, its data handle and its rect (the on-screen <CODE>x,y,w,h</CODE>
|
||||
coordinates). We are only interested in the data handle here, on which
|
||||
we call <CODE>SetDialogItemText()</CODE> to set our new text. Note
|
||||
here that python programmers need not bother with the C-string versus
|
||||
pascal-string controversy: the python glue module knows what is needed
|
||||
and converts the python string to the correct type. <p>
|
||||
|
||||
And that concludes our first example of the use of resources and
|
||||
dialogs. Next, you could have a look at the source of EasyDialogs for
|
||||
some examples of using input fields and filterprocs. Or, go on with
|
||||
reading the <A HREF="example2.html">second part</A> of this document
|
||||
to see how to implement a better version of this application.<p>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
BIN
Mac/Demo/example1/dnslookup-1.gif
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
55
Mac/Demo/example1/dnslookup-1.py
Normal file
@@ -0,0 +1,55 @@
|
||||
"""Sample program performing domain name lookups and showing off EasyDialogs,
|
||||
Res and Dlg in the process"""
|
||||
|
||||
import EasyDialogs
|
||||
from Carbon import Res
|
||||
from Carbon import Dlg
|
||||
import socket
|
||||
import string
|
||||
import macresource
|
||||
#
|
||||
# Definitions for our resources
|
||||
ID_MAIN=512
|
||||
|
||||
ITEM_LOOKUP_ENTRY=1
|
||||
ITEM_RESULT=2
|
||||
ITEM_LOOKUP_BUTTON=3
|
||||
ITEM_QUIT_BUTTON=4
|
||||
|
||||
def main():
|
||||
"""Main routine: open resource file, call dialog handler"""
|
||||
macresource.need("DLOG", ID_MAIN, "dnslookup-1.rsrc")
|
||||
do_dialog()
|
||||
|
||||
def do_dialog():
|
||||
"""Post dialog and handle user interaction until quit"""
|
||||
my_dlg = Dlg.GetNewDialog(ID_MAIN, -1)
|
||||
while 1:
|
||||
n = Dlg.ModalDialog(None)
|
||||
if n == ITEM_LOOKUP_BUTTON:
|
||||
tp, h, rect = my_dlg.GetDialogItem(ITEM_LOOKUP_ENTRY)
|
||||
txt = Dlg.GetDialogItemText(h)
|
||||
|
||||
tp, h, rect = my_dlg.GetDialogItem(ITEM_RESULT)
|
||||
Dlg.SetDialogItemText(h, dnslookup(txt))
|
||||
elif n == ITEM_QUIT_BUTTON:
|
||||
break
|
||||
|
||||
def dnslookup(str):
|
||||
""" Perform DNS lookup on str. If first character of digit is numeric,
|
||||
assume that str contains an IP address. Otherwise, assume that str
|
||||
contains a hostname."""
|
||||
if str == '': str = ' '
|
||||
if str[0] in string.digits:
|
||||
try:
|
||||
value = socket.gethostbyaddr(str)[0]
|
||||
except:
|
||||
value = 'Lookup failed'
|
||||
else:
|
||||
try:
|
||||
value = socket.gethostbyname(str)
|
||||
except:
|
||||
value = 'Lookup failed'
|
||||
return value
|
||||
|
||||
main()
|
||||
BIN
Mac/Demo/example1/dnslookup-1.rsrc
Normal file
162
Mac/Demo/example2.html
Normal file
@@ -0,0 +1,162 @@
|
||||
<HTML><HEAD><TITLE>Using python to create Macintosh applications, part two</TITLE></HEAD>
|
||||
<BODY>
|
||||
<H1>Using python to create Macintosh applications, part two</H1>
|
||||
<HR>
|
||||
|
||||
In this document we rewrite the application of the <A
|
||||
HREF="example1.html">previous example</A> to use modeless dialogs. We
|
||||
will use an application framework, and we will have a look at creating
|
||||
applets, standalone applications written in Python. The <A
|
||||
HREF="example2/dnslookup-2.py">source code</A> and
|
||||
<A HREF="example2/dnslookup-2.rsrc">resource file</A> are available in the folder
|
||||
<A HREF="example2">example2</A>. <p>
|
||||
|
||||
Again, we start with ResEdit to create our dialogs. Not only do we
|
||||
want a main dialog this time but also an "About" dialog. This example is less
|
||||
than complete since we do not provide a <A NAME="bundle">BNDL resource</A>
|
||||
and related stuff that an application cannot be without. We are able to do this
|
||||
when building a python applet since BuildApplet will substitute default resources
|
||||
for BNDL, etc. when none are supplied (<A HREF="#no-bundle">See below</A>.)
|
||||
"Inside Mac" or various
|
||||
books on Macintosh programming will help here. Also, you can refer to
|
||||
the resource files provided in the Python source distribution for some
|
||||
of the python-specific points of BNDL programming: the
|
||||
"appletbundle.rsrc" file is what is used for creating applets if you
|
||||
don't provide your own resource file. <p>
|
||||
|
||||
When creating your own BNDL resouorces, keep in mind that the Finder gets
|
||||
confused if you have more than one application with the same signature. This may be due
|
||||
to some incorrectness on the side of "BuildApplet", I am not sure. There is one
|
||||
case when you definitely need a unique signature: when you create an applet that
|
||||
has its own data files and you want the user to be able to start your
|
||||
applet by double-clicking one of the datafiles. <p>
|
||||
|
||||
Let's have a look at dnslookup-2.rsrc, our resource file. Dialog 512 is the
|
||||
main window which has one button (Lookup), two labels and
|
||||
two text entry areas, one of which is used for output only. The "Quit"
|
||||
button has disappeared, because its function is handled by a menu choice. Here's
|
||||
what it will look like at run time:<p>
|
||||
<div align=center>
|
||||
<img width=324 height=205 src="example2/dnslookup-2.gif" alt="dialog image">
|
||||
</div>
|
||||
<p>
|
||||
|
||||
<H2>A modeless dialog application using FrameWork</H2>
|
||||
|
||||
On to the source code in <A
|
||||
HREF="example2/dnslookup-2.py">dnslookup-2.py</A>. The
|
||||
start is similar to our previous example program <A
|
||||
HREF="example1/dnslookup-1.py">dnslookup-1.py</A>, with
|
||||
one extra module being imported. To make life more simple we will use
|
||||
the <CODE>FrameWork</CODE> module, a nifty piece of code that handles
|
||||
all the gory Mac details of event loop programming, menubar
|
||||
installation and all the other code that is the same for every Mac
|
||||
program in the world. Like most standard modules, FrameWork will run
|
||||
some sample test code when you invoke it as a main program, so try it
|
||||
now. It will create a menu bar with an Apple menu with the about box
|
||||
and a "File" menu with some pythonesque choices (which do nothing
|
||||
interesting, by the way) and a "Quit" command that works. <p>
|
||||
|
||||
<BLOCKQUOTE>
|
||||
If you have not used <code>FrameWork</code> before you may want to
|
||||
first take a look at the <A HREF="textedit.html">Pathetic EDitor</A>
|
||||
example, which builds a minimal text editor using FrameWork and TextEdit.
|
||||
On the other hand: we don't use many features of FrameWork, so you could
|
||||
also continue with this document.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
After the imports we get the definitions of resource-IDs in our
|
||||
resource file, slightly changed from the previous version of our
|
||||
program. The main program is also
|
||||
similar to our previous version, with one important exception: we
|
||||
first check to see whether our resource is available before opening
|
||||
the resource file. Why is this? Because later, when we will have
|
||||
converted the script to an applet, our resources will be available in
|
||||
the applet file and we don't need the separate resource file
|
||||
anymore. <p>
|
||||
|
||||
Next comes the definition of our main class,
|
||||
<CODE>DNSLookup</CODE>, which inherits
|
||||
<CODE>FrameWork.Application</CODE>. The Application class handles the
|
||||
menu bar and the main event loop and event dispatching. In the
|
||||
<CODE>__init__</CODE> routine we first let the base class initialize
|
||||
itself, then we create our modeless dialog and finally we jump into
|
||||
the main loop. The main loop continues until we call <CODE>self._quit</CODE>,
|
||||
which we will do when the user selects "Quit". When we create
|
||||
the instance of <CODE>MyDialog</CODE> (which inherits
|
||||
<CODE>DialogWindow</CODE>, which inherits <CODE>Window</CODE>) we pass
|
||||
a reference to the application object, this reference is used to tell
|
||||
Application about our new window. This enables the event loop to keep
|
||||
track of all windows and dispatch things like update events and mouse
|
||||
clicks. <p>
|
||||
|
||||
The <CODE>makeusermenus()</CODE> method (which is called sometime
|
||||
during the Application <CODE>__init__</CODE> routine) creates a File
|
||||
menu with a Quit command (shortcut command-Q), which will callback to
|
||||
our quit() method. <CODE>Quit()</CODE>, in turn, calls <CODE>_quit</CODE> which
|
||||
causes the mainloop to terminate at a convenient time. <p>
|
||||
|
||||
Application provides a standard about box, but we override this by
|
||||
providing our own <CODE>do_about()</CODE> method which shows an about
|
||||
box from a resource as a modal dialog. This piece of code should look
|
||||
familiar to you from the previous example program. That do_about is
|
||||
called when the user selects About from the Apple menu is, again,
|
||||
taken care of by the __init__ routine of Application. <p>
|
||||
|
||||
The <CODE>MyDialog</CODE> class is the container for our main
|
||||
window. Initialization is again done by first calling the base class
|
||||
<CODE>__init__</CODE> function and finally setting the local variable
|
||||
"parent." <p>
|
||||
|
||||
<CODE>Do_itemhit()</CODE> is called when an item is selected in this
|
||||
dialog by the user. We are passed the item number (and the original
|
||||
event structure, which we normally ignore). The code is similar to the
|
||||
main loop of our previous example program: a switch depending on the
|
||||
item selected. <CODE>Dnslookup()</CODE> is quite similar to our previous
|
||||
example. <p>
|
||||
|
||||
<H2><IMG SRC="html.icons/mkapplet.gif"><A NAME="applets">Creating applets</A></H2>
|
||||
|
||||
Now let us try to turn the python script into an applet, a standalone
|
||||
application. This will <em>not</em> work if you have the "classic 68k"
|
||||
Python distribution, only if you have the cfm68k or PPC distribution.
|
||||
|
||||
<blockquote>
|
||||
Actually, "standalone" is probably not the correct term here, since an
|
||||
applet does still depend on a lot of the python environment: the
|
||||
PythonCore shared library, the Python Preferences file, the python Lib
|
||||
folder and any other modules that the main module depends on. It is
|
||||
possible to get rid of all these dependencies and create true standalone
|
||||
applications in Python, but this is a bit difficult. See <a href="freezing.html">
|
||||
Standalone Applications in Python</a> for details. For this
|
||||
document, by standalone we mean here that
|
||||
the script has the look-and-feel of an application, including the
|
||||
ability to have its own document types, be droppable, etc.
|
||||
</blockquote>
|
||||
|
||||
The easiest way to create an applet is to take your source file and
|
||||
drop it onto "BuildApplet", located in the Python home
|
||||
folder. This will create an applet with the same name as your python
|
||||
source with the ".py" stripped. Also, if a resource file with the same
|
||||
name as your source but with ".rsrc" extension is available the
|
||||
resources from that file will be copied to your applet too. If there
|
||||
is no resource file for your script a set of default resources will be
|
||||
used, and the applet will have the default creator 'Pyt0'. The latter
|
||||
also happens if you do have a resource file but without the BNDL
|
||||
combo. <A NAME="no-bundle">Actually</A>, as in the present example.
|
||||
<p>
|
||||
|
||||
If you need slightly more control over the BuildApplet process you can
|
||||
double-click it, and you will get dialogs for source and
|
||||
destination of the applet. The rest of the process, including locating
|
||||
the resource file, remains the same. <p>
|
||||
|
||||
Note that though our example application completely bypasses the
|
||||
normal python user interface this is by no means necessary. Any python
|
||||
script can be turned into an applet, and all the usual features of the
|
||||
interpreter still work. <p>
|
||||
|
||||
That's all for this example, you may now return to the <A HREF="index.html">
|
||||
table of contents</A> to pick another topic. <p>
|
||||
</BODY>
|
||||
</HTML>
|
||||
BIN
Mac/Demo/example2/dnslookup-2.gif
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
85
Mac/Demo/example2/dnslookup-2.py
Normal file
@@ -0,0 +1,85 @@
|
||||
import FrameWork
|
||||
import EasyDialogs
|
||||
from Carbon import Res
|
||||
from Carbon import Dlg
|
||||
import socket
|
||||
import string
|
||||
import macresource
|
||||
#
|
||||
# Definitions for our resources
|
||||
ID_MAIN=512
|
||||
ID_ABOUT=513
|
||||
|
||||
ITEM_LOOKUP_ENTRY=1
|
||||
ITEM_RESULT=2
|
||||
ITEM_LOOKUP_BUTTON=3
|
||||
|
||||
def main():
|
||||
macresource.need("DLOG", ID_MAIN, "dnslookup-2.rsrc")
|
||||
DNSLookup()
|
||||
|
||||
class DNSLookup(FrameWork.Application):
|
||||
"Application class for DNS Lookup"
|
||||
|
||||
def __init__(self):
|
||||
# First init menus, etc.
|
||||
FrameWork.Application.__init__(self)
|
||||
# Next create our dialog
|
||||
self.main_dialog = MyDialog(self)
|
||||
# Now open the dialog
|
||||
self.main_dialog.open(ID_MAIN)
|
||||
# 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 do_about(self, *args):
|
||||
f = Dlg.GetNewDialog(ID_ABOUT, -1)
|
||||
while 1:
|
||||
n = Dlg.ModalDialog(None)
|
||||
if n == 1:
|
||||
return
|
||||
|
||||
class MyDialog(FrameWork.DialogWindow):
|
||||
"Main dialog window for DNSLookup"
|
||||
def __init__(self, parent):
|
||||
FrameWork.DialogWindow.__init__(self, parent)
|
||||
self.parent = parent
|
||||
|
||||
def do_itemhit(self, item, event):
|
||||
if item == ITEM_LOOKUP_BUTTON:
|
||||
self.dolookup()
|
||||
|
||||
def dolookup(self):
|
||||
"""Get text entered in the lookup entry area. Place result of the
|
||||
call to dnslookup in the result entry area."""
|
||||
tp, h, rect = self.dlg.GetDialogItem(ITEM_LOOKUP_ENTRY)
|
||||
txt = Dlg.GetDialogItemText(h)
|
||||
|
||||
tp, h, rect = self.dlg.GetDialogItem(ITEM_RESULT)
|
||||
Dlg.SetDialogItemText(h, self.dnslookup(txt))
|
||||
|
||||
def dnslookup(self, str):
|
||||
""" Perform DNS lookup on str. If first character of digit is numeric,
|
||||
assume that str contains an IP address. Otherwise, assume that str
|
||||
contains a hostname."""
|
||||
if str == '': str = ' '
|
||||
if str[0] in string.digits:
|
||||
try:
|
||||
value = socket.gethostbyaddr(str)[0]
|
||||
except:
|
||||
value = 'Lookup failed'
|
||||
else:
|
||||
try:
|
||||
value = socket.gethostbyname(str)
|
||||
except:
|
||||
value = 'Lookup failed'
|
||||
return value
|
||||
|
||||
|
||||
main()
|
||||
BIN
Mac/Demo/example2/dnslookup-2.rsrc
Normal file
BIN
Mac/Demo/html.icons/createmake.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
Mac/Demo/html.icons/mkapplet.gif
Normal file
|
After Width: | Height: | Size: 1010 B |
BIN
Mac/Demo/html.icons/options.gif
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
Mac/Demo/html.icons/preferences.gif
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
Mac/Demo/html.icons/python.gif
Normal file
|
After Width: | Height: | Size: 1004 B |
115
Mac/Demo/imgbrowse/imgbrowse.py
Normal file
@@ -0,0 +1,115 @@
|
||||
"""imgbrowse - Display pictures using img"""
|
||||
|
||||
import FrameWork
|
||||
import EasyDialogs
|
||||
from Carbon import Res
|
||||
from Carbon import Qd
|
||||
from Carbon import QuickDraw
|
||||
from Carbon import Win
|
||||
#ifrom Carbon mport List
|
||||
import struct
|
||||
import img
|
||||
import imgformat
|
||||
import mac_image
|
||||
|
||||
|
||||
# Where is the picture window?
|
||||
LEFT=200
|
||||
TOP=64
|
||||
MINWIDTH=64
|
||||
MINHEIGHT=64
|
||||
MAXWIDTH=320
|
||||
MAXHEIGHT=320
|
||||
|
||||
|
||||
def main():
|
||||
print 'hello world'
|
||||
imgbrowse()
|
||||
|
||||
class imgbrowse(FrameWork.Application):
|
||||
def __init__(self):
|
||||
# First init menus, etc.
|
||||
FrameWork.Application.__init__(self)
|
||||
self.lastwin = None
|
||||
# Finally, go into the event loop
|
||||
self.mainloop()
|
||||
|
||||
def makeusermenus(self):
|
||||
self.filemenu = m = FrameWork.Menu(self.menubar, "File")
|
||||
self.openitem = FrameWork.MenuItem(m, "Open...", "O", self.opendoc)
|
||||
self.infoitem = FrameWork.MenuItem(m, "Info", "I", self.info)
|
||||
self.quititem = FrameWork.MenuItem(m, "Quit", "Q", self.quit)
|
||||
|
||||
def quit(self, *args):
|
||||
self._quit()
|
||||
|
||||
def opendoc(self, *args):
|
||||
pathname = EasyDialogs.AskFileForOpen() # Any file type
|
||||
if not pathname:
|
||||
return
|
||||
bar = EasyDialogs.ProgressBar('Reading and converting...')
|
||||
try:
|
||||
rdr = img.reader(imgformat.macrgb16, pathname)
|
||||
except img.error, arg:
|
||||
EasyDialogs.Message(repr(arg))
|
||||
return
|
||||
w, h = rdr.width, rdr.height
|
||||
bar.set(10)
|
||||
data = rdr.read()
|
||||
del bar
|
||||
pixmap = mac_image.mkpixmap(w, h, imgformat.macrgb16, data)
|
||||
self.showimg(w, h, pixmap, data)
|
||||
|
||||
def showimg(self, w, h, pixmap, data):
|
||||
win = imgwindow(self)
|
||||
win.open(w, h, pixmap, data)
|
||||
self.lastwin = win
|
||||
|
||||
def info(self, *args):
|
||||
if self.lastwin:
|
||||
self.lastwin.info()
|
||||
|
||||
class imgwindow(FrameWork.Window):
|
||||
def open(self, width, height, pixmap, data):
|
||||
self.pixmap = pixmap
|
||||
self.data = data
|
||||
self.pictrect = (0, 0, width, height)
|
||||
bounds = (LEFT, TOP, LEFT+width, TOP+height)
|
||||
|
||||
self.wid = Win.NewCWindow(bounds, "Picture", 1, 0, -1, 1, 0)
|
||||
self.do_postopen()
|
||||
|
||||
def do_update(self, *args):
|
||||
pass
|
||||
currect = self.fitrect()
|
||||
print 'PICT:', self.pictrect
|
||||
print 'WIND:', currect
|
||||
print 'ARGS:', (self.pixmap, self.wid.GetWindowPort().GetPortBitMapForCopyBits(), self.pictrect,
|
||||
currect, QuickDraw.srcCopy, None)
|
||||
self.info()
|
||||
Qd.CopyBits(self.pixmap, self.wid.GetWindowPort().GetPortBitMapForCopyBits(), self.pictrect,
|
||||
currect, QuickDraw.srcCopy, None)
|
||||
|
||||
def fitrect(self):
|
||||
"""Return self.pictrect scaled to fit in window"""
|
||||
graf = self.wid.GetWindowPort()
|
||||
screenrect = graf.GetPortBounds()
|
||||
picwidth = self.pictrect[2] - self.pictrect[0]
|
||||
picheight = self.pictrect[3] - self.pictrect[1]
|
||||
if picwidth > screenrect[2] - screenrect[0]:
|
||||
factor = float(picwidth) / float(screenrect[2]-screenrect[0])
|
||||
picwidth = picwidth / factor
|
||||
picheight = picheight / factor
|
||||
if picheight > screenrect[3] - screenrect[1]:
|
||||
factor = float(picheight) / float(screenrect[3]-screenrect[1])
|
||||
picwidth = picwidth / factor
|
||||
picheight = picheight / factor
|
||||
return (screenrect[0], screenrect[1], screenrect[0]+int(picwidth),
|
||||
screenrect[1]+int(picheight))
|
||||
|
||||
def info(self):
|
||||
graf = self.wid.GetWindowPort()
|
||||
bits = graf.GetPortBitMapForCopyBits()
|
||||
mac_image.dumppixmap(bits.pixmap_data)
|
||||
|
||||
main()
|
||||
55
Mac/Demo/imgbrowse/mac_image.py
Normal file
@@ -0,0 +1,55 @@
|
||||
"""mac_image - Helper routines (hacks) for images"""
|
||||
import imgformat
|
||||
from Carbon import Qd
|
||||
import struct
|
||||
import MacOS
|
||||
|
||||
_fmt_to_mac = {
|
||||
imgformat.macrgb16 : (16, 16, 3, 5),
|
||||
}
|
||||
|
||||
def mkpixmap(w, h, fmt, data):
|
||||
"""kludge a pixmap together"""
|
||||
fmtinfo = _fmt_to_mac[fmt]
|
||||
|
||||
rv = struct.pack("lHhhhhhhlllhhhhlll",
|
||||
id(data)+MacOS.string_id_to_buffer, # HACK HACK!!
|
||||
w*2 + 0x8000,
|
||||
0, 0, h, w,
|
||||
0,
|
||||
0, 0, # XXXX?
|
||||
72<<16, 72<<16,
|
||||
fmtinfo[0], fmtinfo[1],
|
||||
fmtinfo[2], fmtinfo[3],
|
||||
0, 0, 0)
|
||||
## print 'Our pixmap, size %d:'%len(rv)
|
||||
## dumppixmap(rv)
|
||||
return Qd.RawBitMap(rv)
|
||||
|
||||
def dumppixmap(data):
|
||||
baseAddr, \
|
||||
rowBytes, \
|
||||
t, l, b, r, \
|
||||
pmVersion, \
|
||||
packType, packSize, \
|
||||
hRes, vRes, \
|
||||
pixelType, pixelSize, \
|
||||
cmpCount, cmpSize, \
|
||||
planeBytes, pmTable, pmReserved \
|
||||
= struct.unpack("lhhhhhhhlllhhhhlll", data)
|
||||
print 'Base: 0x%x'%baseAddr
|
||||
print 'rowBytes: %d (0x%x)'%(rowBytes&0x3fff, rowBytes)
|
||||
print 'rect: %d, %d, %d, %d'%(t, l, b, r)
|
||||
print 'pmVersion: 0x%x'%pmVersion
|
||||
print 'packing: %d %d'%(packType, packSize)
|
||||
print 'resolution: %f x %f'%(float(hRes)/0x10000, float(vRes)/0x10000)
|
||||
print 'pixeltype: %d, size %d'%(pixelType, pixelSize)
|
||||
print 'components: %d, size %d'%(cmpCount, cmpSize)
|
||||
print 'planeBytes: %d (0x%x)'%(planeBytes, planeBytes)
|
||||
print 'pmTable: 0x%x'%pmTable
|
||||
print 'pmReserved: 0x%x'%pmReserved
|
||||
for i in range(0, len(data), 16):
|
||||
for j in range(16):
|
||||
if i + j < len(data):
|
||||
print '%02.2x'%ord(data[i+j]),
|
||||
print
|
||||
156
Mac/Demo/index.html
Normal file
@@ -0,0 +1,156 @@
|
||||
<HTML><HEAD><TITLE>Macintosh Python crash course</TITLE></HEAD>
|
||||
<BODY>
|
||||
<H1><IMG SRC="html.icons/python.gif">Macintosh Python crash course</H1>
|
||||
<HR>
|
||||
|
||||
<p>This set of documents provides an introduction to various aspects of
|
||||
Python programming on the Mac. It is assumed that the reader is
|
||||
already familiar with Python and, to some extent, with MacOS Toolbox
|
||||
programming. Other readers may find something interesting here too,
|
||||
your mileage may vary. </p>
|
||||
|
||||
<p>As the previous paragraph reveals to the careful observer these examples
|
||||
are dated, most of them were writting before OSX and haven't been updated
|
||||
afterwards. They still show how to use the Carbon wrappers but aren't
|
||||
necessarily the best way to use the Carbon API's in OSX.</p>
|
||||
|
||||
Another set of Macintosh-savvy examples, more aimed at beginners, is
|
||||
maintained by Joseph Strout, at Python Tidbits in <A
|
||||
HREF="http://www.strout.net/python/">
|
||||
http://www.strout.net/python/</A>.
|
||||
<P>
|
||||
|
||||
The <a href="http://www.python.org/doc/lib/Top.html">Python Library
|
||||
Reference</a> contains a section on <a
|
||||
href="http://www.python.org/doc/lib/Macintosh-Specific-Services.html">Macintosh-specific
|
||||
modules</a> that you should also read. Documentation is also available
|
||||
in PostScript and other forms, see the <a
|
||||
href="http://www.python.org/doc/">documentation</a> section on the
|
||||
webserver. <p>
|
||||
|
||||
<p>The W widget set by Just van Rossum, does not have complete documentation as
|
||||
of this writing, but Corran Webster has documented most of it on his
|
||||
<A HREF="http://www.nevada.edu/~cwebster/Python/">Python Page</A>.</p>
|
||||
|
||||
There are also some documentation links, as well as other MacPython-related
|
||||
pages, in the
|
||||
<A HREF="http://dmoz.org/Computers/Systems/Macintosh/Development/Scripting/Python/">
|
||||
Open Directory</A>.
|
||||
|
||||
|
||||
<H2>Table of contents</H2>
|
||||
|
||||
<blockquote><B>Note:</B>
|
||||
Some of these documents were actually written a long time ago and have seen
|
||||
little maintainance, so use with care. </blockquote>
|
||||
<UL>
|
||||
<LI>
|
||||
<A HREF="example0.html">Using python to create Macintosh applications,
|
||||
part zero</A> whets your appetite by showing you how to ask the user
|
||||
for a filename, and how to display a message. It explains about end-of-line
|
||||
confusion while doing so.
|
||||
|
||||
<LI>
|
||||
<A HREF="example1.html">Using python to create Macintosh applications,
|
||||
part one</A> explains how to create a simple modal-dialog application
|
||||
in Python. It also takes a glance at using the toolbox modules Res and
|
||||
Dlg, and EasyDialogs for simple question-dialogs.
|
||||
|
||||
<LI>
|
||||
<A HREF="example2.html">Using python to create Macintosh applications,
|
||||
part two</A> turns the previous example program into a more complete
|
||||
mac application, using a modeless dialog, menus, etc. It also explains
|
||||
how to create applets, standalone applications written in Python.
|
||||
|
||||
<LI>
|
||||
<A HREF="freezing.html">Freezing Python programs</A> extends on this concept,
|
||||
and shows you how to create applications that can be used on machines without
|
||||
a full Python installed. This one is probably best skipped on first contact
|
||||
with MacPython.
|
||||
|
||||
<LI>
|
||||
<A HREF="textedit.html">Using FrameWork and TextEdit</A> shows you
|
||||
how to use <code>FrameWork</code> application framework and the
|
||||
<code>TextEdit</code> toolbox to build a text editor.
|
||||
|
||||
<LI>
|
||||
<A HREF="plugins.html">Creating a C extension module on the Macintosh</A>
|
||||
is meant for the hardcore programmer, and shows how to create an
|
||||
extension module in C. It also handles using Modulator to create the
|
||||
boilerplate for your module, and creating dynamically-loadable modules
|
||||
on PowerPC Macs. It assumes you use CodeWarrior for you development.
|
||||
|
||||
<LI>
|
||||
<A HREF="mpwextensions.html">Creating C extension modules using MPW</A>
|
||||
is a companion document, written by Corran Webster, which explains how you
|
||||
can develop Python extensions using Apple's free MPW compiler environment.
|
||||
|
||||
<LI>
|
||||
<A HREF="applescript.html">Using Open Scripting Architecture from Python</A> explains
|
||||
how to create a Python module interfacing to a scriptable application,
|
||||
and how to use that module in your python program.
|
||||
|
||||
<LI>
|
||||
<A HREF="cgi.html">Using python to create CGI scripts</A> is a preliminary
|
||||
introduction to writing CGI scripts in Python and to writing scriptable applications
|
||||
in Python.
|
||||
|
||||
<LI>
|
||||
<A HREF="building.html">Building Mac Python from source</A> explains
|
||||
how to build a PPC or 68K interpreter from a source distribution.
|
||||
|
||||
<LI>
|
||||
<A HREF="embed.html">Embedding Python on the Mac</A> is a minimal example of
|
||||
how to embed Python in other Mac applications.
|
||||
|
||||
</UL>
|
||||
|
||||
The Python distribution contains a few more examples, all unexplained:
|
||||
<UL>
|
||||
<LI>
|
||||
<I>PICTbrowse</I> is an application that locates PICT
|
||||
resources and displays them, it demonstrates some quickdraw and the
|
||||
resource and list managers. In the same folder you will find the very
|
||||
similar scripts ICONbrowse and cicnbrowse. oldPICTbrowse is the same program
|
||||
but form the pre-Appearance era, it uses a dialog with a user item and
|
||||
creates and manages its own List object.
|
||||
|
||||
<LI>
|
||||
<I>Imgbrowse</I> displays image files in
|
||||
many different formats (gif, tiff, pbm, etc). It shows how to use the
|
||||
img modules on the mac.
|
||||
|
||||
<LI>
|
||||
<I>Quicktime</I> has the standard <code>MovieInWindow</code> and
|
||||
<code>VerySimplePlayer</code> examples, re-coded in Python.
|
||||
|
||||
<LI>
|
||||
<I>Resources</I>, <I>Sound</I> and <I>Speech</I> have some examples
|
||||
on using the respective managers. In the <i>Mac:Lib</i> folder you
|
||||
will also find modules that do useful things with the Communications
|
||||
Toolbox, the Finder interface, etc.
|
||||
|
||||
<LI>
|
||||
<I>Printing</I> has an example on using the Printing module to, you guessed
|
||||
it, print from Python. The code is somewhat self-documenting. Donated
|
||||
by Just van Rossum, who also donated the Printing module itself.
|
||||
</UL>
|
||||
|
||||
At some point in the (possibly distant) future, I will add chapters on
|
||||
how to use bgen to create modules completely automatic and how to make
|
||||
your Python program scriptable, but that will have to wait. <p>
|
||||
|
||||
<HR>
|
||||
|
||||
Please let me know if you miss critical information in this
|
||||
document. I am quite sure that I will never find the time to turn it
|
||||
into a complete MacPython programmers guide (which would probably be a
|
||||
400-page book instead of 10 lousy html-files), but it should contain
|
||||
at least the information that is neither in the standard Python
|
||||
documentation nor in Inside Mac or other Mac programmers
|
||||
documentation. <p>
|
||||
|
||||
<HR>
|
||||
<A HREF="http://www.cwi.nl/~jack">Jack Jansen</A>,
|
||||
<A HREF="mailto:jack@cwi.nl">jack@cwi.nl</A>, 22-Apr-00.
|
||||
</BODY></HTML>
|
||||
374
Mac/Demo/mlte/mlted.py
Normal file
@@ -0,0 +1,374 @@
|
||||
# A minimal text editor using MLTE. Based on wed.py.
|
||||
#
|
||||
# To be done:
|
||||
# - Functionality: find, etc.
|
||||
|
||||
from Menu import DrawMenuBar
|
||||
from FrameWork import *
|
||||
from Carbon import Win
|
||||
from Carbon import Ctl
|
||||
from Carbon import Qd
|
||||
from Carbon import Res
|
||||
from Carbon import Scrap
|
||||
import os
|
||||
from Carbon import MacTextEditor
|
||||
from Carbon import Mlte
|
||||
|
||||
UNDOLABELS = [ # Indexed by MLTECanUndo() value
|
||||
"Typing", "Cut", "Paste", "Clear", "Font Change", "Color Change", "Size Change",
|
||||
"Style Change", "Align Left", "Align Center", "Align Right", "Drop", "Move"]
|
||||
|
||||
class MlteWindow(Window):
|
||||
def open(self, path, name, data):
|
||||
self.path = path
|
||||
self.name = name
|
||||
r = windowbounds(400, 400)
|
||||
w = Win.NewWindow(r, name, 1, 0, -1, 1, 0)
|
||||
self.wid = w
|
||||
flags = MacTextEditor.kTXNDrawGrowIconMask|MacTextEditor.kTXNWantHScrollBarMask| \
|
||||
MacTextEditor.kTXNWantVScrollBarMask
|
||||
self.ted, self.frameid = Mlte.TXNNewObject(None, w, None, flags, MacTextEditor.kTXNTextEditStyleFrameType,
|
||||
MacTextEditor.kTXNTextFile, MacTextEditor.kTXNMacOSEncoding)
|
||||
self.ted.TXNSetData(MacTextEditor.kTXNTextData, data, 0, 0x7fffffff)
|
||||
self.changed = 0
|
||||
self.do_postopen()
|
||||
self.do_activate(1, None)
|
||||
|
||||
def do_idle(self, event):
|
||||
self.ted.TXNIdle()
|
||||
self.ted.TXNAdjustCursor(None)
|
||||
|
||||
|
||||
|
||||
def do_activate(self, onoff, evt):
|
||||
if onoff:
|
||||
## self.ted.TXNActivate(self.frameid, 0)
|
||||
self.ted.TXNFocus(1)
|
||||
self.parent.active = self
|
||||
else:
|
||||
self.ted.TXNFocus(0)
|
||||
self.parent.active = None
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def do_update(self, wid, event):
|
||||
self.ted.TXNDraw(None)
|
||||
|
||||
def do_postresize(self, width, height, window):
|
||||
self.ted.TXNResizeFrame(width, height, self.frameid)
|
||||
|
||||
def do_contentclick(self, local, modifiers, evt):
|
||||
self.ted.TXNClick(evt)
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def do_char(self, ch, event):
|
||||
self.ted.TXNKeyDown(event)
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def close(self):
|
||||
if self.changed:
|
||||
save = EasyDialogs.AskYesNoCancel('Save window "%s" before closing?'%self.name, 1)
|
||||
if save > 0:
|
||||
self.menu_save()
|
||||
elif save < 0:
|
||||
return
|
||||
if self.parent.active == self:
|
||||
self.parent.active = None
|
||||
self.ted.TXNDeleteObject()
|
||||
del self.ted
|
||||
## del self.tedtexthandle
|
||||
self.do_postclose()
|
||||
|
||||
def menu_save(self):
|
||||
if not self.path:
|
||||
self.menu_save_as()
|
||||
return # Will call us recursively
|
||||
dhandle = self.ted.TXNGetData(0, 0x7fffffff)
|
||||
data = dhandle.data
|
||||
fp = open(self.path, 'wb') # NOTE: wb, because data has CR for end-of-line
|
||||
fp.write(data)
|
||||
if data[-1] <> '\r': fp.write('\r')
|
||||
fp.close()
|
||||
self.changed = 0
|
||||
|
||||
def menu_save_as(self):
|
||||
path = EasyDialogs.AskFileForSave(message='Save as:')
|
||||
if not path: return
|
||||
self.path = path
|
||||
self.name = os.path.split(self.path)[-1]
|
||||
self.wid.SetWTitle(self.name)
|
||||
self.menu_save()
|
||||
|
||||
def menu_cut(self):
|
||||
## self.ted.WESelView()
|
||||
self.ted.TXNCut()
|
||||
### Mlte.ConvertToPublicScrap()
|
||||
## Scrap.ZeroScrap()
|
||||
## self.ted.WECut()
|
||||
## self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
self.changed = 1
|
||||
|
||||
def menu_copy(self):
|
||||
## Scrap.ZeroScrap()
|
||||
self.ted.TXNCopy()
|
||||
### Mlte.ConvertToPublicScrap()
|
||||
## self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def menu_paste(self):
|
||||
### Mlte.ConvertFromPublicScrap()
|
||||
self.ted.TXNPaste()
|
||||
## self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
self.changed = 1
|
||||
|
||||
def menu_clear(self):
|
||||
## self.ted.WESelView()
|
||||
self.ted.TXNClear()
|
||||
## self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
self.changed = 1
|
||||
|
||||
def menu_undo(self):
|
||||
self.ted.TXNUndo()
|
||||
## self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def menu_redo(self):
|
||||
self.ted.TXNRedo()
|
||||
## self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def have_selection(self):
|
||||
start, stop = self.ted.TXNGetSelection()
|
||||
return start < stop
|
||||
|
||||
def can_paste(self):
|
||||
return Mlte.TXNIsScrapPastable()
|
||||
|
||||
def can_undo(self):
|
||||
can, which = self.ted.TXNCanUndo()
|
||||
if not can:
|
||||
return None
|
||||
if which >= len(UNDOLABELS):
|
||||
# Unspecified undo
|
||||
return "Undo"
|
||||
which = UNDOLABELS[which]
|
||||
|
||||
return "Undo "+which
|
||||
|
||||
def can_redo(self):
|
||||
can, which = self.ted.TXNCanRedo()
|
||||
if not can:
|
||||
return None
|
||||
if which >= len(UNDOLABELS):
|
||||
# Unspecified undo
|
||||
return "Redo"
|
||||
which = UNDOLABELS[which]
|
||||
|
||||
return "Redo "+which
|
||||
|
||||
class Mlted(Application):
|
||||
def __init__(self):
|
||||
Application.__init__(self)
|
||||
self.num = 0
|
||||
self.active = None
|
||||
self.updatemenubar()
|
||||
|
||||
def makeusermenus(self):
|
||||
self.filemenu = m = Menu(self.menubar, "File")
|
||||
self.newitem = MenuItem(m, "New window", "N", self.open)
|
||||
self.openitem = MenuItem(m, "Open...", "O", self.openfile)
|
||||
self.closeitem = MenuItem(m, "Close", "W", self.closewin)
|
||||
m.addseparator()
|
||||
self.saveitem = MenuItem(m, "Save", "S", self.save)
|
||||
self.saveasitem = MenuItem(m, "Save as...", "", self.saveas)
|
||||
m.addseparator()
|
||||
self.quititem = MenuItem(m, "Quit", "Q", self.quit)
|
||||
|
||||
self.editmenu = m = Menu(self.menubar, "Edit")
|
||||
self.undoitem = MenuItem(m, "Undo", "Z", self.undo)
|
||||
self.redoitem = MenuItem(m, "Redo", None, self.redo)
|
||||
m.addseparator()
|
||||
self.cutitem = MenuItem(m, "Cut", "X", self.cut)
|
||||
self.copyitem = MenuItem(m, "Copy", "C", self.copy)
|
||||
self.pasteitem = MenuItem(m, "Paste", "V", self.paste)
|
||||
self.clearitem = MenuItem(m, "Clear", "", self.clear)
|
||||
|
||||
# Groups of items enabled together:
|
||||
self.windowgroup = [self.closeitem, self.saveitem, self.saveasitem, self.editmenu]
|
||||
self.focusgroup = [self.cutitem, self.copyitem, self.clearitem]
|
||||
self.windowgroup_on = -1
|
||||
self.focusgroup_on = -1
|
||||
self.pastegroup_on = -1
|
||||
self.undo_label = "never"
|
||||
self.redo_label = "never"
|
||||
|
||||
def updatemenubar(self):
|
||||
changed = 0
|
||||
on = (self.active <> None)
|
||||
if on <> self.windowgroup_on:
|
||||
for m in self.windowgroup:
|
||||
m.enable(on)
|
||||
self.windowgroup_on = on
|
||||
changed = 1
|
||||
if on:
|
||||
# only if we have an edit menu
|
||||
on = self.active.have_selection()
|
||||
if on <> self.focusgroup_on:
|
||||
for m in self.focusgroup:
|
||||
m.enable(on)
|
||||
self.focusgroup_on = on
|
||||
changed = 1
|
||||
on = self.active.can_paste()
|
||||
if on <> self.pastegroup_on:
|
||||
self.pasteitem.enable(on)
|
||||
self.pastegroup_on = on
|
||||
changed = 1
|
||||
on = self.active.can_undo()
|
||||
if on <> self.undo_label:
|
||||
if on:
|
||||
self.undoitem.enable(1)
|
||||
self.undoitem.settext(on)
|
||||
self.undo_label = on
|
||||
else:
|
||||
self.undoitem.settext("Nothing to undo")
|
||||
self.undoitem.enable(0)
|
||||
changed = 1
|
||||
on = self.active.can_redo()
|
||||
if on <> self.redo_label:
|
||||
if on:
|
||||
self.redoitem.enable(1)
|
||||
self.redoitem.settext(on)
|
||||
self.redo_label = on
|
||||
else:
|
||||
self.redoitem.settext("Nothing to redo")
|
||||
self.redoitem.enable(0)
|
||||
changed = 1
|
||||
if changed:
|
||||
DrawMenuBar()
|
||||
|
||||
#
|
||||
# Apple menu
|
||||
#
|
||||
|
||||
def do_about(self, id, item, window, event):
|
||||
EasyDialogs.Message("A simple single-font text editor based on MacTextEditor")
|
||||
|
||||
#
|
||||
# File menu
|
||||
#
|
||||
|
||||
def open(self, *args):
|
||||
self._open(0)
|
||||
|
||||
def openfile(self, *args):
|
||||
self._open(1)
|
||||
|
||||
def _open(self, askfile):
|
||||
if askfile:
|
||||
path = EasyDialogs.AskFileForOpen(typeList=('TEXT',))
|
||||
if not path:
|
||||
return
|
||||
name = os.path.split(path)[-1]
|
||||
try:
|
||||
fp = open(path, 'rb') # NOTE binary, we need cr as end-of-line
|
||||
data = fp.read()
|
||||
fp.close()
|
||||
except IOError, arg:
|
||||
EasyDialogs.Message("IOERROR: %r" % (arg,))
|
||||
return
|
||||
else:
|
||||
path = None
|
||||
name = "Untitled %d"%self.num
|
||||
data = ''
|
||||
w = MlteWindow(self)
|
||||
w.open(path, name, data)
|
||||
self.num = self.num + 1
|
||||
|
||||
def closewin(self, *args):
|
||||
if self.active:
|
||||
self.active.close()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def save(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_save()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def saveas(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_save_as()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
|
||||
def quit(self, *args):
|
||||
for w in self._windows.values():
|
||||
w.close()
|
||||
if self._windows:
|
||||
return
|
||||
self._quit()
|
||||
|
||||
#
|
||||
# Edit menu
|
||||
#
|
||||
|
||||
def undo(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_undo()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def redo(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_redo()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def cut(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_cut()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def copy(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_copy()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def paste(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_paste()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def clear(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_clear()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
#
|
||||
# Other stuff
|
||||
#
|
||||
|
||||
def idle(self, event):
|
||||
if self.active:
|
||||
self.active.do_idle(event)
|
||||
else:
|
||||
Qd.SetCursor(Qd.GetQDGlobalsArrow())
|
||||
|
||||
def main():
|
||||
Mlte.TXNInitTextension(0)
|
||||
try:
|
||||
App = Mlted()
|
||||
App.mainloop()
|
||||
finally:
|
||||
Mlte.TXNTerminateTextension()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
70
Mac/Demo/quicktime/MovieInWindow.py
Normal file
@@ -0,0 +1,70 @@
|
||||
"""MovieInWindow converted to python
|
||||
|
||||
Jack Jansen, CWI, December 1995
|
||||
"""
|
||||
|
||||
from Carbon import Qt
|
||||
from Carbon import QuickTime
|
||||
from Carbon import Qd
|
||||
from Carbon import QuickDraw
|
||||
from Carbon import Evt
|
||||
from Carbon import Events
|
||||
from Carbon import Win
|
||||
from Carbon import Windows
|
||||
from Carbon import File
|
||||
import EasyDialogs
|
||||
import sys
|
||||
import os
|
||||
|
||||
|
||||
def main():
|
||||
# skip the toolbox initializations, already done
|
||||
# XXXX Should use gestalt here to check for quicktime version
|
||||
Qt.EnterMovies()
|
||||
|
||||
# Get the movie file
|
||||
if len(sys.argv) > 1:
|
||||
filename = sys.argv[1]
|
||||
else:
|
||||
filename = EasyDialogs.AskFileForOpen() # Was: QuickTime.MovieFileType
|
||||
if not filename:
|
||||
sys.exit(0)
|
||||
|
||||
# Open the window
|
||||
bounds = (175, 75, 175+160, 75+120)
|
||||
theWindow = Win.NewCWindow(bounds, os.path.split(filename)[1], 1, 0, -1, 0, 0)
|
||||
Qd.SetPort(theWindow)
|
||||
# XXXX Needed? SetGWorld((CGrafPtr)theWindow, nil)
|
||||
|
||||
playMovieInWindow(theWindow, filename, theWindow.GetWindowPort().GetPortBounds())
|
||||
|
||||
def playMovieInWindow(theWindow, theFile, movieBox):
|
||||
"""Play a movie in a window"""
|
||||
# XXXX Needed? SetGWorld((CGrafPtr)theWindow, nil);
|
||||
|
||||
# Get the movie
|
||||
theMovie = loadMovie(theFile)
|
||||
|
||||
# Set where we want it
|
||||
theMovie.SetMovieBox(movieBox)
|
||||
|
||||
# Start at the beginning
|
||||
theMovie.GoToBeginningOfMovie()
|
||||
|
||||
# Give a little time to preroll
|
||||
theMovie.MoviesTask(0)
|
||||
|
||||
# Start playing
|
||||
theMovie.StartMovie()
|
||||
|
||||
while not theMovie.IsMovieDone() and not Evt.Button():
|
||||
theMovie.MoviesTask(0)
|
||||
|
||||
def loadMovie(theFile):
|
||||
"""Load a movie given an fsspec. Return the movie object"""
|
||||
movieResRef = Qt.OpenMovieFile(theFile, 1)
|
||||
movie, d1, d2 = Qt.NewMovieFromFile(movieResRef, 0, QuickTime.newMovieActive)
|
||||
return movie
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
92
Mac/Demo/quicktime/VerySimplePlayer.py
Normal file
@@ -0,0 +1,92 @@
|
||||
"""VerySimplePlayer converted to python
|
||||
|
||||
Jack Jansen, CWI, December 1995
|
||||
"""
|
||||
|
||||
from Carbon import Qt
|
||||
from Carbon import QuickTime
|
||||
from Carbon import Qd
|
||||
from Carbon import QuickDraw
|
||||
from Carbon import Evt
|
||||
from Carbon import Events
|
||||
from Carbon import Win
|
||||
from Carbon import Windows
|
||||
from Carbon import File
|
||||
import EasyDialogs
|
||||
import sys
|
||||
|
||||
# XXXX maxbounds = (40, 40, 1000, 1000)
|
||||
|
||||
def main():
|
||||
print 'hello world' # XXXX
|
||||
# skip the toolbox initializations, already done
|
||||
# XXXX Should use gestalt here to check for quicktime version
|
||||
Qt.EnterMovies()
|
||||
|
||||
# Get the movie file
|
||||
fss = EasyDialogs.AskFileForOpen(wanted=File.FSSpec) # Was: QuickTime.MovieFileType
|
||||
if not fss:
|
||||
sys.exit(0)
|
||||
|
||||
# Open the window
|
||||
bounds = (175, 75, 175+160, 75+120)
|
||||
theWindow = Win.NewCWindow(bounds, fss.as_tuple()[2], 0, 0, -1, 1, 0)
|
||||
# XXXX Needed? SetGWorld((CGrafPtr)theWindow, nil)
|
||||
Qd.SetPort(theWindow)
|
||||
|
||||
# Get the movie
|
||||
theMovie = loadMovie(fss)
|
||||
|
||||
# Relocate to (0, 0)
|
||||
bounds = theMovie.GetMovieBox()
|
||||
bounds = 0, 0, bounds[2]-bounds[0], bounds[3]-bounds[1]
|
||||
theMovie.SetMovieBox(bounds)
|
||||
|
||||
# Create a controller
|
||||
theController = theMovie.NewMovieController(bounds, QuickTime.mcTopLeftMovie)
|
||||
|
||||
# Get movie size and update window parameters
|
||||
rv, bounds = theController.MCGetControllerBoundsRect()
|
||||
theWindow.SizeWindow(bounds[2], bounds[3], 0) # XXXX or [3] [2]?
|
||||
Qt.AlignWindow(theWindow, 0)
|
||||
theWindow.ShowWindow()
|
||||
|
||||
# XXXX MCDoAction(theController, mcActionSetGrowBoxBounds, &maxBounds)
|
||||
theController.MCDoAction(QuickTime.mcActionSetKeysEnabled, '1')
|
||||
|
||||
# XXXX MCSetActionFilterWithRefCon(theController, movieControllerEventFilter, (long)theWindow)
|
||||
|
||||
done = 0
|
||||
while not done:
|
||||
gotone, evt = Evt.WaitNextEvent(0xffff, 0)
|
||||
(what, message, when, where, modifiers) = evt
|
||||
## print what, message, when, where, modifiers # XXXX
|
||||
|
||||
if theController.MCIsPlayerEvent(evt):
|
||||
continue
|
||||
|
||||
if what == Events.mouseDown:
|
||||
part, whichWindow = Win.FindWindow(where)
|
||||
if part == Windows.inGoAway:
|
||||
done = whichWindow.TrackGoAway(where)
|
||||
elif part == Windows.inDrag:
|
||||
Qt.DragAlignedWindow(whichWindow, where, (0, 0, 4000, 4000))
|
||||
elif what == Events.updateEvt:
|
||||
whichWindow = Win.WhichWindow(message)
|
||||
if not whichWindow:
|
||||
# Probably the console window. Print something, hope it helps.
|
||||
print 'update'
|
||||
else:
|
||||
Qd.SetPort(whichWindow)
|
||||
whichWindow.BeginUpdate()
|
||||
Qd.EraseRect(whichWindow.GetWindowPort().GetPortBounds())
|
||||
whichWindow.EndUpdate()
|
||||
|
||||
def loadMovie(theFile):
|
||||
"""Load a movie given an fsspec. Return the movie object"""
|
||||
movieResRef = Qt.OpenMovieFile(theFile, 1)
|
||||
movie, d1, d2 = Qt.NewMovieFromFile(movieResRef, 0, QuickTime.newMovieActive)
|
||||
return movie
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
57
Mac/Demo/resources/copyres.py
Normal file
@@ -0,0 +1,57 @@
|
||||
from Carbon.Res import *
|
||||
from Carbon.Resources import *
|
||||
import MacOS
|
||||
|
||||
READ = 1
|
||||
WRITE = 2
|
||||
smAllScripts = -3
|
||||
|
||||
def copyres(src, dst):
|
||||
"""Copy resource from src file to dst file."""
|
||||
|
||||
cur = CurResFile()
|
||||
ctor, type = MacOS.GetCreatorAndType(src)
|
||||
input = FSpOpenResFile(src, READ)
|
||||
try:
|
||||
FSpCreateResFile(dst, ctor, type, smAllScripts)
|
||||
except:
|
||||
raw_input("%s already exists... CR to write anyway! " % dst)
|
||||
output = FSpOpenResFile(dst, WRITE)
|
||||
UseResFile(input)
|
||||
ntypes = Count1Types()
|
||||
for itype in range(1, 1+ntypes):
|
||||
type = Get1IndType(itype)
|
||||
nresources = Count1Resources(type)
|
||||
for ires in range(1, 1+nresources):
|
||||
res = Get1IndResource(type, ires)
|
||||
res.LoadResource()
|
||||
id, type, name = res.GetResInfo()
|
||||
size = res.SizeResource()
|
||||
attrs = res.GetResAttrs()
|
||||
print id, type, name, size, hex(attrs)
|
||||
res.DetachResource()
|
||||
UseResFile(output)
|
||||
try:
|
||||
res2 = Get1Resource(type, id)
|
||||
except (RuntimeError, Res.Error), msg:
|
||||
res2 = None
|
||||
if res2:
|
||||
print "Duplicate type+id, not copied"
|
||||
print (res2.size, res2.data)
|
||||
print res2.GetResInfo()
|
||||
if res2.HomeResFile() == output:
|
||||
'OK'
|
||||
elif res2.HomeResFile() == input:
|
||||
'BAD!'
|
||||
else:
|
||||
print 'Home:', res2.HomeResFile()
|
||||
else:
|
||||
res.AddResource(type, id, name)
|
||||
#res.SetResAttrs(attrs)
|
||||
res.WriteResource()
|
||||
UseResFile(input)
|
||||
UseResFile(cur)
|
||||
CloseResFile(output)
|
||||
CloseResFile(input)
|
||||
|
||||
copyres('::python.<2E>.rsrc', '::foo.rsrc')
|
||||
60
Mac/Demo/resources/listres.py
Normal file
@@ -0,0 +1,60 @@
|
||||
# List all resources
|
||||
|
||||
from Carbon import Res
|
||||
from Carbon.Resources import *
|
||||
|
||||
def list1resources():
|
||||
ntypes = Res.Count1Types()
|
||||
for itype in range(1, 1+ntypes):
|
||||
type = Res.Get1IndType(itype)
|
||||
print "Type:", repr(type)
|
||||
nresources = Res.Count1Resources(type)
|
||||
for i in range(1, 1 + nresources):
|
||||
Res.SetResLoad(0)
|
||||
res = Res.Get1IndResource(type, i)
|
||||
Res.SetResLoad(1)
|
||||
info(res)
|
||||
|
||||
def listresources():
|
||||
ntypes = Res.CountTypes()
|
||||
for itype in range(1, 1+ntypes):
|
||||
type = Res.GetIndType(itype)
|
||||
print "Type:", repr(type)
|
||||
nresources = Res.CountResources(type)
|
||||
for i in range(1, 1 + nresources):
|
||||
Res.SetResLoad(0)
|
||||
res = Res.GetIndResource(type, i)
|
||||
Res.SetResLoad(1)
|
||||
info(res)
|
||||
|
||||
def info(res):
|
||||
print res.GetResInfo(), res.SizeResource(), decodeattrs(res.GetResAttrs())
|
||||
|
||||
attrnames = {
|
||||
resChanged: 'Changed',
|
||||
resPreload: 'Preload',
|
||||
resProtected: 'Protected',
|
||||
resLocked: 'Locked',
|
||||
resPurgeable: 'Purgeable',
|
||||
resSysHeap: 'SysHeap',
|
||||
}
|
||||
|
||||
def decodeattrs(attrs):
|
||||
names = []
|
||||
for bit in range(16):
|
||||
mask = 1<<bit
|
||||
if attrs & mask:
|
||||
if attrnames.has_key(mask):
|
||||
names.append(attrnames[mask])
|
||||
else:
|
||||
names.append(hex(mask))
|
||||
return names
|
||||
|
||||
def test():
|
||||
print "=== Local resourcess ==="
|
||||
list1resources()
|
||||
print "=== All resources ==="
|
||||
listresources()
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
||||
180
Mac/Demo/sound/morse.py
Normal file
@@ -0,0 +1,180 @@
|
||||
import sys, math
|
||||
|
||||
DOT = 30
|
||||
DAH = 80
|
||||
OCTAVE = 2 # 1 == 441 Hz, 2 == 882 Hz, ...
|
||||
SAMPWIDTH = 2
|
||||
FRAMERATE = 44100
|
||||
BASEFREQ = 441
|
||||
QSIZE = 20000
|
||||
|
||||
morsetab = {
|
||||
'A': '.-', 'a': '.-',
|
||||
'B': '-...', 'b': '-...',
|
||||
'C': '-.-.', 'c': '-.-.',
|
||||
'D': '-..', 'd': '-..',
|
||||
'E': '.', 'e': '.',
|
||||
'F': '..-.', 'f': '..-.',
|
||||
'G': '--.', 'g': '--.',
|
||||
'H': '....', 'h': '....',
|
||||
'I': '..', 'i': '..',
|
||||
'J': '.---', 'j': '.---',
|
||||
'K': '-.-', 'k': '-.-',
|
||||
'L': '.-..', 'l': '.-..',
|
||||
'M': '--', 'm': '--',
|
||||
'N': '-.', 'n': '-.',
|
||||
'O': '---', 'o': '---',
|
||||
'P': '.--.', 'p': '.--.',
|
||||
'Q': '--.-', 'q': '--.-',
|
||||
'R': '.-.', 'r': '.-.',
|
||||
'S': '...', 's': '...',
|
||||
'T': '-', 't': '-',
|
||||
'U': '..-', 'u': '..-',
|
||||
'V': '...-', 'v': '...-',
|
||||
'W': '.--', 'w': '.--',
|
||||
'X': '-..-', 'x': '-..-',
|
||||
'Y': '-.--', 'y': '-.--',
|
||||
'Z': '--..', 'z': '--..',
|
||||
'0': '-----',
|
||||
'1': '.----',
|
||||
'2': '..---',
|
||||
'3': '...--',
|
||||
'4': '....-',
|
||||
'5': '.....',
|
||||
'6': '-....',
|
||||
'7': '--...',
|
||||
'8': '---..',
|
||||
'9': '----.',
|
||||
',': '--..--',
|
||||
'.': '.-.-.-',
|
||||
'?': '..--..',
|
||||
';': '-.-.-.',
|
||||
':': '---...',
|
||||
"'": '.----.',
|
||||
'-': '-....-',
|
||||
'/': '-..-.',
|
||||
'(': '-.--.-',
|
||||
')': '-.--.-',
|
||||
'_': '..--.-',
|
||||
' ': ' '
|
||||
}
|
||||
|
||||
# If we play at 44.1 kHz (which we do), then if we produce one sine
|
||||
# wave in 100 samples, we get a tone of 441 Hz. If we produce two
|
||||
# sine waves in these 100 samples, we get a tone of 882 Hz. 882 Hz
|
||||
# appears to be a nice one for playing morse code.
|
||||
def mkwave(octave):
|
||||
global sinewave, nowave
|
||||
sinewave = ''
|
||||
n = int(FRAMERATE / BASEFREQ)
|
||||
for i in range(n):
|
||||
val = int(math.sin(2 * math.pi * i * octave / n) * 0x7fff)
|
||||
sample = chr((val >> 8) & 255) + chr(val & 255)
|
||||
sinewave = sinewave + sample[:SAMPWIDTH]
|
||||
nowave = '\0' * (n*SAMPWIDTH)
|
||||
|
||||
mkwave(OCTAVE)
|
||||
|
||||
class BufferedAudioDev:
|
||||
def __init__(self, *args):
|
||||
import audiodev
|
||||
self._base = apply(audiodev.AudioDev, args)
|
||||
self._buffer = []
|
||||
self._filled = 0
|
||||
self._addmethods(self._base, self._base.__class__)
|
||||
def _addmethods(self, inst, cls):
|
||||
for name in cls.__dict__.keys():
|
||||
if not hasattr(self, name):
|
||||
try:
|
||||
setattr(self, name, getattr(inst, name))
|
||||
except:
|
||||
pass
|
||||
for basecls in cls.__bases__:
|
||||
self._addmethods(self, inst, basecls)
|
||||
def writeframesraw(self, frames):
|
||||
self._buffer.append(frames)
|
||||
self._filled = self._filled + len(frames)
|
||||
if self._filled >= QSIZE:
|
||||
self.flush()
|
||||
def wait(self):
|
||||
self.flush()
|
||||
self._base.wait()
|
||||
def flush(self):
|
||||
print 'flush: %d blocks, %d bytes' % (len(self._buffer), self._filled)
|
||||
if self._buffer:
|
||||
import string
|
||||
self._base.writeframes(string.joinfields(self._buffer, ''))
|
||||
self._buffer = []
|
||||
self._filled = 0
|
||||
|
||||
def main(args = sys.argv[1:]):
|
||||
import getopt, string
|
||||
try:
|
||||
opts, args = getopt.getopt(args, 'o:p:')
|
||||
except getopt.error:
|
||||
sys.stderr.write('Usage ' + sys.argv[0] +
|
||||
' [ -o outfile ] [ args ] ...\n')
|
||||
sys.exit(1)
|
||||
dev = None
|
||||
for o, a in opts:
|
||||
if o == '-o':
|
||||
import aifc
|
||||
dev = aifc.open(a, 'w')
|
||||
dev.setframerate(FRAMERATE)
|
||||
dev.setsampwidth(SAMPWIDTH)
|
||||
dev.setnchannels(1)
|
||||
if o == '-p':
|
||||
mkwave(string.atoi(a))
|
||||
if not dev:
|
||||
dev = BufferedAudioDev()
|
||||
dev.setoutrate(FRAMERATE)
|
||||
dev.setsampwidth(SAMPWIDTH)
|
||||
dev.setnchannels(1)
|
||||
dev.close = dev.stop
|
||||
if args:
|
||||
line = string.join(args)
|
||||
else:
|
||||
line = sys.stdin.readline()
|
||||
while line:
|
||||
print line
|
||||
mline = morse(line)
|
||||
print mline
|
||||
play(mline, dev)
|
||||
if hasattr(dev, 'wait'):
|
||||
dev.wait()
|
||||
if not args:
|
||||
line = sys.stdin.readline()
|
||||
else:
|
||||
line = ''
|
||||
dev.close()
|
||||
|
||||
# Convert a string to morse code with \001 between the characters in
|
||||
# the string.
|
||||
def morse(line):
|
||||
res = ''
|
||||
for c in line:
|
||||
try:
|
||||
res = res + morsetab[c] + '\001'
|
||||
except KeyError:
|
||||
pass
|
||||
return res
|
||||
|
||||
# Play a line of morse code.
|
||||
def play(line, dev):
|
||||
for c in line:
|
||||
if c == '.':
|
||||
sine(dev, DOT)
|
||||
elif c == '-':
|
||||
sine(dev, DAH)
|
||||
else:
|
||||
pause(dev, DAH)
|
||||
pause(dev, DOT)
|
||||
|
||||
def sine(dev, length):
|
||||
dev.writeframesraw(sinewave*length)
|
||||
|
||||
def pause(dev, length):
|
||||
dev.writeframesraw(nowave*length)
|
||||
|
||||
if __name__ == '__main__' or sys.argv[0] == __name__:
|
||||
main()
|
||||
188
Mac/Demo/sound/morselib.py
Normal file
@@ -0,0 +1,188 @@
|
||||
"""Translate text strings to Morse code"""
|
||||
|
||||
FRAMERATE = 22050
|
||||
SAMPWIDTH = 2
|
||||
|
||||
BASEFREQ = 441
|
||||
OCTAVE = 2
|
||||
|
||||
DOT = 30
|
||||
DAH = 80
|
||||
|
||||
morsetab = {
|
||||
'a': '.-',
|
||||
'b': '-...',
|
||||
'c': '-.-.',
|
||||
'd': '-..',
|
||||
'e': '.',
|
||||
'f': '..-.',
|
||||
'g': '--.',
|
||||
'h': '....',
|
||||
'i': '..',
|
||||
'j': '.---',
|
||||
'k': '-.-',
|
||||
'l': '.-..',
|
||||
'm': '--',
|
||||
'n': '-.',
|
||||
'o': '---',
|
||||
'p': '.--.',
|
||||
'q': '--.-',
|
||||
'r': '.-.',
|
||||
's': '...',
|
||||
't': '-',
|
||||
'u': '..-',
|
||||
'v': '...-',
|
||||
'w': '.--',
|
||||
'x': '-..-',
|
||||
'y': '-.--',
|
||||
'z': '--..',
|
||||
'0': '-----',
|
||||
'1': '.----',
|
||||
'2': '..---',
|
||||
'3': '...--',
|
||||
'4': '....-',
|
||||
'5': '.....',
|
||||
'6': '-....',
|
||||
'7': '--...',
|
||||
'8': '---..',
|
||||
'9': '----.',
|
||||
',': '--..--',
|
||||
'.': '.-.-.-',
|
||||
'?': '..--..',
|
||||
';': '-.-.-.',
|
||||
':': '---...',
|
||||
"'": '.----.',
|
||||
'-': '-....-',
|
||||
'/': '-..-.',
|
||||
'(': '-.--.-',
|
||||
')': '-.--.-', # XXX same as code for '(' ???
|
||||
'_': '..--.-',
|
||||
' ': ' '
|
||||
}
|
||||
|
||||
def morsecode(s):
|
||||
from string import lower
|
||||
m = ''
|
||||
for c in s:
|
||||
c = lower(c)
|
||||
if morsetab.has_key(c):
|
||||
c = morsetab[c] + ' '
|
||||
else:
|
||||
c = '? '
|
||||
m = m + c
|
||||
return m
|
||||
|
||||
|
||||
class BaseMorse:
|
||||
"base class for morse transmissions"
|
||||
|
||||
def __init__(self):
|
||||
"constructor"
|
||||
self.dots = DOT
|
||||
self.dahs = DAH
|
||||
|
||||
def noise(self, duration):
|
||||
"beep for given duration"
|
||||
pass
|
||||
|
||||
def pause(self, duration):
|
||||
"pause for given duration"
|
||||
pass
|
||||
|
||||
def dot(self):
|
||||
"short beep"
|
||||
self.noise(self.dots)
|
||||
|
||||
def dah(self):
|
||||
"long beep"
|
||||
self.noise(self.dahs)
|
||||
|
||||
def pdot(self):
|
||||
"pause as long as a dot"
|
||||
self.pause(self.dots)
|
||||
|
||||
def pdah(self):
|
||||
"pause as long as a dah"
|
||||
self.pause(self.dahs)
|
||||
|
||||
def sendmorse(self, s):
|
||||
for c in s:
|
||||
if c == '.': self.dot()
|
||||
elif c == '-': self.dah()
|
||||
else: self.pdah()
|
||||
self.pdot()
|
||||
|
||||
def sendascii(self, s):
|
||||
self.sendmorse(morsecode(s))
|
||||
|
||||
def send(self, s):
|
||||
self.sendascii(s)
|
||||
|
||||
|
||||
import Audio_mac
|
||||
class MyAudio(Audio_mac.Play_Audio_mac):
|
||||
def _callback(self, *args):
|
||||
if hasattr(self, 'usercallback'): self.usercallback()
|
||||
apply(Audio_mac.Play_Audio_mac._callback, (self,) + args)
|
||||
|
||||
|
||||
class MacMorse(BaseMorse):
|
||||
"Mac specific class to play Morse code"
|
||||
|
||||
def __init__(self):
|
||||
BaseMorse.__init__(self)
|
||||
self.dev = MyAudio()
|
||||
self.dev.setoutrate(FRAMERATE)
|
||||
self.dev.setsampwidth(SAMPWIDTH)
|
||||
self.dev.setnchannels(1)
|
||||
self.dev.usercallback = self.usercallback
|
||||
sinewave = ''
|
||||
n = int(FRAMERATE / BASEFREQ)
|
||||
octave = OCTAVE
|
||||
from math import sin, pi
|
||||
for i in range(n):
|
||||
val = int(sin(2 * pi * i * octave / n) * 0x7fff)
|
||||
sample = chr((val >> 8) & 255) + chr(val & 255)
|
||||
sinewave = sinewave + sample[:SAMPWIDTH]
|
||||
self.sinewave = sinewave
|
||||
self.silence = '\0' * (n*SAMPWIDTH)
|
||||
self.morsequeue = ''
|
||||
|
||||
def __del__(self):
|
||||
self.close()
|
||||
|
||||
def close(self):
|
||||
self.dev = None
|
||||
|
||||
def pause(self, duration):
|
||||
self.dev.writeframes(self.silence * duration)
|
||||
|
||||
def noise(self, duration):
|
||||
self.dev.writeframes(self.sinewave * duration)
|
||||
|
||||
def sendmorse(self, s):
|
||||
self.morsequeue = self.morsequeue + s
|
||||
self.dev.usercallback()
|
||||
self.dev.usercallback()
|
||||
self.dev.usercallback()
|
||||
|
||||
def usercallback(self):
|
||||
if self.morsequeue:
|
||||
c, self.morsequeue = self.morsequeue[0], self.morsequeue[1:]
|
||||
if c == '.': self.dot()
|
||||
elif c == '-': self.dah()
|
||||
else: self.pdah()
|
||||
self.pdot()
|
||||
|
||||
|
||||
def test():
|
||||
m = MacMorse()
|
||||
while 1:
|
||||
try:
|
||||
line = raw_input('Morse line: ')
|
||||
except (EOFError, KeyboardInterrupt):
|
||||
break
|
||||
m.send(line)
|
||||
while m.morsequeue: pass
|
||||
|
||||
test()
|
||||
45
Mac/Demo/sound/playaiff.py
Normal file
@@ -0,0 +1,45 @@
|
||||
from Carbon.Sound import *
|
||||
from Carbon import Snd
|
||||
|
||||
import aifc, audioop
|
||||
|
||||
fn = 'f:just samples:2ndbeat.aif'
|
||||
af = aifc.open(fn, 'r')
|
||||
print af.getparams()
|
||||
print 'nframes =', af.getnframes()
|
||||
print 'nchannels =', af.getnchannels()
|
||||
print 'framerate =', af.getframerate()
|
||||
nframes = min(af.getnframes(), 100000)
|
||||
frames = af.readframes(nframes)
|
||||
print 'len(frames) =', len(frames)
|
||||
print repr(frames[:100])
|
||||
frames = audioop.add(frames, '\x80'*len(frames), 1)
|
||||
print repr(frames[:100])
|
||||
|
||||
import struct
|
||||
|
||||
header1 = struct.pack('llhhllbbl',
|
||||
0,
|
||||
af.getnchannels(),
|
||||
af.getframerate(),0,
|
||||
0,
|
||||
0,
|
||||
0xFF,
|
||||
60,
|
||||
nframes)
|
||||
print repr(header1)
|
||||
header2 = struct.pack('llhlll', 0, 0, 0, 0, 0, 0)
|
||||
header3 = struct.pack('hhlll',
|
||||
af.getsampwidth()*8,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0)
|
||||
print repr(header3)
|
||||
header = header1 + header2 + header3
|
||||
|
||||
buffer = header + frames
|
||||
|
||||
chan = Snd.SndNewChannel(5,0x00C0)
|
||||
|
||||
Snd.SndDoCommand(chan, (bufferCmd, 0, buffer), 0)
|
||||
150
Mac/Demo/textedit.html
Normal file
@@ -0,0 +1,150 @@
|
||||
<HTML><HEAD><TITLE>Using FrameWork and TextEdit</TITLE></HEAD>
|
||||
<BODY>
|
||||
<H1>Using FrameWork and TextEdit</H1>
|
||||
<HR>
|
||||
|
||||
In this document we use the <CODE>FrameWork</CODE> and <CODE>TextEdit</CODE>
|
||||
modules to create a simple text editor. The functionality
|
||||
of the editor is very basic: you can open multiple files, type text and use
|
||||
cut/copy/paste. The main intention is to explain the use of FrameWork, really. <p>
|
||||
|
||||
<H2>FrameWork</H2>
|
||||
|
||||
The FrameWork module provides you with a skeleton application. It declares a
|
||||
number of classes suitable for subclassing in your application, thereby
|
||||
releaving you of the burden of doing all event handling, etc. yourself. For a
|
||||
real understanding you will have to browse the source. Here is a short overview
|
||||
of the classes and what functionality they provide.
|
||||
|
||||
<dl>
|
||||
<dt> <CODE>Application</CODE>
|
||||
<dd>
|
||||
This is the toplevel class you will override. It maintains the menu bar and contains
|
||||
the main event handling code. Normal use is to override the <code>__init__</code> routine
|
||||
to do your own initializations and override <code>makeusermenus</code> to create your menus
|
||||
(your menu callback routines may be here too, but this is by no means necessary).
|
||||
The event handling code can be overridden at various levels, from very low-level (the
|
||||
<code>dispatch</code> method) to intermediate level (<code>do_keyDown</code>, for instance)
|
||||
to high-level (<code>do_key</code>). The application class knows about the <code>Window</code>
|
||||
objects you create, and will forward events to the appropriate window (So, normally you
|
||||
would have a <code>do_key</code> method in your window object, not your application object).
|
||||
|
||||
<dt> <CODE>MenuBar</CODE>, <CODE>Menu</CODE> and <CODE>MenuItem</CODE>
|
||||
<dd>
|
||||
These classes (and a few friends like <CODE>SubMenu</CODE>) handle your menus. You would not
|
||||
normally override them but use them as-is. The idiom for creating menus is a bit strange,
|
||||
see the test code at the bottom of FrameWork for sample use. The apple menu is handled for you
|
||||
by <CODE>MenuBar</CODE> and <CODE>Application</CODE>.
|
||||
|
||||
<dt> <CODE>Window</CODE>
|
||||
<dd>
|
||||
The basic window. Again, a class that you normally subclass in your application, possibly
|
||||
multiple times if you have different types of windows. The init call instantiates the data
|
||||
structure but actually opening the window is delayed until you call <code>open</code>. Your
|
||||
open method should call <code>do_postopen</code> to let the base class handle linking in to
|
||||
the application object. Similarly with <code>close</code> and <code>do_postclose</code>. The
|
||||
rest of the code is mainly event-oriented: you override <code>do_postresize</code>,
|
||||
<code>do_contentclick</code>, <code>do_update</code>, <code>do_activate</code>
|
||||
and <code>do_key</code> to "do your thing". When these methods are called the relevant environment
|
||||
has been setup (like <code>BeginDrawing</code> has been called for updates, etc).
|
||||
|
||||
<dt> <CODE>windowbounds</CODE>
|
||||
<dd>
|
||||
Not a class but a function: you pass it a width and height and it will return you a rectangle
|
||||
you can use to create your window. It will take care of staggering windows and it will try
|
||||
to fit the window on the screen (but the resulting rect will <em>always</em> have the size you
|
||||
specify).
|
||||
|
||||
<dt> <CODE>ControlsWindow</CODE>
|
||||
<dd>
|
||||
A subclass of Window which automatically handles drawing and clicking for controls. You override
|
||||
the same methods as for Window (if you need to: control-related things are done automatically) and
|
||||
<code>do_controlhit</code>.
|
||||
|
||||
<dt> <CODE>ScrolledWindow</CODE>
|
||||
<dd>
|
||||
A subclass of ControlsWindow, a window with optional scrollbars. If you override <code>do_activate</code>
|
||||
or <code>do_postresize</code> you must call the ScrolledWindow methods at the end of your override.
|
||||
You call <code>scrollbars</code> to enable/disable scrollbars and <code>updatescrollbars</code> to
|
||||
update them. You provide <code>getscrollbarvalues</code> to return the current x/y values (a helper
|
||||
method <code>scalebarvalues</code> is available) and <code>scrollbarcallback</code> to update your
|
||||
display after the user has used the scrollbars.
|
||||
|
||||
<dt> <CODE>DialogWindow</CODE>
|
||||
<dd>
|
||||
A modeless dialog window initialized from a DLOG resource. See the
|
||||
<A HREF="example2.html">second Interslip example</A> for its useage.
|
||||
</dl>
|
||||
|
||||
<H2>A sample text editor</H2>
|
||||
|
||||
Let us have a look at <A HREF="textedit/ped.py">ped.py</A> (in the Demo:textedit folder), the Pathetic
|
||||
EDitor. It has multiple windows, cut/copy/paste and keyboard input, but that is about all. It looks
|
||||
as if you can resize the window but it does not work. Still, it serves as an example.
|
||||
|
||||
Ped creates two classes, <code>TEWindow</code> and <code>Ped</code>. Let us start with the latter one,
|
||||
which is a subclass of <code>FrameWork.Application</code> and our main application. The init function
|
||||
has little to do aside from the standard init: it remembers a window sequence number (for untitled windows),
|
||||
and sets things up for menu disable to work. Remember, the <code>makeusermenus</code> is called
|
||||
automatically. <p>
|
||||
|
||||
<code>Makeusermenus</code> creates the <code>File</code> and <code>Edit</code> menus. It also initializes
|
||||
a couple of lists that are used later to correctly enable and disable menu items (and complete menus) depending
|
||||
on whether a window is open, text is selected, etc. The callback functions for the menu items are
|
||||
all methods of this class. <p>
|
||||
|
||||
<code>Updatemenubar</code> handles greying out (and re-enabling) of menu items depending on whether there
|
||||
is a current window and its state. <p>
|
||||
|
||||
The rest of the methods are all callbacks and simple to understand. They check whether there is an active
|
||||
window (and complain loudly if there is none: the corresponding menu entry should have been disabled
|
||||
in that case!) and call the appropriate window method. Only the <code>_open</code> method (the common code
|
||||
for <code>Open</code> and <code>New</code>) deserves some mention. It instantiates a <code>TEWindow</code>
|
||||
object and opens it with the title, filename and contents of the file to edit. Note that FrameWork takes
|
||||
care of remembering the window object. A minor note on opening the file in binary mode: this is because
|
||||
TextEdit expects MacOS style carriage-return terminated lines, not python/unix/C style newline-terminated
|
||||
lines. <p>
|
||||
|
||||
Oh yes: the <code>quit</code> callback does a little magic too. It closes all windows, and only if this
|
||||
succeeds it actually quits. This gives the user a chance to cancel the operation if some files are unsaved.
|
||||
<p>
|
||||
|
||||
Lastly, there is the <code>idle</code> method, called by the Application base class when no event
|
||||
is available. It is forwarded to the active window, so it can blink the text caret. <p>
|
||||
|
||||
The <code>TEWindow</code> object handles a single window. Due to this structuring it is absolutely no
|
||||
problem to have multiple windows open at the same time (although a real application should exercise care when
|
||||
two windows refer to the same document). TEWindow uses the standard init code inherited from
|
||||
<code>ScrolledWindow</code>, and sets itself up at the time of the <code>open</code> call. It obtains screen
|
||||
coordinates, opens the window, creates rectangles for TextEdit to work in (the magical number <code>15</code>
|
||||
here is the size of a normal scroll bar: unfortunately there is no symbolic constant for it),
|
||||
creates the TextEdit object and initializes it with our data. Finally, the scroll bars are created (the
|
||||
initial values will be obtained automatically through <code>getscrollbarvalues</code>) and we activate
|
||||
ourselves (this is unfortunately not done automatically by the MacOS event handling code). <p>
|
||||
|
||||
<code>Do_idle</code> simply calls the TextEdit routine that blinks the cursor. <code>Getscrollbarvalues</code>
|
||||
returns the current X and Y scrollbar values, scaled to <code>0..32767</code>. For X we return <code>None</code>,
|
||||
which means "no scrollbar, please", for Y we use the scaler provided by <code>ScrolledWindow</code>. <p>
|
||||
|
||||
<code>Scrollbar_callback</code> is called when the user uses the scrollbar. It is passed a string <code>'x'</code>
|
||||
or <code>'y'</code>, one of <code>'set', '-', '--', '+', '++'</code> and (for <code>set</code>) an absolute
|
||||
value. Note that the sign of the value passed to <code>TEPinScroll</code> is counter-intuitive. <p>
|
||||
|
||||
<code>do_activate</code> (de)activates the scrollbars and calls the relevant TextEdit routine. Moreover, it
|
||||
tells the application object if we are now the active window, and updates the menubar. The next few methods
|
||||
are update and menu callbacks, and pretty straightforward. Note that <code>do_close</code> can
|
||||
return without closing the window (if the document is changed and the users cancels out of the operation).
|
||||
Also note the "magic" in <code>menu_save_as</code>
|
||||
that set the correct window title. <p>
|
||||
|
||||
Things get moderately interesting again at the cut/copy/paste handling, since the TextEdit scrap is
|
||||
separate from the desktop scrap. For that reason there are various calls to routines that move the scrap
|
||||
back and forth. <code>Have_selection</code> is called by the menubar update code to determine whether cut and
|
||||
copy should be enabled. <p>
|
||||
|
||||
Understanding the main program is left as an exercise to the reader. <p>
|
||||
|
||||
<hr>
|
||||
That's all for this example, you could now continue with the <A HREF="waste.html">next example</A>, where we use WASTE, a more-or-less
|
||||
TextEdit compatible library with more functionality, to rebuild our editor. Or you can
|
||||
return to the <A HREF="index.html">table of contents</A> to pick another topic. <p>
|
||||
359
Mac/Demo/textedit/ped.py
Normal file
@@ -0,0 +1,359 @@
|
||||
# A minimal text editor.
|
||||
#
|
||||
# To be done:
|
||||
# - Update viewrect after resize
|
||||
# - Handle horizontal scrollbar correctly
|
||||
# - Functionality: find, etc.
|
||||
|
||||
from Carbon.Menu import DrawMenuBar
|
||||
from FrameWork import *
|
||||
from Carbon import Win
|
||||
from Carbon import Qd
|
||||
from Carbon import TE
|
||||
from Carbon import Scrap
|
||||
import os
|
||||
import macfs
|
||||
|
||||
class TEWindow(ScrolledWindow):
|
||||
def open(self, path, name, data):
|
||||
self.path = path
|
||||
self.name = name
|
||||
r = windowbounds(400, 400)
|
||||
w = Win.NewWindow(r, name, 1, 0, -1, 1, 0)
|
||||
self.wid = w
|
||||
x0, y0, x1, y1 = self.wid.GetWindowPort().GetPortBounds()
|
||||
x0 = x0 + 4
|
||||
y0 = y0 + 4
|
||||
x1 = x1 - 20
|
||||
y1 = y1 - 20
|
||||
vr = dr = x0, y0, x1, y1
|
||||
##vr = 4, 0, r[2]-r[0]-15, r[3]-r[1]-15
|
||||
##dr = (0, 0, vr[2], 0)
|
||||
Qd.SetPort(w)
|
||||
Qd.TextFont(4)
|
||||
Qd.TextSize(9)
|
||||
self.ted = TE.TENew(dr, vr)
|
||||
self.ted.TEAutoView(1)
|
||||
self.ted.TESetText(data)
|
||||
w.DrawGrowIcon()
|
||||
self.scrollbars()
|
||||
self.changed = 0
|
||||
self.do_postopen()
|
||||
self.do_activate(1, None)
|
||||
|
||||
def do_idle(self):
|
||||
self.ted.TEIdle()
|
||||
|
||||
def getscrollbarvalues(self):
|
||||
dr = self.ted.destRect
|
||||
vr = self.ted.viewRect
|
||||
height = self.ted.nLines * self.ted.lineHeight
|
||||
vx = self.scalebarvalue(dr[0], dr[2]-dr[0], vr[0], vr[2])
|
||||
vy = self.scalebarvalue(dr[1], dr[1]+height, vr[1], vr[3])
|
||||
print dr, vr, height, vx, vy
|
||||
return None, vy
|
||||
|
||||
def scrollbar_callback(self, which, what, value):
|
||||
if which == 'y':
|
||||
if what == 'set':
|
||||
height = self.ted.nLines * self.ted.lineHeight
|
||||
cur = self.getscrollbarvalues()[1]
|
||||
delta = (cur-value)*height/32767
|
||||
if what == '-':
|
||||
delta = self.ted.lineHeight
|
||||
elif what == '--':
|
||||
delta = (self.ted.viewRect[3]-self.ted.lineHeight)
|
||||
if delta <= 0:
|
||||
delta = self.ted.lineHeight
|
||||
elif what == '+':
|
||||
delta = -self.ted.lineHeight
|
||||
elif what == '++':
|
||||
delta = -(self.ted.viewRect[3]-self.ted.lineHeight)
|
||||
if delta >= 0:
|
||||
delta = -self.ted.lineHeight
|
||||
self.ted.TEPinScroll(0, delta)
|
||||
print 'SCROLL Y', delta
|
||||
else:
|
||||
pass # No horizontal scrolling
|
||||
|
||||
def do_activate(self, onoff, evt):
|
||||
print "ACTIVATE", onoff
|
||||
ScrolledWindow.do_activate(self, onoff, evt)
|
||||
if onoff:
|
||||
self.ted.TEActivate()
|
||||
self.parent.active = self
|
||||
self.parent.updatemenubar()
|
||||
else:
|
||||
self.ted.TEDeactivate()
|
||||
|
||||
def do_update(self, wid, event):
|
||||
Qd.EraseRect(wid.GetWindowPort().GetPortBounds())
|
||||
self.ted.TEUpdate(wid.GetWindowPort().GetPortBounds())
|
||||
self.updatescrollbars()
|
||||
|
||||
def do_contentclick(self, local, modifiers, evt):
|
||||
shifted = (modifiers & 0x200)
|
||||
self.ted.TEClick(local, shifted)
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def do_char(self, ch, event):
|
||||
self.ted.TESelView()
|
||||
self.ted.TEKey(ord(ch))
|
||||
self.changed = 1
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def close(self):
|
||||
if self.changed:
|
||||
save = EasyDialogs.AskYesNoCancel('Save window "%s" before closing?'%self.name, 1)
|
||||
if save > 0:
|
||||
self.menu_save()
|
||||
elif save < 0:
|
||||
return
|
||||
if self.parent.active == self:
|
||||
self.parent.active = None
|
||||
self.parent.updatemenubar()
|
||||
del self.ted
|
||||
self.do_postclose()
|
||||
|
||||
def menu_save(self):
|
||||
if not self.path:
|
||||
self.menu_save_as()
|
||||
return # Will call us recursively
|
||||
print 'Saving to ', self.path
|
||||
dhandle = self.ted.TEGetText()
|
||||
data = dhandle.data
|
||||
fp = open(self.path, 'wb') # NOTE: wb, because data has CR for end-of-line
|
||||
fp.write(data)
|
||||
if data[-1] <> '\r': fp.write('\r')
|
||||
fp.close()
|
||||
self.changed = 0
|
||||
|
||||
def menu_save_as(self):
|
||||
path = EasyDialogs.AskFileForSave(message='Save as:')
|
||||
if not path: return
|
||||
self.path = path
|
||||
self.name = os.path.split(self.path)[-1]
|
||||
self.wid.SetWTitle(self.name)
|
||||
self.menu_save()
|
||||
|
||||
def menu_cut(self):
|
||||
self.ted.TESelView()
|
||||
self.ted.TECut()
|
||||
if hasattr(Scrap, 'ZeroScrap'):
|
||||
Scrap.ZeroScrap()
|
||||
else:
|
||||
Scrap.ClearCurrentScrap()
|
||||
TE.TEToScrap()
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
self.changed = 1
|
||||
|
||||
def menu_copy(self):
|
||||
self.ted.TECopy()
|
||||
if hasattr(Scrap, 'ZeroScrap'):
|
||||
Scrap.ZeroScrap()
|
||||
else:
|
||||
Scrap.ClearCurrentScrap()
|
||||
TE.TEToScrap()
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
|
||||
def menu_paste(self):
|
||||
TE.TEFromScrap()
|
||||
self.ted.TESelView()
|
||||
self.ted.TEPaste()
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
self.changed = 1
|
||||
|
||||
def menu_clear(self):
|
||||
self.ted.TESelView()
|
||||
self.ted.TEDelete()
|
||||
self.updatescrollbars()
|
||||
self.parent.updatemenubar()
|
||||
self.changed = 1
|
||||
|
||||
def have_selection(self):
|
||||
return (self.ted.selStart < self.ted.selEnd)
|
||||
|
||||
class Ped(Application):
|
||||
def __init__(self):
|
||||
Application.__init__(self)
|
||||
self.num = 0
|
||||
self.active = None
|
||||
self.updatemenubar()
|
||||
|
||||
def makeusermenus(self):
|
||||
self.filemenu = m = Menu(self.menubar, "File")
|
||||
self.newitem = MenuItem(m, "New window", "N", self.open)
|
||||
self.openitem = MenuItem(m, "Open...", "O", self.openfile)
|
||||
self.closeitem = MenuItem(m, "Close", "W", self.closewin)
|
||||
m.addseparator()
|
||||
self.saveitem = MenuItem(m, "Save", "S", self.save)
|
||||
self.saveasitem = MenuItem(m, "Save as...", "", self.saveas)
|
||||
m.addseparator()
|
||||
self.quititem = MenuItem(m, "Quit", "Q", self.quit)
|
||||
|
||||
self.editmenu = m = Menu(self.menubar, "Edit")
|
||||
self.undoitem = MenuItem(m, "Undo", "Z", self.undo)
|
||||
self.cutitem = MenuItem(m, "Cut", "X", self.cut)
|
||||
self.copyitem = MenuItem(m, "Copy", "C", self.copy)
|
||||
self.pasteitem = MenuItem(m, "Paste", "V", self.paste)
|
||||
self.clearitem = MenuItem(m, "Clear", "", self.clear)
|
||||
|
||||
# Not yet implemented:
|
||||
self.undoitem.enable(0)
|
||||
|
||||
# Groups of items enabled together:
|
||||
self.windowgroup = [self.closeitem, self.saveitem, self.saveasitem, self.editmenu]
|
||||
self.focusgroup = [self.cutitem, self.copyitem, self.clearitem]
|
||||
self.windowgroup_on = -1
|
||||
self.focusgroup_on = -1
|
||||
self.pastegroup_on = -1
|
||||
|
||||
def updatemenubar(self):
|
||||
changed = 0
|
||||
on = (self.active <> None)
|
||||
if on <> self.windowgroup_on:
|
||||
for m in self.windowgroup:
|
||||
m.enable(on)
|
||||
self.windowgroup_on = on
|
||||
changed = 1
|
||||
if on:
|
||||
# only if we have an edit menu
|
||||
on = self.active.have_selection()
|
||||
if on <> self.focusgroup_on:
|
||||
for m in self.focusgroup:
|
||||
m.enable(on)
|
||||
self.focusgroup_on = on
|
||||
changed = 1
|
||||
if hasattr(Scrap, 'InfoScrap'):
|
||||
on = (Scrap.InfoScrap()[0] <> 0)
|
||||
else:
|
||||
flavors = Scrap.GetCurrentScrap().GetScrapFlavorInfoList()
|
||||
for tp, info in flavors:
|
||||
if tp == 'TEXT':
|
||||
on = 1
|
||||
break
|
||||
else:
|
||||
on = 0
|
||||
if on <> self.pastegroup_on:
|
||||
self.pasteitem.enable(on)
|
||||
self.pastegroup_on = on
|
||||
changed = 1
|
||||
if changed:
|
||||
DrawMenuBar()
|
||||
|
||||
#
|
||||
# Apple menu
|
||||
#
|
||||
|
||||
def do_about(self, id, item, window, event):
|
||||
EasyDialogs.Message("A simple single-font text editor")
|
||||
|
||||
#
|
||||
# File menu
|
||||
#
|
||||
|
||||
def open(self, *args):
|
||||
self._open(0)
|
||||
|
||||
def openfile(self, *args):
|
||||
self._open(1)
|
||||
|
||||
def _open(self, askfile):
|
||||
if askfile:
|
||||
path = EasyDialogs.AskFileForOpen(typeList=('TEXT',))
|
||||
if not path:
|
||||
return
|
||||
name = os.path.split(path)[-1]
|
||||
try:
|
||||
fp = open(path, 'rb') # NOTE binary, we need cr as end-of-line
|
||||
data = fp.read()
|
||||
fp.close()
|
||||
except IOError, arg:
|
||||
EasyDialogs.Message("IOERROR: %r" % (arg,))
|
||||
return
|
||||
else:
|
||||
path = None
|
||||
name = "Untitled %d"%self.num
|
||||
data = ''
|
||||
w = TEWindow(self)
|
||||
w.open(path, name, data)
|
||||
self.num = self.num + 1
|
||||
|
||||
def closewin(self, *args):
|
||||
if self.active:
|
||||
self.active.close()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def save(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_save()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def saveas(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_save_as()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
|
||||
def quit(self, *args):
|
||||
for w in self._windows.values():
|
||||
w.close()
|
||||
if self._windows:
|
||||
return
|
||||
self._quit()
|
||||
|
||||
#
|
||||
# Edit menu
|
||||
#
|
||||
|
||||
def undo(self, *args):
|
||||
pass
|
||||
|
||||
def cut(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_cut()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def copy(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_copy()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def paste(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_paste()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
def clear(self, *args):
|
||||
if self.active:
|
||||
self.active.menu_clear()
|
||||
else:
|
||||
EasyDialogs.Message("No active window?")
|
||||
|
||||
#
|
||||
# Other stuff
|
||||
#
|
||||
|
||||
def idle(self, *args):
|
||||
if self.active:
|
||||
self.active.do_idle()
|
||||
else:
|
||||
Qd.SetCursor(Qd.GetQDGlobalsArrow())
|
||||
|
||||
def main():
|
||||
App = Ped()
|
||||
App.mainloop()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||