blob: ab653a914132525a20fafb28510321918c60c815 [file] [log] [blame]
Kurt B. Kaiser09cb74b2003-06-12 04:20:56 +00001"""Simple text browser for IDLE
2
Steven M. Gava44d3d1a2001-07-31 06:59:02 +00003"""
csabella0aa0a062017-05-28 06:50:55 -04004from tkinter import Toplevel, Frame, Button, Text
5from tkinter import DISABLED, SUNKEN, VERTICAL, WORD
6from tkinter import RIGHT, LEFT, TOP, BOTTOM, BOTH, X, Y
Terry Jan Reedy01e35752016-06-10 18:19:21 -04007from tkinter.ttk import Scrollbar
Terry Jan Reedy82c46152016-06-22 04:54:18 -04008from tkinter.messagebox import showerror
Steven M. Gava44d3d1a2001-07-31 06:59:02 +00009
Terry Jan Reedybfbaa6b2016-08-31 00:50:55 -040010
Steven M. Gava44d3d1a2001-07-31 06:59:02 +000011class TextViewer(Toplevel):
Terry Jan Reedya3623c82016-08-31 19:45:39 -040012 "A simple text viewer dialog for IDLE."
Kurt B. Kaiser09cb74b2003-06-12 04:20:56 +000013
Louie Luba365da2017-05-18 05:51:31 +080014 def __init__(self, parent, title, text, modal=True,
15 _htest=False, _utest=False):
16 """Show the given text in a scrollable window with a 'close' button.
Guido van Rossum8ce8a782007-11-01 19:42:39 +000017
Louie Luba365da2017-05-18 05:51:31 +080018 If modal is left True, users cannot interact with other windows
19 until the textview window is closed.
Terry Jan Reedy537e2c82014-06-05 03:38:34 -040020
csabella0aa0a062017-05-28 06:50:55 -040021 parent - parent of this dialog
22 title - string which is title of popup dialog
23 text - text to display in dialog
Terry Jan Reedy537e2c82014-06-05 03:38:34 -040024 _htest - bool; change box location when running htest.
Louie Luba365da2017-05-18 05:51:31 +080025 _utest - bool; don't wait_window when running unittest.
Steven M. Gavad721c482001-07-31 10:46:53 +000026 """
27 Toplevel.__init__(self, parent)
28 self.configure(borderwidth=5)
Terry Jan Reedya3623c82016-08-31 19:45:39 -040029 # Place dialog below parent if running htest.
Terry Jan Reedyd0cadba2015-10-11 22:07:31 -040030 self.geometry("=%dx%d+%d+%d" % (750, 500,
Terry Jan Reedy1b392ff2014-05-24 18:48:18 -040031 parent.winfo_rootx() + 10,
32 parent.winfo_rooty() + (10 if not _htest else 100)))
Terry Jan Reedya3623c82016-08-31 19:45:39 -040033 # TODO: get fg/bg from theme.
Kurt B. Kaiser09cb74b2003-06-12 04:20:56 +000034 self.bg = '#ffffff'
35 self.fg = '#000000'
Steven M. Gava44d3d1a2001-07-31 06:59:02 +000036
csabella0aa0a062017-05-28 06:50:55 -040037 self.create_widgets()
Steven M. Gavad721c482001-07-31 10:46:53 +000038 self.title(title)
csabella0aa0a062017-05-28 06:50:55 -040039 self.protocol("WM_DELETE_WINDOW", self.ok)
Steven M. Gavad721c482001-07-31 10:46:53 +000040 self.parent = parent
csabella0aa0a062017-05-28 06:50:55 -040041 self.text.focus_set()
Terry Jan Reedya3623c82016-08-31 19:45:39 -040042 # Bind keys for closing this dialog.
csabella0aa0a062017-05-28 06:50:55 -040043 self.bind('<Return>', self.ok)
44 self.bind('<Escape>', self.ok)
45 self.text.insert(0.0, text)
46 self.text.config(state=DISABLED)
Terry Jan Reedye91e7632012-02-05 15:14:20 -050047
48 if modal:
49 self.transient(parent)
50 self.grab_set()
Louie Luba365da2017-05-18 05:51:31 +080051 if not _utest:
52 self.wait_window()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000053
csabella0aa0a062017-05-28 06:50:55 -040054 def create_widgets(self):
Louie Luba365da2017-05-18 05:51:31 +080055 "Create Frame with Text (with vertical Scrollbar) and Button."
csabella0aa0a062017-05-28 06:50:55 -040056 frame = Frame(self, relief=SUNKEN, height=700)
57 frame_buttons = Frame(self)
58 self.button_ok = Button(frame_buttons, text='Close',
59 command=self.ok, takefocus=False)
60 self.scrollbar = Scrollbar(frame, orient=VERTICAL, takefocus=False)
61 self.text = Text(frame, wrap=WORD, highlightthickness=0,
Kurt B. Kaiser09cb74b2003-06-12 04:20:56 +000062 fg=self.fg, bg=self.bg)
csabella0aa0a062017-05-28 06:50:55 -040063 self.scrollbar.config(command=self.text.yview)
64 self.text.config(yscrollcommand=self.scrollbar.set)
65
66 self.button_ok.pack()
67 self.scrollbar.pack(side=RIGHT, fill=Y)
68 self.text.pack(side=LEFT, expand=True, fill=BOTH)
69 frame_buttons.pack(side=BOTTOM, fill=X)
70 frame.pack(side=TOP, expand=True, fill=BOTH)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000071
csabella0aa0a062017-05-28 06:50:55 -040072 def ok(self, event=None):
73 """Dismiss text viewer dialog."""
Steven M. Gavad721c482001-07-31 10:46:53 +000074 self.destroy()
Steven M. Gava44d3d1a2001-07-31 06:59:02 +000075
Guido van Rossum8ce8a782007-11-01 19:42:39 +000076
Louie Luba365da2017-05-18 05:51:31 +080077def view_text(parent, title, text, modal=True, _utest=False):
csabella0aa0a062017-05-28 06:50:55 -040078 """Create TextViewer for given text.
79
80 parent - parent of this dialog
81 title - string which is the title of popup dialog
82 text - text to display in this dialog
83 modal - controls if users can interact with other windows while this
84 dialog is displayed
85 _utest - bool; controls wait_window on unittest
86 """
Louie Luba365da2017-05-18 05:51:31 +080087 return TextViewer(parent, title, text, modal, _utest=_utest)
Guido van Rossum8ce8a782007-11-01 19:42:39 +000088
csabella0aa0a062017-05-28 06:50:55 -040089
Louie Luba365da2017-05-18 05:51:31 +080090def view_file(parent, title, filename, encoding=None, modal=True, _utest=False):
csabella0aa0a062017-05-28 06:50:55 -040091 """Create TextViewer for text in filename.
92
93 Return error message if file cannot be read. Otherwise calls view_text
94 with contents of the file.
95 """
Guido van Rossum8ce8a782007-11-01 19:42:39 +000096 try:
Éric Araujoccf03a12011-08-01 17:29:36 +020097 with open(filename, 'r', encoding=encoding) as file:
98 contents = file.read()
Terry Jan Reedy82c46152016-06-22 04:54:18 -040099 except OSError:
100 showerror(title='File Load Error',
101 message='Unable to load file %r .' % filename,
102 parent=parent)
103 except UnicodeDecodeError as err:
104 showerror(title='Unicode Decode Error',
105 message=str(err),
106 parent=parent)
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000107 else:
Louie Luba365da2017-05-18 05:51:31 +0800108 return view_text(parent, title, contents, modal, _utest=_utest)
terryjreedy295304d2017-05-17 22:59:46 -0400109 return None
Louie Luba365da2017-05-18 05:51:31 +0800110
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000111
Steven M. Gava44d3d1a2001-07-31 06:59:02 +0000112if __name__ == '__main__':
Terry Jan Reedy537e2c82014-06-05 03:38:34 -0400113 import unittest
114 unittest.main('idlelib.idle_test.test_textview', verbosity=2, exit=False)
Terry Jan Reedy1b392ff2014-05-24 18:48:18 -0400115 from idlelib.idle_test.htest import run
116 run(TextViewer)