Skip to content

Instantly share code, notes, and snippets.

@eldorplus
Forked from BlakeRain/collapse-controls.py
Created May 27, 2021 22:12
Show Gist options
  • Save eldorplus/b8d34d050d37a54291391ccdca0c83ef to your computer and use it in GitHub Desktop.
Save eldorplus/b8d34d050d37a54291391ccdca0c83ef to your computer and use it in GitHub Desktop.
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk
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: @bg_color;
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()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment