Advertisement
Uno-Dan

Treeview

Apr 13th, 2020
337
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 26.62 KB | None | 0 0
  1. class Treeview(Base, ttk.Treeview):
  2.     def __init__(self, parent, key, **kwargs):
  3.         Base.__init__(self, parent, key, **kwargs)
  4.         self.columns = self.setting_get('columns', {})
  5.         self.headings = self.setting_get('headings', {})
  6.         ttk.Treeview.__init__(self, parent, columns=tuple(range(1, len(self.columns))), **self.options_get())
  7.  
  8.         self.undo_data = {}
  9.         self.bindings = {}
  10.         self.column_sort = {}
  11.  
  12.         self.levels = \
  13.             self.x_root = \
  14.             self.y_root = \
  15.             self.largest = \
  16.             self.xscroll = \
  17.             self.yscroll = \
  18.             self.pointer_x = \
  19.             self.pointer_y = \
  20.             self.direction = \
  21.             self.detached = \
  22.             self._selection_colors = \
  23.             self.root_selection = None
  24.  
  25.         self.init()
  26.  
  27.     def init(self):
  28.         def set_columns():
  29.             for index, column in enumerate(self.columns):
  30.                 self.column(f'#{index}', **dict(column))
  31.  
  32.         def set_headings():
  33.             for index, heading in enumerate(self.headings):
  34.                 self.column_sort[f'#{index}'] = True
  35.                 self.heading(f'#{index}', **dict(heading))
  36.  
  37.         def set_scrolling():
  38.             scroll = self.setting_get('scroll')
  39.             if scroll:
  40.                 self.scrollbars_add(*scroll)
  41.  
  42.         set_columns()
  43.         set_headings()
  44.         set_scrolling()
  45.  
  46.         self.bindings_set()
  47.         self.populate()
  48.         self.render()
  49.  
  50.     def separator_double_click(self, column):
  51.  
  52.         def get_size(item):
  53.             frame = ttk.Frame(self.app)
  54.             text = self.item(item).get('text') if column == '#0' else self.set(item, column)
  55.             lbl = tk.Label(frame, text=text)
  56.             lbl.grid()
  57.             frame.update_idletasks()
  58.             size = lbl.winfo_width()
  59.             lbl.grid_forget()
  60.  
  61.             return size
  62.  
  63.         def walk(children):
  64.             for child in children:
  65.                 size = get_size(child) + 8
  66.                 if size + (self.levels * 20) > self.largest:
  67.                     self.largest = size
  68.  
  69.                     if len(child.split('_')) > self.levels:
  70.                         self.levels = len(child.split('_'))
  71.  
  72.                 if self.item(child)['open']:
  73.                     walk(self.get_children(child))
  74.  
  75.             return self.levels, self.largest
  76.  
  77.         self.levels = 1
  78.         self.largest = 0
  79.         depth, width = walk(self.get_children())
  80.         if column == '#0':
  81.             width += depth * 20
  82.         self.column(column, width=width)
  83.  
  84.     ######################################################################
  85.  
  86.     def get_iid(self, parent=''):
  87.         nodes = self.get_children(parent)
  88.  
  89.         idx = len(nodes)
  90.         iid = f'{parent}_!{idx}'.strip('_')
  91.  
  92.         while self.exists(iid):
  93.             idx += 1
  94.             iid = f'{parent}_!{idx}'.strip('_')
  95.         return iid
  96.  
  97.     def parent_get(self, item):
  98.         return super(Treeview, self).parent(item)
  99.  
  100.     def tags_add(self, item, tags):
  101.         if isinstance(tags, str):
  102.             tags = (tags,)
  103.  
  104.         _tags = list(self.item(item)['tags'])
  105.         _tags = [] if not _tags else _tags
  106.  
  107.         for tag in tags:
  108.             if tag not in _tags:
  109.                 _tags.append(tag)
  110.         self.item(item, tags=_tags)
  111.  
  112.     def tags_remove(self, item, tags):
  113.         if isinstance(tags, str):
  114.             tags = (tags,)
  115.  
  116.         _tags = list(self.item(item)['tags'])
  117.         for tag in tags:
  118.             if tag in _tags:
  119.                 _tags.pop(_tags.index(tag))
  120.         self.item(item, tags=_tags)
  121.  
  122.     def tags_refresh(self):
  123.         def do_refresh(children, _tag):
  124.             for child in children:
  125.                 item = self.item(child)
  126.  
  127.                 _tag = 'even' if _tag == 'odd' else 'odd'
  128.                 _tags = list(self.item(child)['tags'])
  129.                 if f'selected_{_tag}' not in item['tags']:
  130.                     _tags.append(_tag)
  131.                 self.item(child, tags=_tags)
  132.  
  133.                 if int(item['open']):
  134.                     _tag = do_refresh(self.get_children(child), _tag)
  135.  
  136.             return _tag
  137.  
  138.         self.tags_remove_all('odd', 'even', 'cut_odd', 'cut_even', 'copy_odd', 'copy_even')
  139.         do_refresh(self.get_children(), 'odd')
  140.  
  141.     def tags_remove_all(self, *tags):
  142.  
  143.         def do_remove(node):
  144.             self.tags_remove(node, tags)
  145.             for node in self.get_children(node):
  146.                 do_remove(node)
  147.  
  148.         for child in self.get_children():
  149.             do_remove(child)
  150.  
  151.     def tags_set_colors(self):
  152.         def do_refresh(children):
  153.             for child in children:
  154.                 _tags = self.item(child, 'tags')
  155.  
  156.                 if 'odd' in _tags:
  157.                     self.tags_remove(child, 'odd')
  158.                     self.tags_add(child, f'{mode}_odd')
  159.                 elif 'even' in _tags:
  160.                     self.tags_remove(child, 'even')
  161.                     self.tags_add(child, f'{mode}_even')
  162.  
  163.                 _item = self.item(child)
  164.                 nodes = self.get_children(child)
  165.                 if int(_item['open']):
  166.                     do_refresh(nodes)
  167.  
  168.         mode = 'cut' if self.tag_has('cut') else 'copy'
  169.         items = sorted(self.tag_has(mode))
  170.  
  171.         if items:
  172.             item = items.pop(0)
  173.             tags = self.item(item, 'tags')
  174.  
  175.             if 'odd' in tags:
  176.                 self.tags_remove(item, 'odd')
  177.                 self.tags_add(item, f'{mode}_odd')
  178.             elif 'even' in tags:
  179.                 self.tags_remove(item, 'even')
  180.                 self.tags_add(item, f'{mode}_even')
  181.             do_refresh(self.get_children(item))
  182.  
  183.     def cut(self, _=None):
  184.         self.copy('cut')
  185.  
  186.     def undo(self):
  187.         for k, value in self.undo_data.items():
  188.             self.content_set(k, **value)
  189.  
  190.         for item in sorted(self.detached):
  191.             parent = '' if '_' not in item else item.rsplit('_', 1)[0]
  192.             index = int(item.rsplit('_', 1).pop().lstrip('!'))
  193.             self.move(item, parent, index)
  194.  
  195.         self.popup.disable_items('undo')
  196.  
  197.     def copy(self, mode='copy'):
  198.         def get_items():
  199.             items = []
  200.             root = selections.pop(0)
  201.             items.append(root)
  202.             while selections:
  203.                 selection = selections.pop(0)
  204.                 if not selection.startswith(root):
  205.                     root = selection
  206.                     items.append(root)
  207.             return items
  208.  
  209.         def tags_update(_item):
  210.             _tag = ''
  211.             tags = list(self.item(_item, 'tags'))
  212.  
  213.             if 'odd' in tags:
  214.                 self.tags_remove(_item, 'odd')
  215.                 _tag = f'{mode}_odd'
  216.             else:
  217.                 self.tags_remove(_item, 'even')
  218.                 _tag = f'{mode}_even'
  219.  
  220.             self.tags_add(_item, _tag)
  221.             if int(self.item(_item)['open']):
  222.                 for node in self.get_children(_item):
  223.                     tags_update(node)
  224.  
  225.         selections = sorted(self.selection())
  226.         if not selections:
  227.             return
  228.  
  229.         self.tags_remove_all('cut', 'copy', 'cut_odd', 'cut_even', 'copy_odd', 'copy_even')
  230.         self.tags_refresh()
  231.         for item in get_items():
  232.             self.tags_add(item, mode)
  233.             tags_update(item)
  234.  
  235.         self.pointer_x, self.pointer_y = self.winfo_toplevel().winfo_pointerxy()
  236.  
  237.     def paste(self):
  238.         def get_items(parent):
  239.             item_names = []
  240.             for c in self.get_children(parent):
  241.                 item_names.append(self.item(c, 'text'))
  242.             return item_names
  243.  
  244.         def add_nodes(parent, _node):
  245.             _item = self.item(_node)
  246.  
  247.             if self.has_name(parent, _item['text']):
  248.                 _results = self.rename(_item['text'])
  249.                 _text = _results.get('text', '')
  250.  
  251.                 while _results.get('text', '') in get_items(parent):
  252.                     _results = self.rename(_item['text'])
  253.  
  254.                 if 'text' not in _results:
  255.                     return 'cancel'
  256.                 _item['text'] = _results['text']
  257.  
  258.             _iid = self.append(parent, _item['text'], _item['values'], open=_item['open'])
  259.  
  260.             if 'cut' in _item['tags']:
  261.                 self.item(_iid, tags=(self.item(_iid, 'tags'), 'copy'))
  262.  
  263.             for child in self.get_children(_node):
  264.                 add_nodes(_iid, child)
  265.  
  266.         selections = self.selection()
  267.         if not selections:
  268.             return
  269.         selection = selections[0]
  270.  
  271.         mode = 'cut' if self.tag_has('cut') else 'copy'
  272.         items = sorted(self.tag_has(mode))
  273.         if items:
  274.             if selection.startswith(items[0]):
  275.                 return
  276.  
  277.             for item in items:
  278.                 if add_nodes(selection, item) == 'cancel':
  279.                     self.tags_refresh()
  280.                     return
  281.  
  282.             if mode == 'cut':
  283.                 self.delete(*items)
  284.  
  285.             self.tags_refresh()
  286.             self.tags_set_colors()
  287.  
  288.     def rename(self, value=''):
  289.         def after_do_ok(dialog):
  290.             def text_get(_text):
  291.                 while not _text:
  292.                     _data = entry_value_get()
  293.                     if 'text' not in _data:
  294.                         return
  295.                     _text = _data['text']
  296.                 return _text
  297.  
  298.             def item_name_get():
  299.                 _dlg = self.app.dialog_manager.dialog(dlg_key, **{
  300.                     'options': {
  301.                         'value': text,
  302.                         'message': f'The name ({text}) already exists.\nPlease enter a different name and try again.',
  303.                         'position': (self.x_root, self.y_root),
  304.                     },
  305.                 })
  306.                 self.x_root, self.y_root = _dlg.results['geometry'].split('+', 1).pop().split('+')
  307.                 return _dlg.results
  308.  
  309.             def entry_value_get():
  310.                 _dlg = self.app.dialog_manager.dialog(dlg_key, **{
  311.                     'options': {
  312.                         'value': '',
  313.                         'message': 'You have not entered a name.\nPlease enter a name and try again.',
  314.                         'position': (self.x_root, self.y_root),
  315.                     },
  316.                 })
  317.                 self.x_root, self.y_root = _dlg.results['geometry'].split('+', 1).pop().split('+')
  318.                 return _dlg.results
  319.  
  320.             text = dialog.results.get('text', '').strip(' ')
  321.             target = self.selection()[0]
  322.  
  323.             text = text_get(text)
  324.  
  325.             while self.has_name(self.parent_get(target), text):
  326.                 data = item_name_get()
  327.                 if 'text' not in data:
  328.                     return
  329.                 text = text_get(data['text'])
  330.  
  331.         def before_exit(dialog):
  332.             results = dialog.results
  333.             self.x_root, self.y_root = results['geometry'].split('+', 1).pop().split('+')
  334.  
  335.         selection = self.selection()[0]
  336.  
  337.         target_item = self.item(selection)
  338.  
  339.         if not self.x_root or not self.y_root:
  340.             self.x_root, self.y_root = \
  341.                 self.winfo_rootx()+self.bbox(selection)[0], self.winfo_rooty()+self.bbox(selection)[1]
  342.             font = tkfont.nametofont('TkTextFont')
  343.  
  344.             self.x_root = self.x_root + self.column('#0')['width']
  345.             self.y_root = self.y_root + font.metrics('linespace')
  346.  
  347.         dlg_key = 'rename'
  348.         while True:
  349.             dlg = self.app.dialog_manager.dialog(dlg_key, **{
  350.                 'options': {
  351.                     'value': value if value else target_item['text'],
  352.                     'message': f'Enter a new name for the {target_item["values"][0].lower()}.',
  353.                     'position': (self.x_root, self.y_root),
  354.                 },
  355.                 'callbacks': {
  356.                     'after_do_ok': after_do_ok,
  357.                     'before_exit': before_exit,
  358.                 },
  359.             })
  360.             if 'text' not in dlg.results or ('text' in dlg.results and dlg.results['text']):
  361.                 break
  362.  
  363.         return dlg.results
  364.  
  365.     def insert(self, parent='', index=tk.END, **kwargs):
  366.         kwargs.pop('iid', None)
  367.         kwargs.pop('image', None)
  368.         unique = kwargs.pop('unique', True)
  369.  
  370.         iid = self.get_iid(parent)
  371.         try:
  372.             if unique:
  373.                 for child in self.get_children(parent):
  374.                     if not kwargs['text'] or kwargs['text'] == self.item(child)['text']:
  375.                         raise NameError()
  376.  
  377.             item = super(Treeview, self).insert(parent, index, iid=iid, **kwargs)
  378.             self.content_set(iid, **kwargs)
  379.  
  380.             return item
  381.  
  382.         except NameError:
  383.             print(555555555555)
  384.             return False
  385.  
  386.     def append(self, parent, text, values, **kwargs):
  387.         kwargs['text'] = text
  388.         kwargs['values'] = values
  389.  
  390.         return self.insert(parent, **kwargs)
  391.  
  392.     def remove(self, iid=None):
  393.         def do_remove(uri):
  394.             def walk(_content):
  395.                 data = _content.copy()
  396.                 for key in data.keys():
  397.                     if key == target:
  398.                         self.undo_data.update({key: _content[key]})
  399.                         del _content[key]
  400.                         break
  401.                     if isinstance(data[key], dict):
  402.                         walk(_content[key])
  403.  
  404.             target = uri.rsplit('/').pop()
  405.  
  406.             content = self.setting_get('content', {})
  407.             walk(content)
  408.             self.setting_set('content', content)
  409.  
  410.         selections = self.selection()
  411.         if not iid and not selections:
  412.             return
  413.         elif iid:
  414.             selections = [iid]
  415.  
  416.         for selection in sorted(selections):
  417.             do_remove(tvi2uri(selection))
  418.  
  419.         selected = selections[0]
  420.         _prev = self.prev(selected)
  421.         _next = self.next(selected)
  422.         _parent = super(Treeview, self).parent(selected)
  423.  
  424.         self.detached = []
  425.         for selection in sorted(selections, reverse=True):
  426.             self.detached.append(selection)
  427.             self.detach(selection)
  428.  
  429.         if _next and self.exists(_next):
  430.             self.selection_set(_next)
  431.             self.focus(_next)
  432.         elif _prev and self.exists(_prev) and not self.item(_prev)['open']:
  433.             self.selection_set(_prev)
  434.             self.focus(_prev)
  435.         else:
  436.             if _parent and not _prev:
  437.                 node = _parent
  438.             elif self.get_children(_prev):
  439.                 node = list(self.get_children(_prev)).pop()
  440.             else:
  441.                 return
  442.  
  443.             if node:
  444.                 self.selection_set(node)
  445.  
  446.         self.refresh()
  447.         if self.undo_data:
  448.             self.popup.enable_items('undo')
  449.  
  450.         self.tags_refresh()
  451.         self.tags_set_colors()
  452.  
  453.     def escape(self, _):
  454.         self.tags_remove_all('cut', 'copy', 'cut_odd', 'cut_even', 'copy_odd', 'copy_even')
  455.         self.selection_set('')
  456.         self.tags_refresh()
  457.  
  458.     def expand(self, _):
  459.         def refresh():
  460.             self.tags_refresh()
  461.         self.after(0, refresh)
  462.  
  463.         def set_colors():
  464.             tags = self.tag_has('copy')
  465.             if not tags:
  466.                 tags = self.tag_has('cut')
  467.  
  468.             if tags:
  469.                 self.tags_set_colors()
  470.         self.after(0, set_colors)
  471.  
  472.     def actions(self, event):
  473.         region = self.identify('region', event.x, event.y)
  474.  
  475.         if region == 'tree':
  476.             item = self.identify('item', event.x, event.y)
  477.  
  478.     def refresh(self):
  479.         font = tkfont.nametofont('TkTextFont')
  480.         self.style.configure('Treeview', rowheight=font.metrics('linespace') + 5)
  481.         self.style.configure("Treeview.Heading", font=tkfont.nametofont('TkHeadingFont'))
  482.         self.column_widths_set()
  483.  
  484.     def collapse(self, _):
  485.         def refresh():
  486.             self.tags_refresh()
  487.         self.after(0, refresh)
  488.  
  489.         def set_colors():
  490.             tags = self.tag_has('copy')
  491.             if not tags:
  492.                 tags = self.tag_has('cut')
  493.  
  494.             if tags:
  495.                 self.tags_set_colors()
  496.         self.after(0, set_colors)
  497.  
  498.     def populate(self):
  499.         def walk(_parent, _data, _content):
  500.             _idx = 0
  501.  
  502.             for _, _value in sorted(_data.items()):
  503.                 if isinstance(_value, dict):
  504.                     _iid = f'{_parent}_!{_idx}'
  505.                     _idx += 1
  506.                     _kwargs = {
  507.                         'text': _value.get('text', ''),
  508.                         'image': _value.get('image', None),
  509.                         'values': _value.get('values', []),
  510.                         'open': _value.get('open', 0),
  511.                         'tags': _value.get('tags', []),
  512.                     }
  513.                     _content[_iid] = _kwargs
  514.                     self.insert(_parent, tk.END, iid=_iid, **_kwargs)
  515.                     walk(_iid, _value, _content[_iid])
  516.  
  517.         idx = 0
  518.         parent = ''
  519.         content = {}
  520.  
  521.         for _, value in sorted(self.setting_get('content', {}).items()):
  522.             if isinstance(value, dict):
  523.                 iid = f'{parent}_!{idx}'.strip("_")
  524.                 idx += 1
  525.                 kwargs = {
  526.                     'text': value.get('text', ''),
  527.                     'image': value.get('image', None),
  528.                     'values': value.get('values', []),
  529.                     'open': value.get('open', 0),
  530.                     'tags': value.get('tags', []),
  531.                 }
  532.                 self.insert(parent, tk.END, iid=iid, **kwargs)
  533.                 content[iid] = kwargs
  534.                 walk(iid, value, content[iid])
  535.  
  536.         self.setting_set('content', content)
  537.         self.refresh()
  538.  
  539.         self.tags_refresh()
  540.  
  541.     def control_a(self):
  542.         def walk(children):
  543.             for child in children:
  544.                 self.selection_add(child)
  545.                 _children = self.get_children(child)
  546.                 if _children:
  547.                     walk(_children)
  548.  
  549.         selections = self.selection()
  550.         if selections:
  551.             walk(self.get_children(selections[0]))
  552.  
  553.     def has_name(self, parent, name):
  554.         for iid in self.get_children(parent):
  555.             if name == self.item(iid)['text']:
  556.                 return True
  557.         return False
  558.  
  559.     def content_set(self, iid, **kwargs):
  560.         def do_set(data):
  561.             for key, value in data.items():
  562.                 if not isinstance(value, dict):
  563.                     continue
  564.  
  565.                 elif key == iid:
  566.                     value.update(kwargs)
  567.                     return 'break'
  568.  
  569.                 elif key == parent and iid not in value:
  570.                     value[iid] = kwargs
  571.                     return 'break'
  572.  
  573.                 if do_set(value) == 'break':
  574.                     break
  575.  
  576.         content = self.setting_get('content', {})
  577.         parent = '' if '_' not in iid else iid.rsplit('_', 1)[0]
  578.  
  579.         if '_' not in iid and iid not in content:
  580.             content[iid] = kwargs
  581.         else:
  582.             do_set(content)
  583.  
  584.     def content_get(self, iid=None):
  585.         def do_get(data):
  586.             for _key, _value in data.items():
  587.                 if not isinstance(_value, dict):
  588.                     continue
  589.                 if _key == iid:
  590.                     return _value
  591.                 do_get(_value)
  592.             return None
  593.  
  594.         content = self.setting_get('content', {})
  595.         if not iid or not content:
  596.             return content
  597.         elif iid in content:
  598.             _data = {}
  599.             for key, value in content[iid].items():
  600.                 if not isinstance(value, dict):
  601.                     _data[key] = value
  602.             return _data
  603.         return do_get(content)
  604.  
  605.     def bindings_set(self):
  606.  
  607.         def shift_up(_):
  608.             cur_item = self.focus()
  609.             get_parent = super(Treeview, self).parent
  610.  
  611.             if not get_parent(cur_item) and not self.index(cur_item):
  612.                 return 'break'
  613.  
  614.             if not self.direction:
  615.                 self.direction = 'up'
  616.  
  617.             def prev_item(node):
  618.                 _prev = self.prev(node)
  619.                 if not _prev:
  620.                     _prev = get_parent(node)
  621.                 elif self.get_children(_prev) and self.item(_prev)['open']:
  622.                     def walk(_node):
  623.                         if self.get_children(_node) and self.item(_node)['open']:
  624.                             return walk(list(self.get_children(_node)).pop())
  625.                         return _node
  626.                     _prev = walk(list(self.get_children(_prev)).pop())
  627.  
  628.                 return _prev
  629.  
  630.             item = prev_item(cur_item)
  631.             if self.direction == 'up':
  632.                 if item:
  633.                     self.selection_add(item)
  634.                     self.focus(item)
  635.                 else:
  636.                     _parent = get_parent(item)
  637.                     if not self.item(_parent)['open']:
  638.                         item = _parent
  639.             else:
  640.                 self.selection_remove(cur_item)
  641.                 self.focus(item)
  642.  
  643.             if item == self.root_selection:
  644.                 self.direction = None
  645.  
  646.             return 'break'
  647.  
  648.         def shift_down(_):
  649.             cur_item = self.focus()
  650.  
  651.             if not self.direction:
  652.                 self.direction = 'down'
  653.  
  654.             get_parent = super(Treeview, self).parent
  655.  
  656.             def next_item(node):
  657.                 _next = self.next(node)
  658.  
  659.                 if self.get_children(node) and self.item(node)['open']:
  660.                     _next = self.get_children(node)[0]
  661.                 elif not _next:
  662.                     def walk(_node):
  663.                         _parent = get_parent(_node)
  664.                         _item = self.next(_parent)
  665.                         if not _item and get_parent(_parent):
  666.                             return walk(get_parent(_parent))
  667.                         return _item
  668.  
  669.                     if get_parent(cur_item):
  670.                         _next = walk(cur_item)
  671.  
  672.                 return _next
  673.  
  674.             item = next_item(cur_item)
  675.  
  676.             if not item:
  677.                 return
  678.  
  679.             if self.direction == 'down':
  680.                 self.selection_add(item)
  681.                 self.focus(item)
  682.             else:
  683.                 self.selection_remove(cur_item)
  684.                 self.focus(cur_item)
  685.  
  686.             if item == self.root_selection and item != self.focus():
  687.                 self.direction = None
  688.  
  689.             self.focus(item)
  690.  
  691.             return 'break'
  692.  
  693.         def control_a(_):
  694.             def walk(children):
  695.                 for child in children:
  696.                     self.selection_add(child)
  697.                     _children = self.get_children(child)
  698.                     if _children:
  699.                         walk(_children)
  700.             walk(self.get_children())
  701.  
  702.         def control_x(_):
  703.             self.copy()
  704.             self.remove()
  705.  
  706.         def control_c(_):
  707.             self.copy()
  708.  
  709.         def control_v(_):
  710.             for selection in self.selection():
  711.                 self.paste()
  712.  
  713.         def control_z(e):
  714.             tree = e.widget
  715.             tree.selection_set(super(Treeview, self).parent(tree.focus()))
  716.             # self.paste()
  717.  
  718.         def key_press(event):
  719.             tree = event.widget
  720.             if 'Shift' in event.keysym:
  721.                 if tree.selection() and len(tree.selection()) <= 1:
  722.                     self.root_selection = tree.focus()
  723.  
  724.         def header_dbl_click(event):
  725.             region = self.identify("region", event.x, event.y)
  726.             if region == "separator":
  727.                 column_number = self.identify_column(event.x)
  728.                 self.separator_double_click(column_number)
  729.  
  730.         bindings = {
  731.             '<Key>': key_press,
  732.             '<Control-a>': control_a,
  733.             '<Control-x>': control_x,
  734.             '<Control-c>': control_c,
  735.             '<Control-v>': control_v,
  736.             '<Control-z>': control_z,
  737.             # '<Up>': self.clear_selections,
  738.             # '<Down>': self.clear_selections,
  739.             '<Escape>': self.escape,
  740.             '<Button-1>': self.actions,
  741.             '<Double-1>': header_dbl_click,
  742.             '<Shift-Up>': shift_up,
  743.             '<Shift-Down>': shift_down,
  744.             '<<TreeviewOpen>>': self.expand,
  745.             '<<TreeviewClose>>': self.collapse,
  746.             '<ButtonRelease-1>': self.column_widths_update,
  747.         }
  748.         for command, callback in bindings.items():
  749.             self.bindings[command] = self.bind(command, callback)
  750.  
  751.     def column_widths_set(self):
  752.         column_widths = self.setting_get('column_widths')
  753.         if column_widths:
  754.             for idx in range(len(self.cget('columns')) + 1):
  755.                 self.column(f'#{idx}', width=column_widths[idx])
  756.  
  757.     def column_widths_update(self, _=None):
  758.         values = []
  759.         for idx in range(len(self.cget('columns')) + 1):
  760.             values.append(self.column(f'#{idx}', 'width'))
  761.         self.setting_set('column_widths', values)
  762.  
  763.     def scrollbars_add(self, xscroll, yscroll):
  764.         if not xscroll and not yscroll:
  765.             return
  766.  
  767.         self.xscroll, self.yscroll = xscroll, yscroll
  768.  
  769.         if xscroll:
  770.             sb = self.parent.add_element('scrollbar1', **scrollbar1)
  771.             sb.parent = self
  772.             sb.configure(command=self.xview)
  773.             self.configure(xscrollcommand=sb.set_scroll)
  774.  
  775.         if yscroll:
  776.             sb = self.parent.add_element('scrollbar0', **scrollbar0)
  777.             sb.parent = self
  778.             sb.configure(command=self.yview)
  779.             self.configure(yscrollcommand=sb.set_scroll)
  780.  
  781.     def do_scroll(self, event):
  782.         wdg = event.widget
  783.  
  784.         options = wdg.options_get()
  785.         if wdg.type == 'Scrollbar' and options.get('orient', tk.HORIZONTAL) == tk.HORIZONTAL:
  786.             event.state = (event.state | 1)
  787.  
  788.         c_width, c_height = self.winfo_width(), self.winfo_height()
  789.  
  790.         autosave_state = self.setting_get('autosave_state', True)
  791.  
  792.         if event.state & 0x1 and self.xscroll:
  793.             if event.num == 4:
  794.                 if c_width <= self.winfo_reqwidth():
  795.                     self.xview_scroll(-1, tk.UNITS)
  796.             elif event.num == 5:
  797.                 self.xview_scroll(1, tk.UNITS)
  798.  
  799.             if autosave_state:
  800.                 self.setting_set('xview', self.xview())
  801.  
  802.         elif self.yscroll:
  803.             if event.num == 4:
  804.                 if c_height <= self.winfo_reqheight():
  805.                     self.yview_scroll(-1, tk.UNITS)
  806.             elif event.num == 5:
  807.                 self.yview_scroll(1, tk.UNITS)
  808.  
  809.             if autosave_state:
  810.                 self.setting_set('yview', self.yview())
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement