summaryrefslogtreecommitdiffstats
path: root/Lib/idlelib/textview.py
blob: ab653a914132525a20fafb28510321918c60c815 (plain)
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
"""Simple text browser for IDLE

"""
from tkinter import Toplevel, Frame, Button, Text
from tkinter import DISABLED, SUNKEN, VERTICAL, WORD
from tkinter import RIGHT, LEFT, TOP, BOTTOM, BOTH, X, Y
from tkinter.ttk import Scrollbar
from tkinter.messagebox import showerror


class TextViewer(Toplevel):
    "A simple text viewer dialog for IDLE."

    def __init__(self, parent, title, text, modal=True,
                 _htest=False, _utest=False):
        """Show the given text in a scrollable window with a 'close' button.

        If modal is left True, users cannot interact with other windows
        until the textview window is closed.

        parent - parent of this dialog
        title - string which is title of popup dialog
        text - text to display in dialog
        _htest - bool; change box location when running htest.
        _utest - bool; don't wait_window when running unittest.
        """
        Toplevel.__init__(self, parent)
        self.configure(borderwidth=5)
        # Place dialog below parent if running htest.
        self.geometry("=%dx%d+%d+%d" % (750, 500,
                           parent.winfo_rootx() + 10,
                           parent.winfo_rooty() + (10 if not _htest else 100)))
        # TODO: get fg/bg from theme.
        self.bg = '#ffffff'
        self.fg = '#000000'

        self.create_widgets()
        self.title(title)
        self.protocol("WM_DELETE_WINDOW", self.ok)
        self.parent = parent
        self.text.focus_set()
        # Bind keys for closing this dialog.
        self.bind('<Return>', self.ok)
        self.bind('<Escape>', self.ok)
        self.text.insert(0.0, text)
        self.text.config(state=DISABLED)

        if modal:
            self.transient(parent)
            self.grab_set()
            if not _utest:
                self.wait_window()

    def create_widgets(self):
        "Create Frame with Text (with vertical Scrollbar) and Button."
        frame = Frame(self, relief=SUNKEN, height=700)
        frame_buttons = Frame(self)
        self.button_ok = Button(frame_buttons, text='Close',
                                command=self.ok, takefocus=False)
        self.scrollbar = Scrollbar(frame, orient=VERTICAL, takefocus=False)
        self.text = Text(frame, wrap=WORD, highlightthickness=0,
                             fg=self.fg, bg=self.bg)
        self.scrollbar.config(command=self.text.yview)
        self.text.config(yscrollcommand=self.scrollbar.set)
        
        self.button_ok.pack()
        self.scrollbar.pack(side=RIGHT, fill=Y)
        self.text.pack(side=LEFT, expand=True, fill=BOTH)
        frame_buttons.pack(side=BOTTOM, fill=X)
        frame.pack(side=TOP, expand=True, fill=BOTH)

    def ok(self, event=None):
        """Dismiss text viewer dialog."""
        self.destroy()


def view_text(parent, title, text, modal=True, _utest=False):
    """Create TextViewer for given text.

    parent - parent of this dialog
    title - string which is the title of popup dialog
    text - text to display in this dialog
    modal - controls if users can interact with other windows while this
            dialog is displayed
    _utest - bool; controls wait_window on unittest
    """
    return TextViewer(parent, title, text, modal, _utest=_utest)


def view_file(parent, title, filename, encoding=None, modal=True, _utest=False):
    """Create TextViewer for text in filename.

    Return error message if file cannot be read.  Otherwise calls view_text
    with contents of the file.
    """
    try:
        with open(filename, 'r', encoding=encoding) as file:
            contents = file.read()
    except OSError:
        showerror(title='File Load Error',
                  message='Unable to load file %r .' % filename,
                  parent=parent)
    except UnicodeDecodeError as err:
        showerror(title='Unicode Decode Error',
                  message=str(err),
                  parent=parent)
    else:
        return view_text(parent, title, contents, modal, _utest=_utest)
    return None


if __name__ == '__main__':
    import unittest
    unittest.main('idlelib.idle_test.test_textview', verbosity=2, exit=False)
    from idlelib.idle_test.htest import run
    run(TextViewer)