Cleaning up DrawArea class and moved some methods to base class
This commit is contained in:
@@ -10,34 +10,18 @@ from gi.repository import Gtk
|
|||||||
from gi.repository import Gdk
|
from gi.repository import Gdk
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
from libs.surface_manager import SurfaceManager
|
|
||||||
from libs.event_collection import EventCollection
|
|
||||||
|
|
||||||
from data.mouse_buttons import MouseButton
|
from data.mouse_buttons import MouseButton
|
||||||
from data.events import brushes
|
from data.events import brushes
|
||||||
|
|
||||||
from .surface import Surface
|
from .draw_area_base import DrawAreaBase
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Note: https://martimm.github.io/gnome-gtk3/content-docs/tutorial/Cairo/drawing-model.html
|
# Note: https://martimm.github.io/gnome-gtk3/content-docs/tutorial/Cairo/drawing-model.html
|
||||||
class DrawArea(Gtk.DrawingArea):
|
class DrawArea(DrawAreaBase):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(DrawArea, self).__init__()
|
super(DrawArea, self).__init__()
|
||||||
|
|
||||||
self.background_surface: Surface = None
|
|
||||||
self.primary_surface: Surface = None
|
|
||||||
self.intermediate_surface: Surface = None
|
|
||||||
self.surface_manager: SurfaceManager = SurfaceManager()
|
|
||||||
self.event_collection: EventCollection = EventCollection()
|
|
||||||
|
|
||||||
self.is_drawing: bool = False
|
|
||||||
self.brush_mode: str = "Line"
|
|
||||||
self.grid_brush: BrushBase = getattr(brushes, "Grid")()
|
|
||||||
self.brush: BrushBase = getattr(brushes, self.brush_mode)()
|
|
||||||
self.brush_color = self.brush.color
|
|
||||||
self.brush_size = self.brush.size
|
|
||||||
|
|
||||||
self._setup_styling()
|
self._setup_styling()
|
||||||
self._setup_signals()
|
self._setup_signals()
|
||||||
self._subscribe_to_events()
|
self._subscribe_to_events()
|
||||||
@@ -47,21 +31,20 @@ class DrawArea(Gtk.DrawingArea):
|
|||||||
|
|
||||||
|
|
||||||
def _setup_styling(self):
|
def _setup_styling(self):
|
||||||
margin_px = 24
|
super()._setup_styling()
|
||||||
self.set_margin_top(margin_px)
|
|
||||||
self.set_margin_left(margin_px)
|
|
||||||
self.set_margin_right(margin_px)
|
|
||||||
self.set_margin_end(margin_px)
|
|
||||||
|
|
||||||
def _setup_signals(self):
|
def _setup_signals(self):
|
||||||
self.set_can_focus(True)
|
self.set_can_focus(True)
|
||||||
self.set_size_request(800, 600)
|
self.set_size_request(800, 600)
|
||||||
|
|
||||||
self.add_events(Gdk.EventMask.KEY_PRESS_MASK)
|
self.add_events(
|
||||||
self.add_events(Gdk.EventMask.KEY_RELEASE_MASK)
|
Gdk.EventMask.KEY_PRESS_MASK |
|
||||||
self.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
|
Gdk.EventMask.KEY_RELEASE_MASK |
|
||||||
self.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK)
|
Gdk.EventMask.BUTTON_PRESS_MASK |
|
||||||
self.add_events(Gdk.EventMask.BUTTON1_MOTION_MASK)
|
Gdk.EventMask.BUTTON_RELEASE_MASK |
|
||||||
|
Gdk.EventMask.BUTTON1_MOTION_MASK |
|
||||||
|
Gdk.EventMask.POINTER_MOTION_MASK
|
||||||
|
)
|
||||||
|
|
||||||
self.connect("key-release-event", self._key_release_event)
|
self.connect("key-release-event", self._key_release_event)
|
||||||
self.connect("button-press-event", self._button_press_event)
|
self.connect("button-press-event", self._button_press_event)
|
||||||
@@ -79,53 +62,6 @@ class DrawArea(Gtk.DrawingArea):
|
|||||||
def _load_widgets(self):
|
def _load_widgets(self):
|
||||||
...
|
...
|
||||||
|
|
||||||
def _set_new_surface(self):
|
|
||||||
size_w, \
|
|
||||||
size_h, \
|
|
||||||
image_surface = event_system.emit_and_await("get-image-size")
|
|
||||||
|
|
||||||
self.grid_brush.width = size_w
|
|
||||||
self.grid_brush.height = size_h
|
|
||||||
self.background_surface = Surface(size_w, size_h)
|
|
||||||
self.primary_surface = Surface(size_w, size_h)
|
|
||||||
self.intermediate_surface = Surface(size_w, size_h)
|
|
||||||
|
|
||||||
if image_surface:
|
|
||||||
self.primary_surface.create_new_area(image_surface)
|
|
||||||
self.primary_surface.set_image_data(image_surface.get_data())
|
|
||||||
|
|
||||||
self.event_collection.clear()
|
|
||||||
self.surface_manager.clear()
|
|
||||||
|
|
||||||
self.grid_brush.update(None)
|
|
||||||
self.set_size_request(size_w, size_h)
|
|
||||||
self.background_surface.update(self.grid_brush)
|
|
||||||
self.surface_manager.append( self.primary_surface )
|
|
||||||
|
|
||||||
def _save_image(self, fpath: str):
|
|
||||||
self.primary_surface.area.write_to_png(fpath)
|
|
||||||
|
|
||||||
def _do_save_image(self):
|
|
||||||
fpath = event_system.emit_and_await("save-as")
|
|
||||||
if not fpath: return
|
|
||||||
self._save_image(fpath)
|
|
||||||
|
|
||||||
def _set_brush_color(self, color: Gdk.RGBA):
|
|
||||||
self.brush = getattr(brushes, self.brush_mode)()
|
|
||||||
self.brush_color = [color.red, color.green, color.blue, color.alpha]
|
|
||||||
self.brush.color = self.brush_color
|
|
||||||
|
|
||||||
def _set_brush_size(self, size: int):
|
|
||||||
self.brush_size = size
|
|
||||||
self.brush = getattr(brushes, self.brush_mode)()
|
|
||||||
self.brush.size = self.brush_size
|
|
||||||
|
|
||||||
def _set_brush_mode(self, mode: str):
|
|
||||||
self.brush_mode = mode
|
|
||||||
self.brush = getattr(brushes, self.brush_mode)()
|
|
||||||
self.brush.color = self.brush_color
|
|
||||||
self.brush.size = self.brush_size
|
|
||||||
|
|
||||||
def _button_press_event(self, widget, eve):
|
def _button_press_event(self, widget, eve):
|
||||||
if not self.has_focus():
|
if not self.has_focus():
|
||||||
self.grab_focus()
|
self.grab_focus()
|
||||||
@@ -149,7 +85,7 @@ class DrawArea(Gtk.DrawingArea):
|
|||||||
|
|
||||||
if not self.brush.is_valid: return
|
if not self.brush.is_valid: return
|
||||||
|
|
||||||
self.primary_surface.update(self.brush)
|
self.active_surface.update(self.brush)
|
||||||
self.queue_draw()
|
self.queue_draw()
|
||||||
|
|
||||||
if eve.type == Gdk.EventType.BUTTON_RELEASE and eve.button == MouseButton.RIGHT_BUTTON:
|
if eve.type == Gdk.EventType.BUTTON_RELEASE and eve.button == MouseButton.RIGHT_BUTTON:
|
||||||
@@ -163,11 +99,11 @@ class DrawArea(Gtk.DrawingArea):
|
|||||||
|
|
||||||
if is_control:
|
if is_control:
|
||||||
if keyname == "z":
|
if keyname == "z":
|
||||||
if len(self.primary_surface.history_manager) == 0: return
|
if len(self.active_surface.history_manager) == 0: return
|
||||||
self.event_collection.append( self.primary_surface.history_manager.pop() )
|
self.event_collection.append( self.active_surface.history_manager.pop() )
|
||||||
elif keyname == "y":
|
elif keyname == "y":
|
||||||
if len(self.event_collection) == 0: return
|
if len(self.event_collection) == 0: return
|
||||||
self.primary_surface.history_manager.append( self.event_collection.pop() )
|
self.active_surface.history_manager.append( self.event_collection.pop() )
|
||||||
elif keyname == "n":
|
elif keyname == "n":
|
||||||
self._set_new_surface()
|
self._set_new_surface()
|
||||||
elif keyname == "s":
|
elif keyname == "s":
|
||||||
@@ -175,53 +111,59 @@ class DrawArea(Gtk.DrawingArea):
|
|||||||
|
|
||||||
self.queue_draw()
|
self.queue_draw()
|
||||||
|
|
||||||
|
|
||||||
def _motion_notify_event(self, area, eve):
|
def _motion_notify_event(self, area, eve):
|
||||||
if not self.is_drawing: return
|
if not self.is_drawing: return
|
||||||
self.brush.update(eve)
|
self.brush.update(eve)
|
||||||
self.queue_draw()
|
self.queue_draw()
|
||||||
|
|
||||||
|
# Note: In the future I imagine we could have different draw states
|
||||||
|
# besides T/F where we could call some subset order or even other surfaces
|
||||||
def _draw(self, area, brush: cairo.Context):
|
def _draw(self, area, brush: cairo.Context):
|
||||||
self._draw_background(area, brush)
|
match self.is_drawing:
|
||||||
self._draw_surfaces(area, brush)
|
case False:
|
||||||
self._draw_overlay(area, brush)
|
self._is_not_drawing_draw_background(area, brush)
|
||||||
|
self._is_not_drawing_draw_surfaces(area, brush)
|
||||||
|
self.is_not_drawing_draw_overlay(area, brush)
|
||||||
|
case True:
|
||||||
|
self._is_drawing_draw_background(area, brush)
|
||||||
|
self._is_drawing_draw_surfaces(area, brush)
|
||||||
|
self._is_drawing_draw_overlay(area, brush)
|
||||||
|
case _:
|
||||||
|
...
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _draw_background(self, area, brush: cairo.Context):
|
def _is_not_drawing_draw_background(self, area, brush: cairo.Context):
|
||||||
# Note: While drawing, only overlay needs to re-calculate its stack.
|
|
||||||
# This can just copy what exists than re-calculating the surface.
|
|
||||||
if self.is_drawing:
|
|
||||||
brush.set_source_surface(self.background_surface.area, 0.0, 0.0)
|
|
||||||
brush.paint()
|
|
||||||
return
|
|
||||||
|
|
||||||
brush.set_source_surface(self.background_surface.area, 0.0, 0.0)
|
brush.set_source_surface(self.background_surface.area, 0.0, 0.0)
|
||||||
self.background_surface.draw()
|
self.background_surface.draw()
|
||||||
brush.paint()
|
brush.paint()
|
||||||
|
|
||||||
def _draw_surfaces(self, area, brush: cairo.Context):
|
|
||||||
# Note: While drawing, only overlay needs to re-calculate its stack.
|
# Note: While drawing, only overlay needs to re-calculate its stack.
|
||||||
# This can just copy what exists than re-calculating each surface.
|
# This can just copy what exists than re-calculating the surface.
|
||||||
if self.is_drawing:
|
def _is_drawing_draw_background(self, area, brush: cairo.Context):
|
||||||
for surface in self.surface_manager:
|
brush.set_source_surface(self.background_surface.area, 0.0, 0.0)
|
||||||
brush.set_source_surface(surface.area, 0.0, 0.0)
|
|
||||||
|
|
||||||
brush.paint()
|
brush.paint()
|
||||||
return
|
|
||||||
|
|
||||||
|
def _is_not_drawing_draw_surfaces(self, area, brush: cairo.Context):
|
||||||
for surface in self.surface_manager:
|
for surface in self.surface_manager:
|
||||||
brush.set_source_surface(surface.area, 0.0, 0.0)
|
brush.set_source_surface(surface.area, 0.0, 0.0)
|
||||||
surface.draw()
|
surface.draw()
|
||||||
|
|
||||||
brush.paint()
|
brush.paint()
|
||||||
|
|
||||||
def _draw_overlay(self, area, brush: cairo.Context):
|
# Note: While drawing, only overlay needs to re-calculate its stack.
|
||||||
# Note: When NOT drawing, no overlay data should exist nor be processed...
|
# This can just copy what exists than re-calculating each surface.
|
||||||
if not self.is_drawing:
|
def _is_drawing_draw_surfaces(self, area, brush: cairo.Context):
|
||||||
self.intermediate_surface.clear_surface()
|
for surface in self.surface_manager:
|
||||||
return
|
brush.set_source_surface(surface.area, 0.0, 0.0)
|
||||||
|
|
||||||
|
brush.paint()
|
||||||
|
|
||||||
|
# Note: When NOT drawing, no overlay data should exist nor be processed...
|
||||||
|
def is_not_drawing_draw_overlay(self, area, brush: cairo.Context):
|
||||||
|
self.intermediate_surface.clear_surface()
|
||||||
|
|
||||||
|
def _is_drawing_draw_overlay(self, area, brush: cairo.Context):
|
||||||
brush.set_source_surface(self.intermediate_surface.area, 0.0, 0.0)
|
brush.set_source_surface(self.intermediate_surface.area, 0.0, 0.0)
|
||||||
self.intermediate_surface.draw()
|
self.intermediate_surface.draw()
|
||||||
brush.paint()
|
brush.paint()
|
||||||
|
93
src/widgets/draw_area_base.py
Normal file
93
src/widgets/draw_area_base.py
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
|
||||||
|
from gi.repository import Gtk
|
||||||
|
from gi.repository import Gdk
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from libs.surface_manager import SurfaceManager
|
||||||
|
from libs.event_collection import EventCollection
|
||||||
|
|
||||||
|
from data.mouse_buttons import MouseButton
|
||||||
|
from data.events import brushes
|
||||||
|
|
||||||
|
from .surface import Surface
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Note: https://martimm.github.io/gnome-gtk3/content-docs/tutorial/Cairo/drawing-model.html
|
||||||
|
class DrawAreaBase(Gtk.DrawingArea):
|
||||||
|
def __init__(self):
|
||||||
|
super(DrawAreaBase, self).__init__()
|
||||||
|
|
||||||
|
self.background_surface: Surface = None
|
||||||
|
self.active_surface: Surface = None
|
||||||
|
self.intermediate_surface: Surface = None
|
||||||
|
self.surface_manager: SurfaceManager = SurfaceManager()
|
||||||
|
self.event_collection: EventCollection = EventCollection()
|
||||||
|
|
||||||
|
self.is_drawing: bool = False
|
||||||
|
self.brush_mode: str = "Line"
|
||||||
|
self.grid_brush: BrushBase = getattr(brushes, "Grid")()
|
||||||
|
self.brush: BrushBase = getattr(brushes, self.brush_mode)()
|
||||||
|
self.brush_color = self.brush.color
|
||||||
|
self.brush_size = self.brush.size
|
||||||
|
|
||||||
|
|
||||||
|
def _setup_styling(self):
|
||||||
|
margin_px = 24
|
||||||
|
self.set_margin_top(margin_px)
|
||||||
|
self.set_margin_left(margin_px)
|
||||||
|
self.set_margin_right(margin_px)
|
||||||
|
self.set_margin_end(margin_px)
|
||||||
|
|
||||||
|
def _set_new_surface(self):
|
||||||
|
size_w, \
|
||||||
|
size_h, \
|
||||||
|
image_surface = event_system.emit_and_await("get-image-size")
|
||||||
|
|
||||||
|
self.grid_brush.width = size_w
|
||||||
|
self.grid_brush.height = size_h
|
||||||
|
self.background_surface = Surface(size_w, size_h)
|
||||||
|
self.active_surface = Surface(size_w, size_h)
|
||||||
|
self.intermediate_surface = Surface(size_w, size_h)
|
||||||
|
|
||||||
|
if image_surface:
|
||||||
|
self.active_surface.create_new_area(image_surface)
|
||||||
|
self.active_surface.set_image_data(image_surface.get_data())
|
||||||
|
|
||||||
|
self.event_collection.clear()
|
||||||
|
self.surface_manager.clear()
|
||||||
|
|
||||||
|
self.grid_brush.update(None)
|
||||||
|
self.set_size_request(size_w, size_h)
|
||||||
|
self.background_surface.update(self.grid_brush)
|
||||||
|
self.surface_manager.append( self.active_surface )
|
||||||
|
|
||||||
|
def _save_image(self, fpath: str):
|
||||||
|
self.active_surface.area.write_to_png(fpath)
|
||||||
|
|
||||||
|
def _do_save_image(self):
|
||||||
|
fpath = event_system.emit_and_await("save-as")
|
||||||
|
if not fpath: return
|
||||||
|
self._save_image(fpath)
|
||||||
|
|
||||||
|
def _set_brush_color(self, color: Gdk.RGBA):
|
||||||
|
self.brush = getattr(brushes, self.brush_mode)()
|
||||||
|
self.brush_color = [color.red, color.green, color.blue, color.alpha]
|
||||||
|
self.brush.color = self.brush_color
|
||||||
|
|
||||||
|
def _set_brush_size(self, size: int):
|
||||||
|
self.brush_size = size
|
||||||
|
self.brush = getattr(brushes, self.brush_mode)()
|
||||||
|
self.brush.size = self.brush_size
|
||||||
|
|
||||||
|
def _set_brush_mode(self, mode: str):
|
||||||
|
self.brush_mode = mode
|
||||||
|
self.brush = getattr(brushes, self.brush_mode)()
|
||||||
|
self.brush.color = self.brush_color
|
||||||
|
self.brush.size = self.brush_size
|
||||||
|
|
Reference in New Issue
Block a user