Guido van Rossum | 9cf8f33 | 1992-03-30 10:54:51 +0000 | [diff] [blame^] | 1 | #! /usr/local/python |
| 2 | |
| 3 | # A minimal single-window text editor using STDWIN's text objects. |
| 4 | # |
| 5 | # Usage: microedit file |
| 6 | # |
| 7 | # This is not intended as a real application but as an introduction |
| 8 | # to STDWIN programming in Python, especially text objects. |
| 9 | # Once you understand microedit.py, study miniedit.py to learn |
| 10 | # about multiple windows and menus, cut and paste, etc. |
| 11 | |
| 12 | |
| 13 | import sys |
| 14 | import stdwin |
| 15 | from stdwinevents import * |
| 16 | |
| 17 | |
| 18 | # Main program |
| 19 | # |
| 20 | def main(): |
| 21 | # |
| 22 | # Get the filename argument and read its contents as one very |
| 23 | # large string. |
| 24 | # An exception will terminate the program if there is no argument |
| 25 | # or if the file could not be read... |
| 26 | # |
| 27 | filename = sys.argv[1] |
| 28 | fp = open(filename, 'r') |
| 29 | contents = fp.read() |
| 30 | del fp # Close the file |
| 31 | # |
| 32 | # Create the window, using the filename as window title |
| 33 | # |
| 34 | window = stdwin.open(filename) |
| 35 | # |
| 36 | # Add a simple File menu to the window with two items |
| 37 | # |
| 38 | filemenu = window.menucreate('File') |
| 39 | filemenu.additem('Save', 'S') # Item 0 (shortcut Meta-S) |
| 40 | filemenu.additem('Save As...') # Item 1 |
| 41 | # |
| 42 | # Create a text object occupying the entire window |
| 43 | # and fill it with the file's contents |
| 44 | # |
| 45 | corner = window.getwinsize() # (width, height) |
| 46 | area = (0, 0), corner # Rectangle as large as the window |
| 47 | text = window.textcreate(area) |
| 48 | text.settext(contents) |
| 49 | del contents # Get rid of contents object |
| 50 | fix_textsize(window, text) # Set document size accordingly |
| 51 | # |
| 52 | # Main event loop -- stop if a close request comes in. |
| 53 | # |
| 54 | # STDWIN applications should regularly call stdwin.getevent() |
| 55 | # otherwise the windows won't function as expected. |
| 56 | # |
| 57 | while 1: |
| 58 | # |
| 59 | # Get the next event |
| 60 | # |
| 61 | type, w, detail = e = stdwin.getevent() |
| 62 | # |
| 63 | # Event decoding switch |
| 64 | # |
| 65 | if type == WE_CLOSE: |
| 66 | break # Stop (no check for saved file!) |
| 67 | elif type == WE_SIZE: |
| 68 | # |
| 69 | # The window was resized -- |
| 70 | # let the text object recompute the line breaks |
| 71 | # and change the document size accordingly, |
| 72 | # so scroll bars will work |
| 73 | # |
| 74 | fix_textsize(window, text) |
| 75 | elif type == WE_MENU: |
| 76 | # |
| 77 | # Execute a file menu request (our only menu) |
| 78 | # |
| 79 | menu, item = detail |
| 80 | if item == 0: |
| 81 | # |
| 82 | # "Save": save to the current filename |
| 83 | # |
| 84 | dummy = save_file(window, text, filename) |
| 85 | elif item == 1: |
| 86 | # |
| 87 | # "Save As": ask a new filename, save to it, |
| 88 | # and make it the current filename |
| 89 | # |
| 90 | # NB: askfile raises KeyboardInterrupt |
| 91 | # if the user cancels the dialog, hence |
| 92 | # the try statement |
| 93 | # |
| 94 | try: |
| 95 | newfile = stdwin.askfile( \ |
| 96 | 'Save as:', filename, 1) |
| 97 | except KeyboardInterrupt: |
| 98 | newfile = '' |
| 99 | if newfile: |
| 100 | if save_file(window, text, newfile): |
| 101 | filename = newfile |
| 102 | window.settitle(filename) |
| 103 | elif text.event(e): |
| 104 | # |
| 105 | # The text object has handled the event. |
| 106 | # Fix the document size if necessary. |
| 107 | # Note: this sometimes fixes the size |
| 108 | # unnecessarily, e.g., for arrow keys. |
| 109 | # |
| 110 | if type in (WE_CHAR, WE_COMMAND): |
| 111 | fix_docsize(window, text) |
| 112 | |
| 113 | |
| 114 | # Save the window's contents to the filename. |
| 115 | # If the open() fails, put up a warning message and return 0; |
| 116 | # if the save succeeds, return 1. |
| 117 | # |
| 118 | def save_file(window, text, filename): |
| 119 | # |
| 120 | # Open the file for writing, handling exceptions |
| 121 | # |
| 122 | try: |
| 123 | fp = open(filename, 'w') |
| 124 | except RuntimeError: |
| 125 | stdwin.message('Cannot create ' + filename) |
| 126 | return 0 |
| 127 | # |
| 128 | # Get the contents of the text object as one very long string |
| 129 | # |
| 130 | contents = text.gettext() |
| 131 | # |
| 132 | # Write the contents to the file |
| 133 | # |
| 134 | fp.write(contents) |
| 135 | # |
| 136 | # The file is automatically closed when this routine returns |
| 137 | # |
| 138 | return 1 |
| 139 | |
| 140 | |
| 141 | # Change the size of the text object to fit in the window, |
| 142 | # and then fix the window's document size to fit around the text object. |
| 143 | # |
| 144 | def fix_textsize(window, text): |
| 145 | # |
| 146 | # Compute a rectangle as large as the window |
| 147 | # |
| 148 | corner = window.getwinsize() # (width, height) |
| 149 | area = (0, 0), (corner) |
| 150 | # |
| 151 | # Move the text object to this rectangle. |
| 152 | # Note: text.move() ignores the bottom coordinate! |
| 153 | # |
| 154 | text.move(area) |
| 155 | # |
| 156 | # Now fix the document size accordingly |
| 157 | # |
| 158 | fix_docsize(window, text) |
| 159 | |
| 160 | |
| 161 | # Fix the document size, after the text has changed |
| 162 | # |
| 163 | def fix_docsize(window, text): |
| 164 | # |
| 165 | # Get the actual rectangle occupied by the text object. |
| 166 | # This has the same left, top and right, but a different bottom. |
| 167 | # |
| 168 | area = text.getrect() |
| 169 | # |
| 170 | # Compute the true height of the text object |
| 171 | # |
| 172 | origin, corner = area |
| 173 | width, height = corner |
| 174 | # |
| 175 | # Set the document height to the text object's height. |
| 176 | # The width is zero since we don't want a horizontal scroll bar. |
| 177 | # |
| 178 | window.setdocsize(0, height) |
| 179 | |
| 180 | |
| 181 | # Once all functions are defined, call main() |
| 182 | # |
| 183 | main() |