microedit.py 4.47 KB
Newer Older
1
#! /usr/bin/env python
Guido van Rossum's avatar
Guido van Rossum committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183

# A minimal single-window text editor using STDWIN's text objects.
#
# Usage: microedit file
#
# This is not intended as a real application but as an introduction
# to STDWIN programming in Python, especially text objects.
# Once you understand microedit.py, study miniedit.py to learn
# about multiple windows and menus, cut and paste, etc.


import sys
import stdwin
from stdwinevents import *


# Main program
#
def main():
	#
	# Get the filename argument and read its contents as one very
	# large string.
	# An exception will terminate the program if there is no argument
	# or if the file could not be read...
	#
	filename = sys.argv[1]
	fp = open(filename, 'r')
	contents = fp.read()
	del fp				# Close the file
	#
	# Create the window, using the filename as window title
	#
	window = stdwin.open(filename)
	#
	# Add a simple File menu to the window with two items
	#
	filemenu = window.menucreate('File')
	filemenu.additem('Save', 'S')	# Item 0 (shortcut Meta-S)
	filemenu.additem('Save As...')	# Item 1
	#
	# Create a text object occupying the entire window
	# and fill it with the file's contents
	#
	corner = window.getwinsize()	# (width, height)
	area = (0, 0), corner		# Rectangle as large as the window
	text = window.textcreate(area)
	text.settext(contents)
	del contents			# Get rid of contents object
	fix_textsize(window, text)	# Set document size accordingly
	#
	# Main event loop -- stop if a close request comes in.
	#
	# STDWIN applications should regularly call stdwin.getevent()
	# otherwise the windows won't function as expected.
	#
	while 1:
		#
		# Get the next event
		#
		type, w, detail = e = stdwin.getevent()
		#
		# Event decoding switch
		#
		if type == WE_CLOSE:
			break		# Stop (no check for saved file!)
		elif type == WE_SIZE:
			#
			# The window was resized --
			# let the text object recompute the line breaks
			# and change the document size accordingly,
			# so scroll bars will work
			#
			fix_textsize(window, text)
		elif type == WE_MENU:
			#
			# Execute a file menu request (our only menu)
			#
			menu, item = detail
			if item == 0:
				#
				# "Save": save to the current filename
				#
				dummy = save_file(window, text, filename)
			elif item == 1:
				#
				# "Save As": ask a new filename, save to it,
				# and make it the current filename
				#
				# NB: askfile raises KeyboardInterrupt
				# if the user cancels the dialog, hence
				# the try statement
				#
				try:
					newfile = stdwin.askfile( \
						'Save as:', filename, 1)
				except KeyboardInterrupt:
					newfile = ''
				if newfile:
					if save_file(window, text, newfile):
						filename = newfile
						window.settitle(filename)
		elif text.event(e):
			#
			# The text object has handled the event.
			# Fix the document size if necessary.
			# Note: this sometimes fixes the size
			# unnecessarily, e.g., for arrow keys.
			#
			if type in (WE_CHAR, WE_COMMAND):
				fix_docsize(window, text)


# Save the window's contents to the filename.
# If the open() fails, put up a warning message and return 0;
# if the save succeeds, return 1.
#
def save_file(window, text, filename):
	#
	# Open the file for writing, handling exceptions
	#
	try:
		fp = open(filename, 'w')
	except RuntimeError:
		stdwin.message('Cannot create ' + filename)
		return 0
	#
	# Get the contents of the text object as one very long string
	#
	contents = text.gettext()
	#
	# Write the contents to the file
	#
	fp.write(contents)
	#
	# The file is automatically closed when this routine returns
	#
	return 1


# Change the size of the text object to fit in the window,
# and then fix the window's document size to fit around the text object.
#
def fix_textsize(window, text):
	#
	# Compute a rectangle as large as the window
	#
	corner = window.getwinsize()	# (width, height)
	area = (0, 0), (corner)
	#
	# Move the text object to this rectangle.
	# Note: text.move() ignores the bottom coordinate!
	#
	text.move(area)
	#
	# Now fix the document size accordingly
	#
	fix_docsize(window, text)


# Fix the document size, after the text has changed
#
def fix_docsize(window, text):
	#
	# Get the actual rectangle occupied by the text object.
	# This has the same left, top and right, but a different bottom.
	#
	area = text.getrect()
	#
	# Compute the true height of the text object
	#
	origin, corner = area
	width, height = corner
	#
	# Set the document height to the text object's height.
	# The width is zero since we don't want a horizontal scroll bar.
	#
	window.setdocsize(0, height)


# Once all functions are defined, call main()
#
main()