There are probably other, better ways of printing ASCII graphics in Python; but since I do not know what they are, this is the product from that lack of knowledge. This is not meant to be the complete, final version -- there were other versions before this. Definitions and descriptions were finally written, and the code here tries to hold closely to concept that were put forth. Following the code are the specification for how the code should work.
1 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
================================================================================ window.py ================================================================================ # This is the first version of the page class. class page_v1: def __init__(self, rows, columns, default = None): # (page_v1, int, int, str) if default is None: default = ' ' self.__page = list() for index in range(rows): self.__page.append(list(default * columns)) def mutate(self, row, column, string): # (page_v1, int, int, str) try: if row >= 0: for index in range(len(string)): if column + index >= 0: self.__page[row][column + index] = string[index] except: pass def access(self, row, column, length = 1): # (page_v1, int, int, int) string = str() try: for index in range(length): string += self.__page[row][column + index] except: pass return string def internal(self): # (page_v1) array = list() for row in self.__page: array.append(row[:]) return array def __str__(self): # (page_v1) string = str() for row in self.__page: for character in row: string += character string += '\n' return string[:-1] # This is the first version of a theoretical window. class window_v1: def __init__(self, height, width, border = None, background = None): # (window_v1, int, int, str, str) self.__height = height self.__width = width self.__border = border self.__background = background self.__draw = True self.__buffer = None self.__contents = list() def append(self, instance, position, visible = True, index = None): # (window_v1, page_v1 OR window_v1, [int, int], bool, int) self.__draw = True if index is None: self.__contents.append([instance, position, visible]) else: self.__contents.insert(index, [instance, position, visible]) def remove(self, instance): # (window_v1, page_v1 OR window_v1) for index in range(len(self.__contents)): if instance is self.__contents[index]: self.__draw = True del self.__contents[index] def __getitem__(self, index): # (window_v1, int) self.__draw = True return self.__contents[index] def __delitem__(self, index): # (window_v1, int) self.__draw = True del self.__contents[index] def size(self, height = None, width = None): # (window_v1, int, int) if height is not None: self.__draw = True self.__height = height if width is not None: self.__draw = True self.__width = width if height is None and width is None: return self.__height, self.__width def look(self, border = 0, background = 0): # (window_v1, str, str) if border is not 0: self.__draw = True self.__border = border if background is not 0: self.__draw = True self.__background = background if border is 0 and background is 0: return self.__border, self.__background def __update(self): # (window_v1) if self.__draw: self.__draw = False self.__buffer = page_v1(self.__height, self.__width, self.__background) for item in self.__contents: if item: internal = item.internal() for row in range(len(internal)): for column in range(len(internal)): self.__buffer.mutate(row + item, column + item, internal[row][column]) if self.__border is not None: self.__buffer.mutate(0, 0, self.__border * self.__width) self.__buffer.mutate(self.__height - 1, 0, self.__border * self.__width) for row in range(1, self.__height - 1): self.__buffer.mutate(row, 0, self.__border) self.__buffer.mutate(row, self.__width - 1, self.__border) def internal(self): # (window_v1) self.__update() return self.__buffer.internal() def __str__(self): # (window_v1) self.__update() return str(self.__buffer)
WINDOW THEORY V1
Windows should contain zero or more pages.
Windows should contain zero or more windows.
Pages should be buffers that cannot be resized once created.
Pages should be in the form of 2D list.
Pages should be editable.
Pages should be able to return a plain representation of their contents (a copy of the 2D list).
GENERAL THEORY V2
A page is a buffer.
A page is created with a size that cannot be changed.
Internally, a page is a 2D list of length 1 strings.
A the contents of a page can be edited with length 1 strings.
A page can be created with a default cell value; otherwise, the value is a space.
A copy of the internal buffer of a page can be returned.
A string representation of a page can be returned; there is to be no newline added to the last row of a page.
A window is created with a size, outline (which can be None etc. or a length 1 string), and background (a length 1 string [defaults to space]).
A window can contain 0 or more pages and 0 or more windows.
A window can have an outline (1 character); otherwise, it does not have an outline.
A window can have a background character; otherwise, the background is a space.
A window must have a size.
Internally, besides outline, background, and size, a windows consists of a list of information (page(s) and window(s) etc.).
The list consists of lists of the following information: position of the object, the object, and if the object is visible (displayed).
The ordering of the list indicates what object is on top of another object; list is the bottom-most object to be displayed.
A look of a window can be returned as a 2D list (so that it has the same form as a page).
A string representation of the window can be returned and does not have a newline tacked onto its end.
You seem to be struggling very hard to replace the curses module.
And you, Paul Jimenez, seem to be forgetting that there is no 'curses' module on the Win32 platform.
Indeed. Indeed I did - I avoid that platform whenever possible. For portability's sake perhaps this should be turned into 'win32curses' or somesuch and given an identical API - then it would 1) make existing curses-using programs easier to port and 2) let windows python programmers learn an API that will be useful to them on other platforms.
list/mmap. With lists and/or mmap objects, you could make this faster for older Python versions (removing the += operation on strings). Just an idea.
If I remember correctly, Python for cygwin has curses (if you want/need it), though I would understand not wanting to use it (I don't).