blob: dc1a7bfc9eff3885d677d3f689a754770c1a7d27 [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"""
Georg Brandl14fc4272008-05-17 18:39:55 +00004from tkinter import *
Terry Jan Reedy01e35752016-06-10 18:19:21 -04005from tkinter.ttk import Scrollbar
Terry Jan Reedy82c46152016-06-22 04:54:18 -04006from tkinter.messagebox import showerror
Steven M. Gava44d3d1a2001-07-31 06:59:02 +00007
Terry Jan Reedybfbaa6b2016-08-31 00:50:55 -04008
Steven M. Gava44d3d1a2001-07-31 06:59:02 +00009class TextViewer(Toplevel):
Terry Jan Reedya3623c82016-08-31 19:45:39 -040010 "A simple text viewer dialog for IDLE."
Kurt B. Kaiser09cb74b2003-06-12 04:20:56 +000011
Louie Luba365da2017-05-18 05:51:31 +080012 def __init__(self, parent, title, text, modal=True,
13 _htest=False, _utest=False):
14 """Show the given text in a scrollable window with a 'close' button.
Guido van Rossum8ce8a782007-11-01 19:42:39 +000015
Louie Luba365da2017-05-18 05:51:31 +080016 If modal is left True, users cannot interact with other windows
17 until the textview window is closed.
Terry Jan Reedy537e2c82014-06-05 03:38:34 -040018
19 _htest - bool; change box location when running htest.
Louie Luba365da2017-05-18 05:51:31 +080020 _utest - bool; don't wait_window when running unittest.
Steven M. Gavad721c482001-07-31 10:46:53 +000021 """
22 Toplevel.__init__(self, parent)
23 self.configure(borderwidth=5)
Terry Jan Reedya3623c82016-08-31 19:45:39 -040024 # Place dialog below parent if running htest.
Terry Jan Reedyd0cadba2015-10-11 22:07:31 -040025 self.geometry("=%dx%d+%d+%d" % (750, 500,
Terry Jan Reedy1b392ff2014-05-24 18:48:18 -040026 parent.winfo_rootx() + 10,
27 parent.winfo_rooty() + (10 if not _htest else 100)))
Terry Jan Reedya3623c82016-08-31 19:45:39 -040028 # TODO: get fg/bg from theme.
Kurt B. Kaiser09cb74b2003-06-12 04:20:56 +000029 self.bg = '#ffffff'
30 self.fg = '#000000'
Steven M. Gava44d3d1a2001-07-31 06:59:02 +000031
Steven M. Gavad721c482001-07-31 10:46:53 +000032 self.CreateWidgets()
33 self.title(title)
Steven M. Gavad721c482001-07-31 10:46:53 +000034 self.protocol("WM_DELETE_WINDOW", self.Ok)
35 self.parent = parent
36 self.textView.focus_set()
Terry Jan Reedya3623c82016-08-31 19:45:39 -040037 # Bind keys for closing this dialog.
38 self.bind('<Return>',self.Ok)
39 self.bind('<Escape>',self.Ok)
Guido van Rossum8ce8a782007-11-01 19:42:39 +000040 self.textView.insert(0.0, text)
Steven M. Gavad721c482001-07-31 10:46:53 +000041 self.textView.config(state=DISABLED)
Terry Jan Reedye91e7632012-02-05 15:14:20 -050042
43 if modal:
44 self.transient(parent)
45 self.grab_set()
Louie Luba365da2017-05-18 05:51:31 +080046 if not _utest:
47 self.wait_window()
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000048
Steven M. Gavad721c482001-07-31 10:46:53 +000049 def CreateWidgets(self):
Louie Luba365da2017-05-18 05:51:31 +080050 "Create Frame with Text (with vertical Scrollbar) and Button."
Kurt B. Kaiser09cb74b2003-06-12 04:20:56 +000051 frameText = Frame(self, relief=SUNKEN, height=700)
Steven M. Gavad721c482001-07-31 10:46:53 +000052 frameButtons = Frame(self)
Kurt B. Kaiser09cb74b2003-06-12 04:20:56 +000053 self.buttonOk = Button(frameButtons, text='Close',
54 command=self.Ok, takefocus=FALSE)
55 self.scrollbarView = Scrollbar(frameText, orient=VERTICAL,
Terry Jan Reedy01e35752016-06-10 18:19:21 -040056 takefocus=FALSE)
Kurt B. Kaiser09cb74b2003-06-12 04:20:56 +000057 self.textView = Text(frameText, wrap=WORD, highlightthickness=0,
58 fg=self.fg, bg=self.bg)
Steven M. Gavad721c482001-07-31 10:46:53 +000059 self.scrollbarView.config(command=self.textView.yview)
60 self.textView.config(yscrollcommand=self.scrollbarView.set)
Kurt B. Kaiser09cb74b2003-06-12 04:20:56 +000061 self.buttonOk.pack()
Steven M. Gavad721c482001-07-31 10:46:53 +000062 self.scrollbarView.pack(side=RIGHT,fill=Y)
63 self.textView.pack(side=LEFT,expand=TRUE,fill=BOTH)
64 frameButtons.pack(side=BOTTOM,fill=X)
65 frameText.pack(side=TOP,expand=TRUE,fill=BOTH)
Kurt B. Kaiser6655e4b2002-12-31 16:03:23 +000066
Steven M. Gavad721c482001-07-31 10:46:53 +000067 def Ok(self, event=None):
68 self.destroy()
Steven M. Gava44d3d1a2001-07-31 06:59:02 +000069
Guido van Rossum8ce8a782007-11-01 19:42:39 +000070
Louie Luba365da2017-05-18 05:51:31 +080071def view_text(parent, title, text, modal=True, _utest=False):
72 "Display text in a TextViewer."
73 return TextViewer(parent, title, text, modal, _utest=_utest)
Guido van Rossum8ce8a782007-11-01 19:42:39 +000074
Louie Luba365da2017-05-18 05:51:31 +080075def view_file(parent, title, filename, encoding=None, modal=True, _utest=False):
76 "Display file in a TextViever or show error message."
Guido van Rossum8ce8a782007-11-01 19:42:39 +000077 try:
Éric Araujoccf03a12011-08-01 17:29:36 +020078 with open(filename, 'r', encoding=encoding) as file:
79 contents = file.read()
Terry Jan Reedy82c46152016-06-22 04:54:18 -040080 except OSError:
81 showerror(title='File Load Error',
82 message='Unable to load file %r .' % filename,
83 parent=parent)
84 except UnicodeDecodeError as err:
85 showerror(title='Unicode Decode Error',
86 message=str(err),
87 parent=parent)
Guido van Rossum8ce8a782007-11-01 19:42:39 +000088 else:
Louie Luba365da2017-05-18 05:51:31 +080089 return view_text(parent, title, contents, modal, _utest=_utest)
terryjreedy295304d2017-05-17 22:59:46 -040090 return None
Louie Luba365da2017-05-18 05:51:31 +080091
Guido van Rossum8ce8a782007-11-01 19:42:39 +000092
Steven M. Gava44d3d1a2001-07-31 06:59:02 +000093if __name__ == '__main__':
Terry Jan Reedy537e2c82014-06-05 03:38:34 -040094 import unittest
95 unittest.main('idlelib.idle_test.test_textview', verbosity=2, exit=False)
Terry Jan Reedy1b392ff2014-05-24 18:48:18 -040096 from idlelib.idle_test.htest import run
97 run(TextViewer)