1<HTML><HEAD><TITLE>Using FrameWork and TextEdit</TITLE></HEAD> 2<BODY> 3<H1>Using FrameWork and TextEdit</H1> 4<HR> 5 6In this document we use the <CODE>FrameWork</CODE> and <CODE>TextEdit</CODE> 7modules to create a simple text editor. The functionality 8of the editor is very basic: you can open multiple files, type text and use 9cut/copy/paste. The main intention is to explain the use of FrameWork, really. <p> 10 11<H2>FrameWork</H2> 12 13The FrameWork module provides you with a skeleton application. It declares a 14number of classes suitable for subclassing in your application, thereby 15releaving you of the burden of doing all event handling, etc. yourself. For a 16real understanding you will have to browse the source. Here is a short overview 17of the classes and what functionality they provide. 18 19<dl> 20<dt> <CODE>Application</CODE> 21<dd> 22This is the toplevel class you will override. It maintains the menu bar and contains 23the main event handling code. Normal use is to override the <code>__init__</code> routine 24to do your own initializations and override <code>makeusermenus</code> to create your menus 25(your menu callback routines may be here too, but this is by no means necessary). 26The event handling code can be overridden at various levels, from very low-level (the 27<code>dispatch</code> method) to intermediate level (<code>do_keyDown</code>, for instance) 28to high-level (<code>do_key</code>). The application class knows about the <code>Window</code> 29objects you create, and will forward events to the appropriate window (So, normally you 30would have a <code>do_key</code> method in your window object, not your application object). 31 32<dt> <CODE>MenuBar</CODE>, <CODE>Menu</CODE> and <CODE>MenuItem</CODE> 33<dd> 34These classes (and a few friends like <CODE>SubMenu</CODE>) handle your menus. You would not 35normally override them but use them as-is. The idiom for creating menus is a bit strange, 36see the test code at the bottom of FrameWork for sample use. The apple menu is handled for you 37by <CODE>MenuBar</CODE> and <CODE>Application</CODE>. 38 39<dt> <CODE>Window</CODE> 40<dd> 41The basic window. Again, a class that you normally subclass in your application, possibly 42multiple times if you have different types of windows. The init call instantiates the data 43structure but actually opening the window is delayed until you call <code>open</code>. Your 44open method should call <code>do_postopen</code> to let the base class handle linking in to 45the application object. Similarly with <code>close</code> and <code>do_postclose</code>. The 46rest of the code is mainly event-oriented: you override <code>do_postresize</code>, 47<code>do_contentclick</code>, <code>do_update</code>, <code>do_activate</code> 48and <code>do_key</code> to "do your thing". When these methods are called the relevant environment 49has been setup (like <code>BeginDrawing</code> has been called for updates, etc). 50 51<dt> <CODE>windowbounds</CODE> 52<dd> 53Not a class but a function: you pass it a width and height and it will return you a rectangle 54you can use to create your window. It will take care of staggering windows and it will try 55to fit the window on the screen (but the resulting rect will <em>always</em> have the size you 56specify). 57 58<dt> <CODE>ControlsWindow</CODE> 59<dd> 60A subclass of Window which automatically handles drawing and clicking for controls. You override 61the same methods as for Window (if you need to: control-related things are done automatically) and 62<code>do_controlhit</code>. 63 64<dt> <CODE>ScrolledWindow</CODE> 65<dd> 66A subclass of ControlsWindow, a window with optional scrollbars. If you override <code>do_activate</code> 67or <code>do_postresize</code> you must call the ScrolledWindow methods at the end of your override. 68You call <code>scrollbars</code> to enable/disable scrollbars and <code>updatescrollbars</code> to 69update them. You provide <code>getscrollbarvalues</code> to return the current x/y values (a helper 70method <code>scalebarvalues</code> is available) and <code>scrollbarcallback</code> to update your 71display after the user has used the scrollbars. 72 73<dt> <CODE>DialogWindow</CODE> 74<dd> 75A modeless dialog window initialized from a DLOG resource. See the 76<A HREF="example2.html">second Interslip example</A> for its useage. 77</dl> 78 79<H2>A sample text editor</H2> 80 81Let us have a look at <A HREF="textedit/ped.py">ped.py</A> (in the Demo:textedit folder), the Pathetic 82EDitor. It has multiple windows, cut/copy/paste and keyboard input, but that is about all. It looks 83as if you can resize the window but it does not work. Still, it serves as an example. 84 85Ped creates two classes, <code>TEWindow</code> and <code>Ped</code>. Let us start with the latter one, 86which is a subclass of <code>FrameWork.Application</code> and our main application. The init function 87has little to do aside from the standard init: it remembers a window sequence number (for untitled windows), 88and sets things up for menu disable to work. Remember, the <code>makeusermenus</code> is called 89automatically. <p> 90 91<code>Makeusermenus</code> creates the <code>File</code> and <code>Edit</code> menus. It also initializes 92a couple of lists that are used later to correctly enable and disable menu items (and complete menus) depending 93on whether a window is open, text is selected, etc. The callback functions for the menu items are 94all methods of this class. <p> 95 96<code>Updatemenubar</code> handles greying out (and re-enabling) of menu items depending on whether there 97is a current window and its state. <p> 98 99The rest of the methods are all callbacks and simple to understand. They check whether there is an active 100window (and complain loudly if there is none: the corresponding menu entry should have been disabled 101in that case!) and call the appropriate window method. Only the <code>_open</code> method (the common code 102for <code>Open</code> and <code>New</code>) deserves some mention. It instantiates a <code>TEWindow</code> 103object and opens it with the title, filename and contents of the file to edit. Note that FrameWork takes 104care of remembering the window object. A minor note on opening the file in binary mode: this is because 105TextEdit expects MacOS style carriage-return terminated lines, not python/unix/C style newline-terminated 106lines. <p> 107 108Oh yes: the <code>quit</code> callback does a little magic too. It closes all windows, and only if this 109succeeds it actually quits. This gives the user a chance to cancel the operation if some files are unsaved. 110<p> 111 112Lastly, there is the <code>idle</code> method, called by the Application base class when no event 113is available. It is forwarded to the active window, so it can blink the text caret. <p> 114 115The <code>TEWindow</code> object handles a single window. Due to this structuring it is absolutely no 116problem to have multiple windows open at the same time (although a real application should exercise care when 117two windows refer to the same document). TEWindow uses the standard init code inherited from 118<code>ScrolledWindow</code>, and sets itself up at the time of the <code>open</code> call. It obtains screen 119coordinates, opens the window, creates rectangles for TextEdit to work in (the magical number <code>15</code> 120here is the size of a normal scroll bar: unfortunately there is no symbolic constant for it), 121creates the TextEdit object and initializes it with our data. Finally, the scroll bars are created (the 122initial values will be obtained automatically through <code>getscrollbarvalues</code>) and we activate 123ourselves (this is unfortunately not done automatically by the MacOS event handling code). <p> 124 125<code>Do_idle</code> simply calls the TextEdit routine that blinks the cursor. <code>Getscrollbarvalues</code> 126returns the current X and Y scrollbar values, scaled to <code>0..32767</code>. For X we return <code>None</code>, 127which means "no scrollbar, please", for Y we use the scaler provided by <code>ScrolledWindow</code>. <p> 128 129<code>Scrollbar_callback</code> is called when the user uses the scrollbar. It is passed a string <code>'x'</code> 130or <code>'y'</code>, one of <code>'set', '-', '--', '+', '++'</code> and (for <code>set</code>) an absolute 131value. Note that the sign of the value passed to <code>TEPinScroll</code> is counter-intuitive. <p> 132 133<code>do_activate</code> (de)activates the scrollbars and calls the relevant TextEdit routine. Moreover, it 134tells the application object if we are now the active window, and updates the menubar. The next few methods 135are update and menu callbacks, and pretty straightforward. Note that <code>do_close</code> can 136return without closing the window (if the document is changed and the users cancels out of the operation). 137Also note the "magic" in <code>menu_save_as</code> 138that set the correct window title. <p> 139 140Things get moderately interesting again at the cut/copy/paste handling, since the TextEdit scrap is 141separate from the desktop scrap. For that reason there are various calls to routines that move the scrap 142back and forth. <code>Have_selection</code> is called by the menubar update code to determine whether cut and 143copy should be enabled. <p> 144 145Understanding the main program is left as an exercise to the reader. <p> 146 147<hr> 148That'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 149TextEdit compatible library with more functionality, to rebuild our editor. Or you can 150return to the <A HREF="index.html">table of contents</A> to pick another topic. <p> 151