from tkinter import ttk
import tkinter as tk

class ScrolledWindow(tk.Frame):
    """
    1. Master widget gets scrollbars and a canvas. Scrollbars are connected
    to canvas scrollregion.

    2. self.scrollwindow is created and inserted into canvas

    Usage Guideline:
    Assign any widgets as children of <ScrolledWindow instance>.scrollwindow
    to get them inserted into canvas

    __init__(self, parent, canv_w = 400, canv_h = 400, *args, **kwargs)
    docstring:
    Parent = master of scrolled window
    canv_w - width of canvas
    canv_h - height of canvas

    """

    def __init__(self, parent, canv_w = 400, canv_h = 400, *args, **kwargs):
        """Parent = master of scrolled window
        canv_w - width of canvas
        canv_h - height of canvas

       """
        super().__init__(parent, *args, **kwargs)

        self.parent = parent

        self.is_updating = False # used in order to ask preferencies only once

        # creating a scrollbars
        #self.xscrlbr = ttk.Scrollbar(self.parent, orient = 'horizontal')
        #self.xscrlbr.grid(column = 0, row = 1, sticky = 'ew', columnspan = 2)
        self.yscrlbr = ttk.Scrollbar(self.parent)
        self.yscrlbr.grid(column = 1, row = 0, sticky = 'ns')
        # creating a canvas
        self.canv = tk.Canvas(self.parent)
        self.canv.config(relief = 'flat',
                         width = 10,
                         heigh = 10, bd = 2)
        # placing a canvas into frame
        self.canv.grid(column = 0, row = 0, sticky = 'nsew')
        # accociating scrollbar comands to canvas scroling
        #self.xscrlbr.config(command = self.canv.xview)
        self.yscrlbr.config(command = self.canv.yview)

        self.update_colors()
        # creating a frame to inserto to canvas
        self.scrollwindow = ttk.Frame(self.parent, style="ScrollWindow.TLabel")

        self.canv.create_window(0, 0, window = self.scrollwindow, anchor = 'nw')

        self.canv.config(#xscrollcommand = self.xscrlbr.set,
                         yscrollcommand = self.yscrlbr.set,
                         scrollregion = (0, 0, 100, 100))

        self.yscrlbr.lift(self.scrollwindow)
        #self.xscrlbr.lift(self.scrollwindow)
        self.scrollwindow.bind('<Configure>', self._configure_window)
        self.scrollwindow.bind('<Enter>', self._bound_to_mousewheel)
        self.scrollwindow.bind('<Leave>', self._unbound_to_mousewheel)

        return

    def update_colors(self):
        # used for portability between tk and ttk
        test_style = ttk.Style()
        test_style.configure("ScrollWindow.TLabel", foreground=self.parent.config["color"]["foreground"], background=self.parent.config["color"]["background"])

    def destroyAll(self):
        self.yscrlbr.destroy()
        self.canv.destroy()
        self.scrollwindow.destroy()
        self.destroy()

    def _bound_to_mousewheel(self, event):
        #self.canv.bind_all("<MouseWheel>", self._on_mousewheel)
        self.canv.bind_all("<Button-4>", self._on_mousewheel)
        self.canv.bind_all("<Button-5>", self._on_mousewheel)


    def _unbound_to_mousewheel(self, event):
        #self.canv.unbind_all("<MouseWheel>")
        self.canv.unbind_all("<Button-4>")
        self.canv.unbind_all("<Button-5>")

    def _on_mousewheel(self, event):
        if not self.is_updating:
            self.is_updating = True
            self.parent.ask_preferencies("Scrolling")
            self.is_updating = False
        if event.num == 4:
            if self.parent.config["Scrolling"]["direction"] == "normal":
                self.canv.yview_scroll(-1, "units")
            elif self.parent.config["Scrolling"]["direction"] == "reverse":
                self.canv.yview_scroll(1, "units")
        elif event.num == 5:
            if self.parent.config["Scrolling"]["direction"] == "normal":
                self.canv.yview_scroll(1, "units")
            elif self.parent.config["Scrolling"]["direction"] == "reverse":
                self.canv.yview_scroll(-1, "units")
        #self.canv.yview_scroll(int(-1*(event.delta/120)), "units")

    def _configure_window(self, event):
        # update the scrollbars to match the size of the inner frame
        size = (self.scrollwindow.winfo_reqwidth(), self.scrollwindow.winfo_reqheight())
        self.canv.config(scrollregion='0 0 %s %s' % size)
        if self.scrollwindow.winfo_reqwidth() != self.canv.winfo_width():
            # update the canvas's width to fit the inner frame
            self.canv.config(width = self.scrollwindow.winfo_reqwidth())
        if self.scrollwindow.winfo_reqheight() != self.canv.winfo_height():
            # update the canvas's width to fit the inner frame
            self.canv.config(height = self.scrollwindow.winfo_reqheight())
