# All credit to https://stackoverflow.com/questions/46571448/tkinter-and-a-html-file - thanks DELICA - https://stackoverflow.com/users/7027346/delica

from cefpython3 import cefpython as cef
import ctypes

try:
    import tkinter as tk
    from tkinter import messagebox
except ImportError:
    import Tkinter as tk
import sys
import platform
import logging as _logging

# Fix for PyCharm hints warnings
WindowUtils = cef.WindowUtils()

# Platforms
WINDOWS = (platform.system() == "Windows")
LINUX = (platform.system() == "Linux")
MAC = (platform.system() == "Darwin")

# Globals
logger = _logging.getLogger("tkinter_.py")
url = "localhost:8050/"

class MainFrame(tk.Frame):

    def __init__(self, root):
        self.closing = False
        self.browser = None

        # Root
        root.geometry("900x640")
        tk.Grid.rowconfigure(root, 0, weight=1)
        tk.Grid.columnconfigure(root, 0, weight=1)

        # MainFrame
        tk.Frame.__init__(self, root)
        self.master.title('SimBA Dashboard')
        self.master.protocol("WM_DELETE_WINDOW", self.on_close)
        self.bind("<Configure>", self.on_configure)
        self.bind("<FocusIn>", self.on_focus_in)
        self.bind("<FocusOut>", self.on_focus_out)
        self.focus_set()

        # Pack MainFrame
        self.pack(fill=tk.BOTH, expand=tk.YES)

    def embed_browser(self):
        window_info = cef.WindowInfo()
        rect = [0, 0, self.winfo_width(), self.winfo_height()]
        window_info.SetAsChild(self.get_window_handle(), rect)
        self.browser = cef.CreateBrowserSync(window_info,
                                             url=url) #todo
        assert self.browser
        self.browser.SetClientHandler(LoadHandler(self))
        self.browser.SetClientHandler(FocusHandler(self))
        self.message_loop_work()

    def get_window_handle(self):
        if self.winfo_id() > 0:
            return self.winfo_id()
        else:
            raise Exception("Couldn't obtain window handle")

    def message_loop_work(self):
        cef.MessageLoopWork()
        self.after(10, self.message_loop_work)

    def on_configure(self, event):

        width = event.width
        height = event.height
        if self.browser:
            if WINDOWS:
                ctypes.windll.user32.SetWindowPos(
                    self.browser.GetWindowHandle(), 0,
                    0, 0, width, height, 0x0002)
            elif LINUX:
                self.browser.SetBounds(0, 0, width, height)
            self.browser.NotifyMoveOrResizeStarted()
        if not self.browser:
            self.embed_browser()

    def on_focus_in(self, _):
        logger.debug("BrowserFrame.on_focus_in")
        if self.browser:
            self.browser.SetFocus(True)
            self.focus_set()

    def on_focus_out(self, _):
        logger.debug("BrowserFrame.on_focus_out")
        if self.browser:
            self.browser.SetFocus(False)

    def on_close(self):
        if self.browser:
            self.browser.CloseBrowser(True)
            self.clear_browser_references()
        self.destroy()
        self.master.destroy()

    def get_browser(self):
        if self.browser:
            return self.browser
        return None

    def clear_browser_references(self):
        self.browser = None


class LoadHandler(object):

    def __init__(self, browser_frame):
        self.browser_frame = browser_frame


class FocusHandler(object):

    def __init__(self, browser):
        self.browser = browser

    def OnTakeFocus(self, next_component, **_):
        logger.debug("FocusHandler.OnTakeFocus, next={next}"
                     .format(next=next_component))

    def OnSetFocus(self, source, **_):
        logger.debug("FocusHandler.OnSetFocus, source={source}"
                     .format(source=source))
        return False

    def OnGotFocus(self, **_):
        """Fix CEF focus issues (#255). Call browser frame's focus_set
           to get rid of type cursor in url entry widget."""
        logger.debug("FocusHandler.OnGotFocus")
        self.browser.focus_set()


# if __name__ == '__main__':
logger.setLevel(_logging.INFO)
stream_handler = _logging.StreamHandler()
formatter = _logging.Formatter("[%(filename)s] %(message)s")
stream_handler.setFormatter(formatter)
logger.addHandler(stream_handler)
logger.info("CEF Python {ver}".format(ver=cef.__version__))
logger.info("Python {ver} {arch}".format(
        ver=platform.python_version(), arch=platform.architecture()[0]))
