From 08365425f6ec63335951d831918b5fa5ec4934c1 Mon Sep 17 00:00:00 2001 From: Jack Jansen Date: Fri, 19 Apr 1996 15:56:08 +0000 Subject: Added documentation on FrameWork, TextEdit and Waste Updated minor things in the other documents (pathnames, etc) --- Mac/Demo/applescript.html | 13 ++-- Mac/Demo/example2.html | 18 +++--- Mac/Demo/index.html | 51 +++++++++++----- Mac/Demo/textedit.html | 152 ++++++++++++++++++++++++++++++++++++++++++++++ Mac/Demo/using.html | 24 ++++++-- Mac/Demo/waste.html | 69 +++++++++++++++++++++ 6 files changed, 291 insertions(+), 36 deletions(-) create mode 100644 Mac/Demo/textedit.html create mode 100644 Mac/Demo/waste.html diff --git a/Mac/Demo/applescript.html b/Mac/Demo/applescript.html index 35cbf49..7db5ba6 100644 --- a/Mac/Demo/applescript.html +++ b/Mac/Demo/applescript.html @@ -32,7 +32,7 @@ There is a tool in the standard distribution that looks through a file for an 'AETE' or 'AEUT' resource, the internal representation of the AppleScript dictionary. This tool is called gensuitemodule.py, and lives in -Tools:bgen:ae. When we start it, it asks us for an input +Mac:scripts. When we start it, it asks us for an input file and we point it to the Eudora Light executable. It starts parsing the AETE resource, and for each AppleEvent suite it finds it prompts us for the filename of the resulting python module. Remember to change @@ -46,7 +46,7 @@ gensuitemodule does not currently understand this. Creating the empty Required_Suite.py would hide the correct module of that name from our application.

- +

Time for a sidebar. If you want to re-create Required_Suite.py or one of the other standard modules you should look in System Folder:Extensions:Scripting @@ -55,7 +55,7 @@ AppleEvent dictionaries live. Also, if you are looking for the Finder_Suite interface: don't look in the finder (it has an old System 7.0 scripting suite), look at the extension Finder Scripting Extension.

- +

Let's glance at the Eudora_Suite.py just created. You @@ -81,7 +81,7 @@ arguments the verb expects, and it makes handy use of the keyword argument scheme introduced in Python 1.3 to present a palatable interface to the python programmer. You will see that each method calls some routines from aetools, an auxiliary module -living in Tools:bgen:ae which contains some other nifty +living in Lib:toolbox which contains some other nifty AppleEvent tools as well. Have a look at it sometime, there is (of course) no documentation yet.

@@ -130,10 +130,7 @@ together in the right way.

Looking at the sourcefile testeudora.py we see that it starts -with some imports (and some addpack calls to extend -sys.path to include Tools:bgen:ae, use of -ni should be preferred over addpack but I -have not managed to master it yet). Then we get the class definition +with some imports. Then we get the class definition for our main object and a constant giving the signature of Eudora.

This, again, needs a little explanation. There are various ways to diff --git a/Mac/Demo/example2.html b/Mac/Demo/example2.html index 3bd2791..aebe73d 100644 --- a/Mac/Demo/example2.html +++ b/Mac/Demo/example2.html @@ -11,7 +11,7 @@ HREF="example2/InterslipControl-2.py">Source and resource file (in binary and BinHex form for downloading) are available in the folder example2. If you want to run the program on your -machine you will also need a new copy of FrameWork.py, which has been updated since the 1.3 release.

@@ -61,15 +61,13 @@ 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.

- -A more complete description of FrameWork is -sorely needed, and will (at some point) be incorporated in the -programmers manual or in place of this paragraph. For now you'll have -to make do with the knowledge that you use FrameWork by building your -classes upon the classes provided by it and selectively overriding -methods to extend its functionality (or override the default -behaviour). And you should read the Source, of Course:-)

- +

+If you have not used FrameWork before you may want to +first take a look at the Pathetic EDitor +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. +
After the imports we get the definitions of resource-IDs in our resource file, slightly changed from the previous version of our diff --git a/Mac/Demo/index.html b/Mac/Demo/index.html index fda20b7..774db68 100644 --- a/Mac/Demo/index.html +++ b/Mac/Demo/index.html @@ -19,7 +19,7 @@ HREF="http://www-acs.ucsd.edu/~jstrout/python/"> http://www-acs.ucsd.edu/~jstrout/python/.

