| <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> |
| |