logger.info("Tk {ver}".format(ver=tk.Tcl().eval('info patchlevel')))
assert cef.__version__ >= "55.3", "CEF Python v55.3+ required to run this"
sys.excepthook = cef.ExceptHook  # To shutdown all CEF processes on error
root = tk.Tk()
app = MainFrame(root)
def on_closing():
    if messagebox.askokcancel("Quit", "Do you want to quit?"):
        root.destroy()

root.protocol("WM_DELETE_WINDOW", on_closing)

# Tk must be initialized before CEF otherwise fatal error (Issue #306)
cef.Initialize()
root.mainloop()
# app.mainloop()
cef.Shutdown()

[((418, 435), 'cefpython3.cefpython.WindowUtils', 'cef.WindowUtils', ([], {}), '()\n', (433, 435), True, 'from cefpython3 import cefpython as cef\n'), ((589, 622), 'logging.getLogger', '_logging.getLogger', (['"""tkinter_.py"""'], {}), "('tkinter_.py')\n", (607, 622), True, 'import logging as _logging\n'), ((4152, 4176), 'logging.StreamHandler', '_logging.StreamHandler', ([], {}), '()\n', (4174, 4176), True, 'import logging as _logging\n'), ((4189, 4237), 'logging.Formatter', '_logging.Formatter', (['"""[%(filename)s] %(message)s"""'], {}), "('[%(filename)s] %(message)s')\n", (4207, 4237), True, 'import logging as _logging\n'), ((4711, 4718), 'Tkinter.Tk', 'tk.Tk', ([], {}), '()\n', (4716, 4718), True, 'import Tkinter as tk\n'), ((4964, 4980), 'cefpython3.cefpython.Initialize', 'cef.Initialize', ([], {}), '()\n', (4978, 4980), True, 'from cefpython3 import cefpython as cef\n'), ((5014, 5028), 'cefpython3.cefpython.Shutdown', 'cef.Shutdown', ([], {}), '()\n', (5026, 5028), True, 'from cefpython3 import cefpython as cef\n'), ((460, 477), 'platform.system', 'platform.system', ([], {}), '()\n', (475, 477), False, 'import platform\n'), ((501, 518), 'platform.system', 'platform.system', ([], {}), '()\n', (516, 518), False, 'import platform\n'), ((538, 555), 'platform.system', 'platform.system', ([], {}), '()\n', (553, 555), False, 'import platform\n'), ((4766, 4820), 'tkinter.messagebox.askokcancel', 'messagebox.askokcancel', (['"""Quit"""', '"""Do you want to quit?"""'], {}), "('Quit', 'Do you want to quit?')\n", (4788, 4820), False, 'from tkinter import messagebox\n'), ((820, 859), 'Tkinter.Grid.rowconfigure', 'tk.Grid.rowconfigure', (['root', '(0)'], {'weight': '(1)'}), '(root, 0, weight=1)\n', (840, 859), True, 'import Tkinter as tk\n'), ((868, 910), 'Tkinter.Grid.columnconfigure', 'tk.Grid.columnconfigure', (['root', '(0)'], {'weight': '(1)'}), '(root, 0, weight=1)\n', (891, 910), True, 'import Tkinter as tk\n'), ((940, 969), 'Tkinter.Frame.__init__', 'tk.Frame.__init__', (['self', 'root'], {}), '(self, root)\n', (957, 969), True, 'import Tkinter as tk\n'), ((1381, 1397), 'cefpython3.cefpython.WindowInfo', 'cef.WindowInfo', ([], {}), '()\n', (1395, 1397), True, 'from cefpython3 import cefpython as cef\n'), ((1547, 1590), 'cefpython3.cefpython.CreateBrowserSync', 'cef.CreateBrowserSync', (['window_info'], {'url': 'url'}), '(window_info, url=url)\n', (1568, 1590), True, 'from cefpython3 import cefpython as cef\n'), ((2036, 2057), 'cefpython3.cefpython.MessageLoopWork', 'cef.MessageLoopWork', ([], {}), '()\n', (2055, 2057), True, 'from cefpython3 import cefpython as cef\n'), ((4425, 4450), 'platform.python_version', 'platform.python_version', ([], {}), '()\n', (4448, 4450), False, 'import platform\n'), ((4457, 4480), 'platform.architecture', 'platform.architecture', ([], {}), '()\n', (4478, 4480), False, 'import platform\n'), ((4520, 4528), 'Tkinter.Tcl', 'tk.Tcl', ([], {}), '()\n', (4526, 4528), True, 'import Tkinter as tk\n')]