All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
textwindow.py
Go to the documentation of this file.
1 #! /usr/bin/env python
2 ######################################################################
3 #
4 # Name: textwindow.py
5 #
6 # Purpose: Python class for displaying arbitrary text in a scrolling
7 # window or frame.
8 #
9 # Created: 28-Jan-2015 Herbert Greenlee
10 #
11 ######################################################################
12 
13 from __future__ import absolute_import
14 from __future__ import print_function
15 import sys
16 
17 # Import GUI stuff
18 
19 try:
20  import tkinter as tk
21 except ImportError:
22  import Tkinter as tk
23 
24 # Project widget class
25 
26 class TextWindow(tk.Frame):
27 
28  # Constructor.
29 
30  def __init__(self, parent=None, rows=24, columns=80):
31 
32  # Parent window.
33 
34  if parent == None:
35  self.parent = tk.Toplevel()
36  else:
37  self.parent = parent
38 
39  # Register our outermost frame in the parent window.
40 
41  tk.Frame.__init__(self, self.parent)
42  if parent == None:
43  self.pack(expand=1, fill=tk.BOTH)
44  self.rowconfigure(0, weight=1)
45  self.columnconfigure(0, weight=1)
46 
47  # Add an empty text widget.
48 
49  self.text = tk.Text(self, height=rows, width=columns, wrap=tk.NONE, takefocus=0)
50  self.text.grid(row=0, column=0, sticky=tk.N+tk.E+tk.W+tk.S)
51 
52  # Make scroll bars, but don't grid them yet.
53 
54  self.vbar = tk.Scrollbar(self, orient=tk.VERTICAL, command=self.text.yview)
55  self.text['yscrollcommand'] = self.vbar.set
56  self.vbar_visible = 0
57 
58  self.hbar = tk.Scrollbar(self, orient=tk.HORIZONTAL, command=self.text.xview)
59  self.text['xscrollcommand'] = self.hbar.set
60  self.hbar_visible = 0
61 
62  self.check_scroll()
63 
64  # Set event bindings (check scrollbar visibility when window size
65  # changes).
66 
67  self.text.bind('<Configure>', self.check_scroll)
68 
69  # See if we need to enable or disable either scrollbar.
70 
71  def check_scroll(self, event=None):
72 
73  # Check vertical scroll bar.
74 
75  yv = self.text.yview()
76  if not self.vbar_visible and (yv[0] != 0.0 or yv[1] != 1.0):
77  self.vbar_visible = 1
78  self.vbar.grid(row=0, column=1, sticky=tk.N+tk.S)
79  elif self.vbar_visible and yv[0] == 0.0 and yv[1] == 1.0:
80  self.vbar_visible = 0
81  self.vbar.grid_forget()
82 
83  # Check horizontal scroll bar.
84 
85  xv = self.text.xview()
86  if not self.hbar_visible and (xv[0] != 0.0 or xv[1] != 1.0):
87  self.hbar_visible = 1
88  self.hbar.grid(row=1, column=0, sticky=tk.E+tk.W)
89  elif self.hbar_visible and xv[0] == 0.0 and xv[1] == 1.0:
90  self.hbar_visible = 0
91  self.hbar.grid_forget()
92 
93  # Insert text.
94 
95  def insert(self, pos, text):
96  self.text.insert(pos, text)
97  self.check_scroll()
98 
99  # Insert text at and of buffer.
100 
101  def append(self, text):
102  self.insert(tk.END, text)
103 
104  # File-like methods.
105 
106  # If they want our file descriptor, tell them 2 for now (standard error).
107  # Python docs say not to implement this method if it doesn't make sense
108  # for your file-like object. But subprocess(stderr=) doesn't work without
109  # this method.
110 
111  def fileno(self):
112  return 2
113 
114  # Close/flush file (don't do anything).
115 
116  def close(self):
117  return
118  def flush(self):
119  return
120 
121  # Is this a tty?
122 
123  def isatty(self):
124  return False
125 
126  # Read methods (raise IOError).
127 
128  def __next__(self):
129  raise IOError('File is not open for reading.')
130  def read(self, size=0):
131  raise IOError('File is not open for reading.')
132  def readline(self, size=0):
133  raise IOError('File is not open for reading.')
134  def readlines(self, size=0):
135  raise IOError('File is not open for reading.')
136  def readline(self, size=0):
137  raise IOError('File is not open for reading.')
138  def seek(self, offset, pos=0):
139  raise IOError('File is not open for reading.')
140 
141  # Current position.
142 
143  def tell(self):
144  return len(self.text['text'])
145 
146  # Truncate.
147 
148  def truncate(self, size=0):
149  self.text['text'] = self.text['text'][0:size]
150  self.check_scroll()
151  self.text.yview_moveto(1.0) # Scroll to bottom
152 
153  # Write methods.
154 
155  def write(self, text):
156  self.append(text)
157  self.text.yview_moveto(1.0) # Scroll to bottom
158  def writelines(self, lines):
159  for line in lines:
160  self.append(line)
161  self.text.yview_moveto(1.0) # Scroll to bottom