Edit File by line
/home/barbar84/public_h.../wp-conte.../plugins/sujqvwi/ShExBy/shex_roo.../lib64/python2..../idlelib
File: AutoCompleteWindow.py
"""
[0] Fix | Delete
An auto-completion window for IDLE, used by the AutoComplete extension
[1] Fix | Delete
"""
[2] Fix | Delete
from Tkinter import *
[3] Fix | Delete
from idlelib.MultiCall import MC_SHIFT
[4] Fix | Delete
from idlelib.AutoComplete import COMPLETE_FILES, COMPLETE_ATTRIBUTES
[5] Fix | Delete
[6] Fix | Delete
HIDE_VIRTUAL_EVENT_NAME = "<<autocompletewindow-hide>>"
[7] Fix | Delete
HIDE_SEQUENCES = ("<FocusOut>", "<ButtonPress>")
[8] Fix | Delete
KEYPRESS_VIRTUAL_EVENT_NAME = "<<autocompletewindow-keypress>>"
[9] Fix | Delete
# We need to bind event beyond <Key> so that the function will be called
[10] Fix | Delete
# before the default specific IDLE function
[11] Fix | Delete
KEYPRESS_SEQUENCES = ("<Key>", "<Key-BackSpace>", "<Key-Return>", "<Key-Tab>",
[12] Fix | Delete
"<Key-Up>", "<Key-Down>", "<Key-Home>", "<Key-End>",
[13] Fix | Delete
"<Key-Prior>", "<Key-Next>")
[14] Fix | Delete
KEYRELEASE_VIRTUAL_EVENT_NAME = "<<autocompletewindow-keyrelease>>"
[15] Fix | Delete
KEYRELEASE_SEQUENCE = "<KeyRelease>"
[16] Fix | Delete
LISTUPDATE_SEQUENCE = "<B1-ButtonRelease>"
[17] Fix | Delete
WINCONFIG_SEQUENCE = "<Configure>"
[18] Fix | Delete
DOUBLECLICK_SEQUENCE = "<B1-Double-ButtonRelease>"
[19] Fix | Delete
[20] Fix | Delete
class AutoCompleteWindow:
[21] Fix | Delete
[22] Fix | Delete
def __init__(self, widget):
[23] Fix | Delete
# The widget (Text) on which we place the AutoCompleteWindow
[24] Fix | Delete
self.widget = widget
[25] Fix | Delete
# The widgets we create
[26] Fix | Delete
self.autocompletewindow = self.listbox = self.scrollbar = None
[27] Fix | Delete
# The default foreground and background of a selection. Saved because
[28] Fix | Delete
# they are changed to the regular colors of list items when the
[29] Fix | Delete
# completion start is not a prefix of the selected completion
[30] Fix | Delete
self.origselforeground = self.origselbackground = None
[31] Fix | Delete
# The list of completions
[32] Fix | Delete
self.completions = None
[33] Fix | Delete
# A list with more completions, or None
[34] Fix | Delete
self.morecompletions = None
[35] Fix | Delete
# The completion mode. Either AutoComplete.COMPLETE_ATTRIBUTES or
[36] Fix | Delete
# AutoComplete.COMPLETE_FILES
[37] Fix | Delete
self.mode = None
[38] Fix | Delete
# The current completion start, on the text box (a string)
[39] Fix | Delete
self.start = None
[40] Fix | Delete
# The index of the start of the completion
[41] Fix | Delete
self.startindex = None
[42] Fix | Delete
# The last typed start, used so that when the selection changes,
[43] Fix | Delete
# the new start will be as close as possible to the last typed one.
[44] Fix | Delete
self.lasttypedstart = None
[45] Fix | Delete
# Do we have an indication that the user wants the completion window
[46] Fix | Delete
# (for example, he clicked the list)
[47] Fix | Delete
self.userwantswindow = None
[48] Fix | Delete
# event ids
[49] Fix | Delete
self.hideid = self.keypressid = self.listupdateid = self.winconfigid \
[50] Fix | Delete
= self.keyreleaseid = self.doubleclickid = None
[51] Fix | Delete
# Flag set if last keypress was a tab
[52] Fix | Delete
self.lastkey_was_tab = False
[53] Fix | Delete
[54] Fix | Delete
def _change_start(self, newstart):
[55] Fix | Delete
min_len = min(len(self.start), len(newstart))
[56] Fix | Delete
i = 0
[57] Fix | Delete
while i < min_len and self.start[i] == newstart[i]:
[58] Fix | Delete
i += 1
[59] Fix | Delete
if i < len(self.start):
[60] Fix | Delete
self.widget.delete("%s+%dc" % (self.startindex, i),
[61] Fix | Delete
"%s+%dc" % (self.startindex, len(self.start)))
[62] Fix | Delete
if i < len(newstart):
[63] Fix | Delete
self.widget.insert("%s+%dc" % (self.startindex, i),
[64] Fix | Delete
newstart[i:])
[65] Fix | Delete
self.start = newstart
[66] Fix | Delete
[67] Fix | Delete
def _binary_search(self, s):
[68] Fix | Delete
"""Find the first index in self.completions where completions[i] is
[69] Fix | Delete
greater or equal to s, or the last index if there is no such
[70] Fix | Delete
one."""
[71] Fix | Delete
i = 0; j = len(self.completions)
[72] Fix | Delete
while j > i:
[73] Fix | Delete
m = (i + j) // 2
[74] Fix | Delete
if self.completions[m] >= s:
[75] Fix | Delete
j = m
[76] Fix | Delete
else:
[77] Fix | Delete
i = m + 1
[78] Fix | Delete
return min(i, len(self.completions)-1)
[79] Fix | Delete
[80] Fix | Delete
def _complete_string(self, s):
[81] Fix | Delete
"""Assuming that s is the prefix of a string in self.completions,
[82] Fix | Delete
return the longest string which is a prefix of all the strings which
[83] Fix | Delete
s is a prefix of them. If s is not a prefix of a string, return s."""
[84] Fix | Delete
first = self._binary_search(s)
[85] Fix | Delete
if self.completions[first][:len(s)] != s:
[86] Fix | Delete
# There is not even one completion which s is a prefix of.
[87] Fix | Delete
return s
[88] Fix | Delete
# Find the end of the range of completions where s is a prefix of.
[89] Fix | Delete
i = first + 1
[90] Fix | Delete
j = len(self.completions)
[91] Fix | Delete
while j > i:
[92] Fix | Delete
m = (i + j) // 2
[93] Fix | Delete
if self.completions[m][:len(s)] != s:
[94] Fix | Delete
j = m
[95] Fix | Delete
else:
[96] Fix | Delete
i = m + 1
[97] Fix | Delete
last = i-1
[98] Fix | Delete
[99] Fix | Delete
if first == last: # only one possible completion
[100] Fix | Delete
return self.completions[first]
[101] Fix | Delete
[102] Fix | Delete
# We should return the maximum prefix of first and last
[103] Fix | Delete
first_comp = self.completions[first]
[104] Fix | Delete
last_comp = self.completions[last]
[105] Fix | Delete
min_len = min(len(first_comp), len(last_comp))
[106] Fix | Delete
i = len(s)
[107] Fix | Delete
while i < min_len and first_comp[i] == last_comp[i]:
[108] Fix | Delete
i += 1
[109] Fix | Delete
return first_comp[:i]
[110] Fix | Delete
[111] Fix | Delete
def _selection_changed(self):
[112] Fix | Delete
"""Should be called when the selection of the Listbox has changed.
[113] Fix | Delete
Updates the Listbox display and calls _change_start."""
[114] Fix | Delete
cursel = int(self.listbox.curselection()[0])
[115] Fix | Delete
[116] Fix | Delete
self.listbox.see(cursel)
[117] Fix | Delete
[118] Fix | Delete
lts = self.lasttypedstart
[119] Fix | Delete
selstart = self.completions[cursel]
[120] Fix | Delete
if self._binary_search(lts) == cursel:
[121] Fix | Delete
newstart = lts
[122] Fix | Delete
else:
[123] Fix | Delete
min_len = min(len(lts), len(selstart))
[124] Fix | Delete
i = 0
[125] Fix | Delete
while i < min_len and lts[i] == selstart[i]:
[126] Fix | Delete
i += 1
[127] Fix | Delete
newstart = selstart[:i]
[128] Fix | Delete
self._change_start(newstart)
[129] Fix | Delete
[130] Fix | Delete
if self.completions[cursel][:len(self.start)] == self.start:
[131] Fix | Delete
# start is a prefix of the selected completion
[132] Fix | Delete
self.listbox.configure(selectbackground=self.origselbackground,
[133] Fix | Delete
selectforeground=self.origselforeground)
[134] Fix | Delete
else:
[135] Fix | Delete
self.listbox.configure(selectbackground=self.listbox.cget("bg"),
[136] Fix | Delete
selectforeground=self.listbox.cget("fg"))
[137] Fix | Delete
# If there are more completions, show them, and call me again.
[138] Fix | Delete
if self.morecompletions:
[139] Fix | Delete
self.completions = self.morecompletions
[140] Fix | Delete
self.morecompletions = None
[141] Fix | Delete
self.listbox.delete(0, END)
[142] Fix | Delete
for item in self.completions:
[143] Fix | Delete
self.listbox.insert(END, item)
[144] Fix | Delete
self.listbox.select_set(self._binary_search(self.start))
[145] Fix | Delete
self._selection_changed()
[146] Fix | Delete
[147] Fix | Delete
def show_window(self, comp_lists, index, complete, mode, userWantsWin):
[148] Fix | Delete
"""Show the autocomplete list, bind events.
[149] Fix | Delete
If complete is True, complete the text, and if there is exactly one
[150] Fix | Delete
matching completion, don't open a list."""
[151] Fix | Delete
# Handle the start we already have
[152] Fix | Delete
self.completions, self.morecompletions = comp_lists
[153] Fix | Delete
self.mode = mode
[154] Fix | Delete
self.startindex = self.widget.index(index)
[155] Fix | Delete
self.start = self.widget.get(self.startindex, "insert")
[156] Fix | Delete
if complete:
[157] Fix | Delete
completed = self._complete_string(self.start)
[158] Fix | Delete
start = self.start
[159] Fix | Delete
self._change_start(completed)
[160] Fix | Delete
i = self._binary_search(completed)
[161] Fix | Delete
if self.completions[i] == completed and \
[162] Fix | Delete
(i == len(self.completions)-1 or
[163] Fix | Delete
self.completions[i+1][:len(completed)] != completed):
[164] Fix | Delete
# There is exactly one matching completion
[165] Fix | Delete
return completed == start
[166] Fix | Delete
self.userwantswindow = userWantsWin
[167] Fix | Delete
self.lasttypedstart = self.start
[168] Fix | Delete
[169] Fix | Delete
# Put widgets in place
[170] Fix | Delete
self.autocompletewindow = acw = Toplevel(self.widget)
[171] Fix | Delete
# Put it in a position so that it is not seen.
[172] Fix | Delete
acw.wm_geometry("+10000+10000")
[173] Fix | Delete
# Make it float
[174] Fix | Delete
acw.wm_overrideredirect(1)
[175] Fix | Delete
try:
[176] Fix | Delete
# This command is only needed and available on Tk >= 8.4.0 for OSX
[177] Fix | Delete
# Without it, call tips intrude on the typing process by grabbing
[178] Fix | Delete
# the focus.
[179] Fix | Delete
acw.tk.call("::tk::unsupported::MacWindowStyle", "style", acw._w,
[180] Fix | Delete
"help", "noActivates")
[181] Fix | Delete
except TclError:
[182] Fix | Delete
pass
[183] Fix | Delete
self.scrollbar = scrollbar = Scrollbar(acw, orient=VERTICAL)
[184] Fix | Delete
self.listbox = listbox = Listbox(acw, yscrollcommand=scrollbar.set,
[185] Fix | Delete
exportselection=False, bg="white")
[186] Fix | Delete
for item in self.completions:
[187] Fix | Delete
listbox.insert(END, item)
[188] Fix | Delete
self.origselforeground = listbox.cget("selectforeground")
[189] Fix | Delete
self.origselbackground = listbox.cget("selectbackground")
[190] Fix | Delete
scrollbar.config(command=listbox.yview)
[191] Fix | Delete
scrollbar.pack(side=RIGHT, fill=Y)
[192] Fix | Delete
listbox.pack(side=LEFT, fill=BOTH, expand=True)
[193] Fix | Delete
acw.lift() # work around bug in Tk 8.5.18+ (issue #24570)
[194] Fix | Delete
[195] Fix | Delete
# Initialize the listbox selection
[196] Fix | Delete
self.listbox.select_set(self._binary_search(self.start))
[197] Fix | Delete
self._selection_changed()
[198] Fix | Delete
[199] Fix | Delete
# bind events
[200] Fix | Delete
self.hideid = self.widget.bind(HIDE_VIRTUAL_EVENT_NAME,
[201] Fix | Delete
self.hide_event)
[202] Fix | Delete
for seq in HIDE_SEQUENCES:
[203] Fix | Delete
self.widget.event_add(HIDE_VIRTUAL_EVENT_NAME, seq)
[204] Fix | Delete
self.keypressid = self.widget.bind(KEYPRESS_VIRTUAL_EVENT_NAME,
[205] Fix | Delete
self.keypress_event)
[206] Fix | Delete
for seq in KEYPRESS_SEQUENCES:
[207] Fix | Delete
self.widget.event_add(KEYPRESS_VIRTUAL_EVENT_NAME, seq)
[208] Fix | Delete
self.keyreleaseid = self.widget.bind(KEYRELEASE_VIRTUAL_EVENT_NAME,
[209] Fix | Delete
self.keyrelease_event)
[210] Fix | Delete
self.widget.event_add(KEYRELEASE_VIRTUAL_EVENT_NAME,KEYRELEASE_SEQUENCE)
[211] Fix | Delete
self.listupdateid = listbox.bind(LISTUPDATE_SEQUENCE,
[212] Fix | Delete
self.listselect_event)
[213] Fix | Delete
self.winconfigid = acw.bind(WINCONFIG_SEQUENCE, self.winconfig_event)
[214] Fix | Delete
self.doubleclickid = listbox.bind(DOUBLECLICK_SEQUENCE,
[215] Fix | Delete
self.doubleclick_event)
[216] Fix | Delete
[217] Fix | Delete
def winconfig_event(self, event):
[218] Fix | Delete
if not self.is_active():
[219] Fix | Delete
return
[220] Fix | Delete
# Position the completion list window
[221] Fix | Delete
text = self.widget
[222] Fix | Delete
text.see(self.startindex)
[223] Fix | Delete
x, y, cx, cy = text.bbox(self.startindex)
[224] Fix | Delete
acw = self.autocompletewindow
[225] Fix | Delete
acw_width, acw_height = acw.winfo_width(), acw.winfo_height()
[226] Fix | Delete
text_width, text_height = text.winfo_width(), text.winfo_height()
[227] Fix | Delete
new_x = text.winfo_rootx() + min(x, max(0, text_width - acw_width))
[228] Fix | Delete
new_y = text.winfo_rooty() + y
[229] Fix | Delete
if (text_height - (y + cy) >= acw_height # enough height below
[230] Fix | Delete
or y < acw_height): # not enough height above
[231] Fix | Delete
# place acw below current line
[232] Fix | Delete
new_y += cy
[233] Fix | Delete
else:
[234] Fix | Delete
# place acw above current line
[235] Fix | Delete
new_y -= acw_height
[236] Fix | Delete
acw.wm_geometry("+%d+%d" % (new_x, new_y))
[237] Fix | Delete
[238] Fix | Delete
def hide_event(self, event):
[239] Fix | Delete
if not self.is_active():
[240] Fix | Delete
return
[241] Fix | Delete
self.hide_window()
[242] Fix | Delete
[243] Fix | Delete
def listselect_event(self, event):
[244] Fix | Delete
if not self.is_active():
[245] Fix | Delete
return
[246] Fix | Delete
self.userwantswindow = True
[247] Fix | Delete
cursel = int(self.listbox.curselection()[0])
[248] Fix | Delete
self._change_start(self.completions[cursel])
[249] Fix | Delete
[250] Fix | Delete
def doubleclick_event(self, event):
[251] Fix | Delete
# Put the selected completion in the text, and close the list
[252] Fix | Delete
cursel = int(self.listbox.curselection()[0])
[253] Fix | Delete
self._change_start(self.completions[cursel])
[254] Fix | Delete
self.hide_window()
[255] Fix | Delete
[256] Fix | Delete
def keypress_event(self, event):
[257] Fix | Delete
if not self.is_active():
[258] Fix | Delete
return
[259] Fix | Delete
keysym = event.keysym
[260] Fix | Delete
if hasattr(event, "mc_state"):
[261] Fix | Delete
state = event.mc_state
[262] Fix | Delete
else:
[263] Fix | Delete
state = 0
[264] Fix | Delete
if keysym != "Tab":
[265] Fix | Delete
self.lastkey_was_tab = False
[266] Fix | Delete
if (len(keysym) == 1 or keysym in ("underscore", "BackSpace")
[267] Fix | Delete
or (self.mode == COMPLETE_FILES and keysym in
[268] Fix | Delete
("period", "minus"))) \
[269] Fix | Delete
and not (state & ~MC_SHIFT):
[270] Fix | Delete
# Normal editing of text
[271] Fix | Delete
if len(keysym) == 1:
[272] Fix | Delete
self._change_start(self.start + keysym)
[273] Fix | Delete
elif keysym == "underscore":
[274] Fix | Delete
self._change_start(self.start + '_')
[275] Fix | Delete
elif keysym == "period":
[276] Fix | Delete
self._change_start(self.start + '.')
[277] Fix | Delete
elif keysym == "minus":
[278] Fix | Delete
self._change_start(self.start + '-')
[279] Fix | Delete
else:
[280] Fix | Delete
# keysym == "BackSpace"
[281] Fix | Delete
if len(self.start) == 0:
[282] Fix | Delete
self.hide_window()
[283] Fix | Delete
return
[284] Fix | Delete
self._change_start(self.start[:-1])
[285] Fix | Delete
self.lasttypedstart = self.start
[286] Fix | Delete
self.listbox.select_clear(0, int(self.listbox.curselection()[0]))
[287] Fix | Delete
self.listbox.select_set(self._binary_search(self.start))
[288] Fix | Delete
self._selection_changed()
[289] Fix | Delete
return "break"
[290] Fix | Delete
[291] Fix | Delete
elif keysym == "Return":
[292] Fix | Delete
self.hide_window()
[293] Fix | Delete
return
[294] Fix | Delete
[295] Fix | Delete
elif (self.mode == COMPLETE_ATTRIBUTES and keysym in
[296] Fix | Delete
("period", "space", "parenleft", "parenright", "bracketleft",
[297] Fix | Delete
"bracketright")) or \
[298] Fix | Delete
(self.mode == COMPLETE_FILES and keysym in
[299] Fix | Delete
("slash", "backslash", "quotedbl", "apostrophe")) \
[300] Fix | Delete
and not (state & ~MC_SHIFT):
[301] Fix | Delete
# If start is a prefix of the selection, but is not '' when
[302] Fix | Delete
# completing file names, put the whole
[303] Fix | Delete
# selected completion. Anyway, close the list.
[304] Fix | Delete
cursel = int(self.listbox.curselection()[0])
[305] Fix | Delete
if self.completions[cursel][:len(self.start)] == self.start \
[306] Fix | Delete
and (self.mode == COMPLETE_ATTRIBUTES or self.start):
[307] Fix | Delete
self._change_start(self.completions[cursel])
[308] Fix | Delete
self.hide_window()
[309] Fix | Delete
return
[310] Fix | Delete
[311] Fix | Delete
elif keysym in ("Home", "End", "Prior", "Next", "Up", "Down") and \
[312] Fix | Delete
not state:
[313] Fix | Delete
# Move the selection in the listbox
[314] Fix | Delete
self.userwantswindow = True
[315] Fix | Delete
cursel = int(self.listbox.curselection()[0])
[316] Fix | Delete
if keysym == "Home":
[317] Fix | Delete
newsel = 0
[318] Fix | Delete
elif keysym == "End":
[319] Fix | Delete
newsel = len(self.completions)-1
[320] Fix | Delete
elif keysym in ("Prior", "Next"):
[321] Fix | Delete
jump = self.listbox.nearest(self.listbox.winfo_height()) - \
[322] Fix | Delete
self.listbox.nearest(0)
[323] Fix | Delete
if keysym == "Prior":
[324] Fix | Delete
newsel = max(0, cursel-jump)
[325] Fix | Delete
else:
[326] Fix | Delete
assert keysym == "Next"
[327] Fix | Delete
newsel = min(len(self.completions)-1, cursel+jump)
[328] Fix | Delete
elif keysym == "Up":
[329] Fix | Delete
newsel = max(0, cursel-1)
[330] Fix | Delete
else:
[331] Fix | Delete
assert keysym == "Down"
[332] Fix | Delete
newsel = min(len(self.completions)-1, cursel+1)
[333] Fix | Delete
self.listbox.select_clear(cursel)
[334] Fix | Delete
self.listbox.select_set(newsel)
[335] Fix | Delete
self._selection_changed()
[336] Fix | Delete
self._change_start(self.completions[newsel])
[337] Fix | Delete
return "break"
[338] Fix | Delete
[339] Fix | Delete
elif (keysym == "Tab" and not state):
[340] Fix | Delete
if self.lastkey_was_tab:
[341] Fix | Delete
# two tabs in a row; insert current selection and close acw
[342] Fix | Delete
cursel = int(self.listbox.curselection()[0])
[343] Fix | Delete
self._change_start(self.completions[cursel])
[344] Fix | Delete
self.hide_window()
[345] Fix | Delete
return "break"
[346] Fix | Delete
else:
[347] Fix | Delete
# first tab; let AutoComplete handle the completion
[348] Fix | Delete
self.userwantswindow = True
[349] Fix | Delete
self.lastkey_was_tab = True
[350] Fix | Delete
return
[351] Fix | Delete
[352] Fix | Delete
elif any(s in keysym for s in ("Shift", "Control", "Alt",
[353] Fix | Delete
"Meta", "Command", "Option")):
[354] Fix | Delete
# A modifier key, so ignore
[355] Fix | Delete
return
[356] Fix | Delete
[357] Fix | Delete
else:
[358] Fix | Delete
# Unknown event, close the window and let it through.
[359] Fix | Delete
self.hide_window()
[360] Fix | Delete
return
[361] Fix | Delete
[362] Fix | Delete
def keyrelease_event(self, event):
[363] Fix | Delete
if not self.is_active():
[364] Fix | Delete
return
[365] Fix | Delete
if self.widget.index("insert") != \
[366] Fix | Delete
self.widget.index("%s+%dc" % (self.startindex, len(self.start))):
[367] Fix | Delete
# If we didn't catch an event which moved the insert, close window
[368] Fix | Delete
self.hide_window()
[369] Fix | Delete
[370] Fix | Delete
def is_active(self):
[371] Fix | Delete
return self.autocompletewindow is not None
[372] Fix | Delete
[373] Fix | Delete
def complete(self):
[374] Fix | Delete
self._change_start(self._complete_string(self.start))
[375] Fix | Delete
# The selection doesn't change.
[376] Fix | Delete
[377] Fix | Delete
def hide_window(self):
[378] Fix | Delete
if not self.is_active():
[379] Fix | Delete
return
[380] Fix | Delete
[381] Fix | Delete
# unbind events
[382] Fix | Delete
for seq in HIDE_SEQUENCES:
[383] Fix | Delete
self.widget.event_delete(HIDE_VIRTUAL_EVENT_NAME, seq)
[384] Fix | Delete
self.widget.unbind(HIDE_VIRTUAL_EVENT_NAME, self.hideid)
[385] Fix | Delete
self.hideid = None
[386] Fix | Delete
for seq in KEYPRESS_SEQUENCES:
[387] Fix | Delete
self.widget.event_delete(KEYPRESS_VIRTUAL_EVENT_NAME, seq)
[388] Fix | Delete
self.widget.unbind(KEYPRESS_VIRTUAL_EVENT_NAME, self.keypressid)
[389] Fix | Delete
self.keypressid = None
[390] Fix | Delete
self.widget.event_delete(KEYRELEASE_VIRTUAL_EVENT_NAME,
[391] Fix | Delete
KEYRELEASE_SEQUENCE)
[392] Fix | Delete
self.widget.unbind(KEYRELEASE_VIRTUAL_EVENT_NAME, self.keyreleaseid)
[393] Fix | Delete
self.keyreleaseid = None
[394] Fix | Delete
self.listbox.unbind(LISTUPDATE_SEQUENCE, self.listupdateid)
[395] Fix | Delete
self.listupdateid = None
[396] Fix | Delete
self.autocompletewindow.unbind(WINCONFIG_SEQUENCE, self.winconfigid)
[397] Fix | Delete
self.winconfigid = None
[398] Fix | Delete
[399] Fix | Delete
# destroy widgets
[400] Fix | Delete
self.scrollbar.destroy()
[401] Fix | Delete
self.scrollbar = None
[402] Fix | Delete
self.listbox.destroy()
[403] Fix | Delete
self.listbox = None
[404] Fix | Delete
self.autocompletewindow.destroy()
[405] Fix | Delete
self.autocompletewindow = None
[406] Fix | Delete
[407] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function