178 lines
5.7 KiB
Python
178 lines
5.7 KiB
Python
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()
|
|
|