import gi

gi.require_version("Gtk", "3.0")
gi.require_version("Gdk", "3.0")

from gi.repository import Gdk, Gtk


class ControlPanel(Gtk.Box):
    def __init__(self):
        super().__init__(orientation=Gtk.Orientation.VERTICAL, spacing=5)
        # Place the control panel in the top right
        self.set_halign(Gtk.Align.END)
        self.set_valign(Gtk.Align.START)

        # Add the .control-panel CSS class to this widget
        context = self.get_style_context()
        context.add_class("control-panel")

    def add_group(self, group):
        self.pack_start(group, False, False, 0)


class ControlPanelGroup(Gtk.Expander):
    def __init__(self, title: str):
        Gtk.Expander.__init__(self, label=title)
        self._inner = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)

        # Set the size request to 200 pixels wide
        self.set_size_request(200, -1)

        # Add a bit of margin after the header
        self._inner.set_margin_top(5)

        self.add(self._inner)

    def add_row(self, widget):
        self._inner.pack_start(widget, False, False, 0)


class MyControlPanel(ControlPanel):
    def __init__(self):
        super().__init__()
        self._first_panel = ControlPanelGroup("Some Buttons")
        self._first_panel.add_row(Gtk.Button(label="Button 1"))
        self._first_panel.add_row(Gtk.Button(label="Button 2"))
        self.add_group(self._first_panel)

        self._second_panel = ControlPanelGroup("Extra Settings")
        self._second_panel.add_row(Gtk.Button(label="Button 3"))
        self._second_panel.add_row(Gtk.Button(label="Button 4"))
        self._second_panel.add_row(Gtk.CheckButton.new_with_label("First checkbox"))
        self._second_panel.add_row(Gtk.CheckButton.new_with_label("Second checkbox"))

        combo = Gtk.ComboBoxText()
        combo.append("first", "First Choice")
        combo.append("second", "Second Choice")
        combo.append("third", "Third Choice")
        combo.append("forth", "This one is quite long")
        combo.set_active_id("first")
        self._second_panel.add_row(combo)

        self.add_group(self._second_panel)


class MapEditor(Gtk.DrawingArea):
    def __init__(self):
        super().__init__()
        self.set_events(
            Gdk.EventMask.BUTTON_PRESS_MASK
            | Gdk.EventMask.BUTTON_RELEASE_MASK
            | Gdk.EventMask.POINTER_MOTION_MASK
        )

        self._camera_x = 0  # The X coordinate of the camera
        self._camera_y = 0  # The Y coordinate of the camera
        self._mouse_x = 0  # The X coordinate of the pointer
        self._mouse_y = 0  # The Y coordinate of the pointer
        self._button = None  # The currently held mouse button

        # Connect to the draw and mouse events
        self.connect("draw", self.on_draw)
        self.connect("button-press-event", self.on_button_press_event)
        self.connect("button-release-event", self.on_button_release_event)
        self.connect("motion-notify-event", self.on_motion_notify_event)

    def on_button_press_event(self, widget, event):
        self._mouse_x = event.x
        self._mouse_y = event.y
        self._button = event.button

    def on_button_release_event(self, widget, event):
        self._mouse_x = 0
        self._mouse_y = 0
        self._button = None

    def on_motion_notify_event(self, widget, event):
        if self._button == Gdk.BUTTON_SECONDARY:
            self._camera_x += event.x - self._mouse_x
            self._camera_y += event.y - self._mouse_y
            self._mouse_x = event.x
            self._mouse_y = event.y
            self.queue_draw()

    def on_draw(self, widget, context):
        # Get the width and height of the widget
        width = self.get_allocated_width()
        height = self.get_allocated_height()

        # Render a rectangle for the background of the editor
        context.set_source_rgb(0.11, 0.11, 0.11)
        context.rectangle(0, 0, width, height)
        context.fill()

        # Render our grids
        context.set_line_width(1)
        for color, step in [(0.2, 10), (0.3, 100)]:
            context.set_source_rgb(color, color, color)
            y = int(self._camera_y % step) + 0.5
            while y < height:
                context.move_to(0, y)
                context.line_to(width, y)
                y += step
            x = int(self._camera_x % step) + 0.5
            while x < width:
                context.move_to(x, 0)
                context.line_to(x, height)
                x += step
            context.stroke()


class MainWindow(Gtk.Window):
    def __init__(self):
        super().__init__()

        self.set_title("Collapsible Controls Overlay Demo")

        # Set the default window size to 800x800
        self.set_default_size(800, 800)
        # When our window is destroyed, exit the main event loop
        self.connect("destroy", Gtk.main_quit)

        # Create our map editor and control panel instances
        self._editor = MapEditor()
        self._controls = MyControlPanel()

        # Create the overlay widget
        self._overlay = Gtk.Overlay()

        # Add our editor and control panel as overlays
        self._overlay.add_overlay(self._editor)
        self._overlay.add_overlay(self._controls)

        # Add the overlay as the immediate child of the window
        self.add(self._overlay)


def install_css():
    screen = Gdk.Screen.get_default()
    provider = Gtk.CssProvider()
    provider.load_from_data(
        b"""
      .control-panel {
        background-color: rgba(255,255,255,0.8);
        padding: 4px;
        border-bottom-left-radius: 4px;
      }
      """
    )
    Gtk.StyleContext.add_provider_for_screen(screen, provider, 600)


install_css()
window = MainWindow()
window.show_all()
Gtk.main()

