(root)/
Python-3.11.7/
Lib/
idlelib/
textview.py
       1  """Simple text browser for IDLE
       2  
       3  """
       4  from tkinter import Toplevel, Text, TclError,\
       5      HORIZONTAL, VERTICAL, NS, EW, NSEW, NONE, WORD, SUNKEN
       6  from tkinter.ttk import Frame, Scrollbar, Button
       7  from tkinter.messagebox import showerror
       8  
       9  from idlelib.colorizer import color_config
      10  
      11  
      12  class ESC[4;38;5;81mAutoHideScrollbar(ESC[4;38;5;149mScrollbar):
      13      """A scrollbar that is automatically hidden when not needed.
      14  
      15      Only the grid geometry manager is supported.
      16      """
      17      def set(self, lo, hi):
      18          if float(lo) > 0.0 or float(hi) < 1.0:
      19              self.grid()
      20          else:
      21              self.grid_remove()
      22          super().set(lo, hi)
      23  
      24      def pack(self, **kwargs):
      25          raise TclError(f'{self.__class__.__name__} does not support "pack"')
      26  
      27      def place(self, **kwargs):
      28          raise TclError(f'{self.__class__.__name__} does not support "place"')
      29  
      30  
      31  class ESC[4;38;5;81mScrollableTextFrame(ESC[4;38;5;149mFrame):
      32      """Display text with scrollbar(s)."""
      33  
      34      def __init__(self, master, wrap=NONE, **kwargs):
      35          """Create a frame for Textview.
      36  
      37          master - master widget for this frame
      38          wrap - type of text wrapping to use ('word', 'char' or 'none')
      39  
      40          All parameters except for 'wrap' are passed to Frame.__init__().
      41  
      42          The Text widget is accessible via the 'text' attribute.
      43  
      44          Note: Changing the wrapping mode of the text widget after
      45          instantiation is not supported.
      46          """
      47          super().__init__(master, **kwargs)
      48  
      49          text = self.text = Text(self, wrap=wrap)
      50          text.grid(row=0, column=0, sticky=NSEW)
      51          self.grid_rowconfigure(0, weight=1)
      52          self.grid_columnconfigure(0, weight=1)
      53  
      54          # vertical scrollbar
      55          self.yscroll = AutoHideScrollbar(self, orient=VERTICAL,
      56                                           takefocus=False,
      57                                           command=text.yview)
      58          self.yscroll.grid(row=0, column=1, sticky=NS)
      59          text['yscrollcommand'] = self.yscroll.set
      60  
      61          # horizontal scrollbar - only when wrap is set to NONE
      62          if wrap == NONE:
      63              self.xscroll = AutoHideScrollbar(self, orient=HORIZONTAL,
      64                                               takefocus=False,
      65                                               command=text.xview)
      66              self.xscroll.grid(row=1, column=0, sticky=EW)
      67              text['xscrollcommand'] = self.xscroll.set
      68          else:
      69              self.xscroll = None
      70  
      71  
      72  class ESC[4;38;5;81mViewFrame(ESC[4;38;5;149mFrame):
      73      "Display TextFrame and Close button."
      74      def __init__(self, parent, contents, wrap='word'):
      75          """Create a frame for viewing text with a "Close" button.
      76  
      77          parent - parent widget for this frame
      78          contents - text to display
      79          wrap - type of text wrapping to use ('word', 'char' or 'none')
      80  
      81          The Text widget is accessible via the 'text' attribute.
      82          """
      83          super().__init__(parent)
      84          self.parent = parent
      85          self.bind('<Return>', self.ok)
      86          self.bind('<Escape>', self.ok)
      87          self.textframe = ScrollableTextFrame(self, relief=SUNKEN, height=700)
      88  
      89          text = self.text = self.textframe.text
      90          text.insert('1.0', contents)
      91          text.configure(wrap=wrap, highlightthickness=0, state='disabled')
      92          color_config(text)
      93          text.focus_set()
      94  
      95          self.button_ok = button_ok = Button(
      96                  self, text='Close', command=self.ok, takefocus=False)
      97          self.textframe.pack(side='top', expand=True, fill='both')
      98          button_ok.pack(side='bottom')
      99  
     100      def ok(self, event=None):
     101          """Dismiss text viewer dialog."""
     102          self.parent.destroy()
     103  
     104  
     105  class ESC[4;38;5;81mViewWindow(ESC[4;38;5;149mToplevel):
     106      "A simple text viewer dialog for IDLE."
     107  
     108      def __init__(self, parent, title, contents, modal=True, wrap=WORD,
     109                   *, _htest=False, _utest=False):
     110          """Show the given text in a scrollable window with a 'close' button.
     111  
     112          If modal is left True, users cannot interact with other windows
     113          until the textview window is closed.
     114  
     115          parent - parent of this dialog
     116          title - string which is title of popup dialog
     117          contents - text to display in dialog
     118          wrap - type of text wrapping to use ('word', 'char' or 'none')
     119          _htest - bool; change box location when running htest.
     120          _utest - bool; don't wait_window when running unittest.
     121          """
     122          super().__init__(parent)
     123          self['borderwidth'] = 5
     124          # Place dialog below parent if running htest.
     125          x = parent.winfo_rootx() + 10
     126          y = parent.winfo_rooty() + (10 if not _htest else 100)
     127          self.geometry(f'=750x500+{x}+{y}')
     128  
     129          self.title(title)
     130          self.viewframe = ViewFrame(self, contents, wrap=wrap)
     131          self.protocol("WM_DELETE_WINDOW", self.ok)
     132          self.button_ok = button_ok = Button(self, text='Close',
     133                                              command=self.ok, takefocus=False)
     134          self.viewframe.pack(side='top', expand=True, fill='both')
     135  
     136          self.is_modal = modal
     137          if self.is_modal:
     138              self.transient(parent)
     139              self.grab_set()
     140              if not _utest:
     141                  self.wait_window()
     142  
     143      def ok(self, event=None):
     144          """Dismiss text viewer dialog."""
     145          if self.is_modal:
     146              self.grab_release()
     147          self.destroy()
     148  
     149  
     150  def view_text(parent, title, contents, modal=True, wrap='word', _utest=False):
     151      """Create text viewer for given text.
     152  
     153      parent - parent of this dialog
     154      title - string which is the title of popup dialog
     155      contents - text to display in this dialog
     156      wrap - type of text wrapping to use ('word', 'char' or 'none')
     157      modal - controls if users can interact with other windows while this
     158              dialog is displayed
     159      _utest - bool; controls wait_window on unittest
     160      """
     161      return ViewWindow(parent, title, contents, modal, wrap=wrap, _utest=_utest)
     162  
     163  
     164  def view_file(parent, title, filename, encoding, modal=True, wrap='word',
     165                _utest=False):
     166      """Create text viewer for text in filename.
     167  
     168      Return error message if file cannot be read.  Otherwise calls view_text
     169      with contents of the file.
     170      """
     171      try:
     172          with open(filename, encoding=encoding) as file:
     173              contents = file.read()
     174      except OSError:
     175          showerror(title='File Load Error',
     176                    message=f'Unable to load file {filename!r} .',
     177                    parent=parent)
     178      except UnicodeDecodeError as err:
     179          showerror(title='Unicode Decode Error',
     180                    message=str(err),
     181                    parent=parent)
     182      else:
     183          return view_text(parent, title, contents, modal, wrap=wrap,
     184                           _utest=_utest)
     185      return None
     186  
     187  
     188  if __name__ == '__main__':
     189      from unittest import main
     190      main('idlelib.idle_test.test_textview', verbosity=2, exit=False)
     191  
     192      from idlelib.idle_test.htest import run
     193      run(ViewWindow)