(root)/
Python-3.11.7/
Lib/
idlelib/
searchbase.py
       1  '''Define SearchDialogBase used by Search, Replace, and Grep dialogs.'''
       2  
       3  from tkinter import Toplevel
       4  from tkinter.ttk import Frame, Entry, Label, Button, Checkbutton, Radiobutton
       5  from tkinter.simpledialog import _setup_dialog
       6  
       7  
       8  class ESC[4;38;5;81mSearchDialogBase:
       9      '''Create most of a 3 or 4 row, 3 column search dialog.
      10  
      11      The left and wide middle column contain:
      12      1 or 2 labeled text entry lines (make_entry, create_entries);
      13      a row of standard Checkbuttons (make_frame, create_option_buttons),
      14      each of which corresponds to a search engine Variable;
      15      a row of dialog-specific Check/Radiobuttons (create_other_buttons).
      16  
      17      The narrow right column contains command buttons
      18      (make_button, create_command_buttons).
      19      These are bound to functions that execute the command.
      20  
      21      Except for command buttons, this base class is not limited to items
      22      common to all three subclasses.  Rather, it is the Find dialog minus
      23      the "Find Next" command, its execution function, and the
      24      default_command attribute needed in create_widgets. The other
      25      dialogs override attributes and methods, the latter to replace and
      26      add widgets.
      27      '''
      28  
      29      title = "Search Dialog"  # replace in subclasses
      30      icon = "Search"
      31      needwrapbutton = 1  # not in Find in Files
      32  
      33      def __init__(self, root, engine):
      34          '''Initialize root, engine, and top attributes.
      35  
      36          top (level widget): set in create_widgets() called from open().
      37          frame: container for all widgets in dialog.
      38          text (Text searched): set in open(), only used in subclasses().
      39          ent (ry): created in make_entry() called from create_entry().
      40          row (of grid): 0 in create_widgets(), +1 in make_entry/frame().
      41          default_command: set in subclasses, used in create_widgets().
      42  
      43          title (of dialog): class attribute, override in subclasses.
      44          icon (of dialog): ditto, use unclear if cannot minimize dialog.
      45          '''
      46          self.root = root
      47          self.bell = root.bell
      48          self.engine = engine
      49          self.top = None
      50  
      51      def open(self, text, searchphrase=None):
      52          "Make dialog visible on top of others and ready to use."
      53          self.text = text
      54          if not self.top:
      55              self.create_widgets()
      56          else:
      57              self.top.deiconify()
      58              self.top.tkraise()
      59          self.top.transient(text.winfo_toplevel())
      60          if searchphrase:
      61              self.ent.delete(0,"end")
      62              self.ent.insert("end",searchphrase)
      63          self.ent.focus_set()
      64          self.ent.selection_range(0, "end")
      65          self.ent.icursor(0)
      66          self.top.grab_set()
      67  
      68      def close(self, event=None):
      69          "Put dialog away for later use."
      70          if self.top:
      71              self.top.grab_release()
      72              self.top.transient('')
      73              self.top.withdraw()
      74  
      75      def create_widgets(self):
      76          '''Create basic 3 row x 3 col search (find) dialog.
      77  
      78          Other dialogs override subsidiary create_x methods as needed.
      79          Replace and Find-in-Files add another entry row.
      80          '''
      81          top = Toplevel(self.root)
      82          top.bind("<Return>", self.default_command)
      83          top.bind("<Escape>", self.close)
      84          top.protocol("WM_DELETE_WINDOW", self.close)
      85          top.wm_title(self.title)
      86          top.wm_iconname(self.icon)
      87          _setup_dialog(top)
      88          self.top = top
      89          self.frame = Frame(top, padding="5px")
      90          self.frame.grid(sticky="nwes")
      91          top.grid_columnconfigure(0, weight=100)
      92          top.grid_rowconfigure(0, weight=100)
      93  
      94          self.row = 0
      95          self.frame.grid_columnconfigure(0, pad=2, weight=0)
      96          self.frame.grid_columnconfigure(1, pad=2, minsize=100, weight=100)
      97  
      98          self.create_entries()  # row 0 (and maybe 1), cols 0, 1
      99          self.create_option_buttons()  # next row, cols 0, 1
     100          self.create_other_buttons()  # next row, cols 0, 1
     101          self.create_command_buttons()  # col 2, all rows
     102  
     103      def make_entry(self, label_text, var):
     104          '''Return (entry, label), .
     105  
     106          entry - gridded labeled Entry for text entry.
     107          label - Label widget, returned for testing.
     108          '''
     109          label = Label(self.frame, text=label_text)
     110          label.grid(row=self.row, column=0, sticky="nw")
     111          entry = Entry(self.frame, textvariable=var, exportselection=0)
     112          entry.grid(row=self.row, column=1, sticky="nwe")
     113          self.row = self.row + 1
     114          return entry, label
     115  
     116      def create_entries(self):
     117          "Create one or more entry lines with make_entry."
     118          self.ent = self.make_entry("Find:", self.engine.patvar)[0]
     119  
     120      def make_frame(self,labeltext=None):
     121          '''Return (frame, label).
     122  
     123          frame - gridded labeled Frame for option or other buttons.
     124          label - Label widget, returned for testing.
     125          '''
     126          if labeltext:
     127              label = Label(self.frame, text=labeltext)
     128              label.grid(row=self.row, column=0, sticky="nw")
     129          else:
     130              label = ''
     131          frame = Frame(self.frame)
     132          frame.grid(row=self.row, column=1, columnspan=1, sticky="nwe")
     133          self.row = self.row + 1
     134          return frame, label
     135  
     136      def create_option_buttons(self):
     137          '''Return (filled frame, options) for testing.
     138  
     139          Options is a list of searchengine booleanvar, label pairs.
     140          A gridded frame from make_frame is filled with a Checkbutton
     141          for each pair, bound to the var, with the corresponding label.
     142          '''
     143          frame = self.make_frame("Options")[0]
     144          engine = self.engine
     145          options = [(engine.revar, "Regular expression"),
     146                     (engine.casevar, "Match case"),
     147                     (engine.wordvar, "Whole word")]
     148          if self.needwrapbutton:
     149              options.append((engine.wrapvar, "Wrap around"))
     150          for var, label in options:
     151              btn = Checkbutton(frame, variable=var, text=label)
     152              btn.pack(side="left", fill="both")
     153          return frame, options
     154  
     155      def create_other_buttons(self):
     156          '''Return (frame, others) for testing.
     157  
     158          Others is a list of value, label pairs.
     159          A gridded frame from make_frame is filled with radio buttons.
     160          '''
     161          frame = self.make_frame("Direction")[0]
     162          var = self.engine.backvar
     163          others = [(1, 'Up'), (0, 'Down')]
     164          for val, label in others:
     165              btn = Radiobutton(frame, variable=var, value=val, text=label)
     166              btn.pack(side="left", fill="both")
     167          return frame, others
     168  
     169      def make_button(self, label, command, isdef=0):
     170          "Return command button gridded in command frame."
     171          b = Button(self.buttonframe,
     172                     text=label, command=command,
     173                     default=isdef and "active" or "normal")
     174          cols,rows=self.buttonframe.grid_size()
     175          b.grid(pady=1,row=rows,column=0,sticky="ew")
     176          self.buttonframe.grid(rowspan=rows+1)
     177          return b
     178  
     179      def create_command_buttons(self):
     180          "Place buttons in vertical command frame gridded on right."
     181          f = self.buttonframe = Frame(self.frame)
     182          f.grid(row=0,column=2,padx=2,pady=2,ipadx=2,ipady=2)
     183  
     184          b = self.make_button("Close", self.close)
     185          b.lower()
     186  
     187  
     188  class ESC[4;38;5;81m_searchbase(ESC[4;38;5;149mSearchDialogBase):  # htest #
     189      "Create auto-opening dialog with no text connection."
     190  
     191      def __init__(self, parent):
     192          import re
     193          from idlelib import searchengine
     194  
     195          self.root = parent
     196          self.engine = searchengine.get(parent)
     197          self.create_widgets()
     198          print(parent.geometry())
     199          width,height, x,y = list(map(int, re.split('[x+]', parent.geometry())))
     200          self.top.geometry("+%d+%d" % (x + 40, y + 175))
     201  
     202      def default_command(self, dummy): pass
     203  
     204  
     205  if __name__ == '__main__':
     206      from unittest import main
     207      main('idlelib.idle_test.test_searchbase', verbosity=2, exit=False)
     208  
     209      from idlelib.idle_test.htest import run
     210      run(_searchbase)