-The document was actually written while I was working on a "real" +Some of these documents were actually written while I was working on a "real" project: creating a single-button application that will allow my girlfriend to read her mail (which actually pass thry my mailbox, so I get to read it too, but don't tell her:-) without her @@ -28,15 +28,16 @@ application, when finished, will connect to the net using InterSLIP, start a (pseudo-)POP server on unix using rsh and use AppleScript to tell Eudora to connect to that server and retrieve messages.

- -If you want to try the examples here you will have to download some -fixes to the 1.3 distribution to your Macintosh. You need an updated +

+If you want to try the examples with a version of Python earlier +than 1.3.1 you have to download some things. You need an updated version of FrameWork.py (to go in Lib:mac and updated project templates to go into -the PlugIns folder for PPC users. -Users of 1.3.1 or later distributions don't need these fixes.

- +the PlugIns folder for PPC users.

+The TextEdit and WASTE examples are not useable with distributions +before 1.3.3. +

If you are reading this document on the web and would prefer to read it offline you can transfer the whole stuff (as a BinHexed StuffIt @@ -59,12 +60,13 @@ mac application, using a modeless dialog, menus, etc. It also explains how to create applets, standalone applications written in Python.
  • -In the Python distribution two more examples are included without -explanation. PICTbrowse is an application that locates PICT -resources and displays them, it demonstrates some quickdraw and the -resource and list namagers. Imgbrowse displays image files in -many different formats (gif, tiff, pbm, etc). It shows how to use the -img modules on the mac. +Using FrameWork and TextEdit shows you +how to use FrameWork application framework and the +TextEdit toolbox to build a text editor. + +
  • +Using WASTE expands on this editor by using +WASTE, an extended TextEdit replacement.
  • Creating a C extension module on the Macintosh @@ -79,6 +81,27 @@ how to create a Python module interfacing to a scriptable application, and how to use that module in your python program. +The Python distribution contains a few more examples, all unexplained: +
      +
    • +PICTbrowse is an application that locates PICT +resources and displays them, it demonstrates some quickdraw and the +resource and list managers. + +
    • +Imgbrowse displays image files in +many different formats (gif, tiff, pbm, etc). It shows how to use the +img modules on the mac. + +
    • +Quicktime has the standard MovieInWindow and +VerySimplePlayer examples, re-coded in Python. + +
    • +Resources, Sound and Speech have some examples +on using the respective managers. +
    + 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.

    @@ -95,4 +118,4 @@ documentation.


    Jack Jansen, -jack@cwi.nl, 7-Apr-1996. +jack@cwi.nl, 19-Apr-1996. diff --git a/Mac/Demo/textedit.html b/Mac/Demo/textedit.html new file mode 100644 index 0000000..d56ea0b --- /dev/null +++ b/Mac/Demo/textedit.html @@ -0,0 +1,152 @@ +Using FrameWork and TextEdit + +

    Using FrameWork and TextEdit

    +
    + +In this document we use the FrameWork and TextEdit +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.

    + +

    FrameWork

    + +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. + +
    +
    Application +
    +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 __init__ routine +to do your own initializations and override makeusermenus 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 +dispatch method) to intermedeate level (do_keyDown, for instance) +to high-level (do_key). The application class knows about the Window +objects you create, and will forward events to the appropriate window (So, normally you +would have a do_key method in your window object, not your application object). + +
    MenuBar, Menu and MenuItem +
    +These classes (and a few friends like SubMenu) 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 MenuBar and Application. + +
    Window +
    +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 open. Your +open method should call do_postopen to let the base class handle linking in to +the application object. Similarly with close and do_postclose. The +rest of the code is mainly event-oriented: you override do_postresize, +do_contentclick, do_update, do_activate +and do_key to "do your thing". When these methods are called the relevant environment +has been setup (like BeginDrawing has been called for updates, etc). + +
    windowbounds +
    +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 always have the size you +specify). + +
    ControlsWindow +
    +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 +do_controlhit. + +
    ScrolledWindow +
    +A subclass of ControlsWindow, a window with optional scrollbars. If you override do_activate +or do_postresize you must call the ScrolledWindow methods at the end of your override. +You call scrollbars to enable/disable scrollbars and updatescrollbars to +update them. You provide getscrollbarvalues to return the current x/y values (a helper +method scalebarvalues is available) and scrollbarcallback to update your +display after the user has used the scrollbars. + +
    DialogWindow +
    +A modeless dialog window initialized from a DLOG resource. See the +second Interslip example for its useage. +
    + +

    A sample text editor

    + +Let us have a look at ped.py (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. We will improve +on ped later, in a waste-based example.

    + +Ped creates two classes, TEWindow and Ped. Let us start with the latter one, +which is a subclass of FrameWork.Application 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 makeusermenus is called +automatically.

    + +Makeusermenus creates the File and Edit 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.

    + +Updatemenubar handles greying out (and re-enabling) of menu items depending on whether there +is a current window and its state.

    + +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 _open method (the common code +for Open and New) deserves some mention. It instantiates a TEWindow +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.

    + +Oh yes: the quit 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. +Quitting itself is also a bit strange: you raise self to break out of the main loop. This bit +of idiom was invented by Guido, so blame him:-).

    + +Lastly, there is the idle 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.

    + +The TEWindow 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 +ScrolledWindow, and sets itself up at the time of the open call. It obtains screen +coordinates, opens the window, creates rectangles for TextEdit to work in (the magical number 15 +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 getscrollbarvalues) and we activate +ourselves (this is unfortunately not done automatically by the MacOS event handling code).

    + +Do_idle simply calls the TextEdit routine that blinks the cursor. Getscrollbarvalues +returns the current X and Y scrollbar values, scaled to 0..32767. For X we return None, +which means "no scrollbar, please", for Y we use the scaler provided by ScrolledWindow.

    + +Scrollbar_callback is called when the user uses the scrollbar. It is passed a string 'x' +or 'y', one of 'set', '-', '--', '+', '++' and (for set) an absolute +value. Note that the sign of the value passed to TEPinScroll is counter-intuitive.

    + +do_activate (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 do_close can +return without closing the window (if the document is changed and the users cancels out of the operation). +Also note the "magic" in menu_save_as +that set the correct window title.

    + +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. Have_selection is called by the menubar update code to determine whether cut and +copy should be enabled.

    + +Understanding the main program is left as an exercise to the reader.

    + +


    +That's all for this example, you could now continue with the next example, where we use WASTE, a more-or-less +TextEdit compatible library with more functionality, to rebuild our editor. Or you can +return to the table of contents to pick another topic.

    diff --git a/Mac/Demo/using.html b/Mac/Demo/using.html index 5f20097..849c6d1 100644 --- a/Mac/Demo/using.html +++ b/Mac/Demo/using.html @@ -14,6 +14,14 @@ HREF="http://www.python.org/doc/tut/tut.html">Python Tutorial by Guido van Rossum. This guide more-or-less replaces chapter two of the tutorial, and provides some additional material.

    +There is currently no good tutorial for the mac-specific features of +Python, but to whet your appetite: it has interfaces to many MacOS +toolboxes (quickdraw, sound, quicktime, open scripting, etc) and +various portable toolboxes are available too (Tk, stdwin, complex +numbers, image manipulation, etc). Some +annotated sample programs are available to give you an idea of +Python's power.

    + The document refers to Python 1.3.3 or higher, some of the features (like setting applet options) will not work in earlier versions of Python.

    @@ -24,7 +32,7 @@ The name of the interpreter may differ on different installations: it may be called Python, PythonPPC (for powerpc macs) or Python68K (indeed, for 68K macs). It will always be recognizable by the "16 ton" icon, though. You start the -interpreter in interactive mode by double-clicking it.

    +interpreter in interactive mode by double-clicking its icon:

    @@ -88,7 +96,7 @@ edit-run cycle you can use the import statement and is Guido's original comment for how to do this, from the 1.1 release notes:

    - +

    Make sure the program is a module file (filename must be a Python identifier followed by '.py'). You can then import it @@ -121,7 +129,7 @@ does!). The trick is to first import the module again, then reload it. For instance, import foo; reload(foo). Because the module object already exists internally, the import statement does not attempt to execute the module again -- it just places it in your -workspace. +workspace.

    Clickable python scripts

    @@ -138,6 +146,14 @@ The Scripts folder contains a script set the correct creator and type for all files ending in .py.

    +

    +Older releases of Python used the creator code +'PYTH' in stead of 'Pyth'. If you still have +older Python sources on your system and named them with +'.py' extension the fixfiletypes script will +correct them. +
    +

    Interaction with the user

    Normally, the interpreter will check for user input (mouse clicks, @@ -355,7 +371,7 @@ set) the end-of-line convention used in a file.


    Jack Jansen, -jack@cwi.nl, 15-Apr-1996. +jack@cwi.nl, 19-Apr-1996. diff --git a/Mac/Demo/waste.html b/Mac/Demo/waste.html new file mode 100644 index 0000000..856d792 --- /dev/null +++ b/Mac/Demo/waste.html @@ -0,0 +1,69 @@ +Using WASTE + +

    Using WASTE

    +
    + +WASTE is an almost-compatible TextEdit replacement which overcomes +some of the limitations of it (like the 32K limit) and provides some extensions +(drag and drop, images, undo support). Moreover, it has a much cleaner interface +and is therefore easier integrated in Python.

    + +WASTE is written by Marco Piovanelli, <piovanel@kagi.com>, +and copyrighted by him. You can always obtain the latest version (for use in C +or Pascal programs) and the documentation from +<ftp://ftp.dsi.unimi.it/DSI/piovanel/WASTE>. + +We explain the useage of waste here by showing how to modify the TextEdit based +ped.py of the +previous example into the waste-based wed.py, +so you should have both sources handy.

    + +Functionally, wed.py provides three new things: resizable windows, a horizontal +scroll bar and undo.

    + +Let us look at the code, first at the application class Wed. The only real change is that +we now handle undo. Aside from enabling it in the creation routine and the addition of +a callback routine there is a bit of new code in updatemenubar: Waste not only handles +the full details of implementing undo, it will also tell us what the next undo operation will undo +(or redo). We use this to our advantage by changing the undo menu label to tell the user.

    + +The WasteWindow has seen a bit more change. Initialization of the waste data structure is +a bit different, in that we can specify some options at creation time. Also, waste has no SetText +method but a UseText which expects a handle as parameter. We have to be very careful +that we keep this handle around, because Python will happily free the handle if we have no more references +to it (and I doubt that Waste would like this:-). A final difference in open +is that we use a large number for the destination rectangle width, because we will use a horizontal scroll +bar.

    + +The idle method is a bit more involved, since we also call WEAdjustCursor to +provide the correct cursor based on mouse-position. Users like this.

    + +Getscrollbarvalues is simpler than its' TextEdit counterpart because Waste correctly +updates the destination rectangle when the document changes. Also note that waste uses accessor functions +to get at internal values, as opposed to direct struct access for TextEdit.

    + +Scrollbar_callback on the other hand is more elaborate (but also provides more functionality). +It also handles horizontal scrolls (scrolling one-tenth and half a screenful with the buttons). This +function is also "multi-font-ready" in that scrolling one line will do the expected thing in case of multiple +fonts. We will implement a multi-font editor later. A minor annoyance of Waste is that is does not provide +a pinned scroll, so at the end of our callback routine we have to check that we have not scrolled past the +beginning or end of the document, and adjust when needed.

    + +do_update is also changed, because Waste is completely region-based (as opposed to rect-based). +Hence, we erase regions here and we can also return immedeately if there is nothing to update.

    + +Do_postresize is new: because Waste uses accessor functions we can now modify the viewRect from +Python, which is impossible in the Python TextEdit interface, and hence we can implement resize. The +do_key and do_contentclick methods have also seen minor changes, because the +corresponding waste routines need a bit more information than their TextEdit counterparts. The Cut/copy/paste +code is simplified, because Waste uses the normal desktop scrap.

    + +Implementing undo is a wonder of simplicity: Waste handles all the details for us. Also, the new +can_paste method (which controls greying out of the paste menu entry) is an improvement +over what ped did: in ped it was possible that paste was enabled but that the data on the +scrap was incompatible with TextEdit. No more such problems here.

    + +


    +That is all for now. At some point in the future I will extend this editor to incorporate multiple fonts and +pointsizes, pictures and possibly drag-and-drop editing but I will first have to write the code for it. +For now you will have to go back to the index to pick another example. -- cgit v0.12