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
|
||||
|
||||
# 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
|
||||
from .draw_area_base import DrawAreaBase
|
||||
|
||||
|
||||
|
||||
# Note: https://martimm.github.io/gnome-gtk3/content-docs/tutorial/Cairo/drawing-model.html
|
||||
class DrawArea(Gtk.DrawingArea):
|
||||
class DrawArea(DrawAreaBase):
|
||||
def __init__(self):
|
||||
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_signals()
|
||||
self._subscribe_to_events()
|
||||
@@ -47,21 +31,20 @@ class DrawArea(Gtk.DrawingArea):
|
||||
|
||||
|
||||
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)
|
||||
super()._setup_styling()
|
||||
|
||||
def _setup_signals(self):
|
||||
self.set_can_focus(True)
|
||||
self.set_size_request(800, 600)
|
||||
|
||||
self.add_events(Gdk.EventMask.KEY_PRESS_MASK)
|
||||
self.add_events(Gdk.EventMask.KEY_RELEASE_MASK)
|
||||
self.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
|
||||
self.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK)
|
||||
self.add_events(Gdk.EventMask.BUTTON1_MOTION_MASK)
|
||||
self.add_events(
|
||||
Gdk.EventMask.KEY_PRESS_MASK |
|
||||
Gdk.EventMask.KEY_RELEASE_MASK |
|
||||
Gdk.EventMask.BUTTON_PRESS_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("button-press-event", self._button_press_event)
|
||||
@@ -79,53 +62,6 @@ class DrawArea(Gtk.DrawingArea):
|
||||
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):
|
||||
if not self.has_focus():
|
||||
self.grab_focus()
|
||||
@@ -149,7 +85,7 @@ class DrawArea(Gtk.DrawingArea):
|
||||
|
||||
if not self.brush.is_valid: return
|
||||
|
||||
self.primary_surface.update(self.brush)
|
||||
self.active_surface.update(self.brush)
|
||||
self.queue_draw()
|
||||
|
||||
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 keyname == "z":
|
||||
if len(self.primary_surface.history_manager) == 0: return
|
||||
self.event_collection.append( self.primary_surface.history_manager.pop() )
|
||||
if len(self.active_surface.history_manager) == 0: return
|
||||
self.event_collection.append( self.active_surface.history_manager.pop() )
|
||||
elif keyname == "y":
|
||||
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":
|
||||
self._set_new_surface()
|
||||
elif keyname == "s":
|
||||
@@ -175,53 +111,59 @@ class DrawArea(Gtk.DrawingArea):
|
||||
|
||||
self.queue_draw()
|
||||
|
||||
|
||||
def _motion_notify_event(self, area, eve):
|
||||
if not self.is_drawing: return
|
||||
self.brush.update(eve)
|
||||
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):
|
||||
self._draw_background(area, brush)
|
||||
self._draw_surfaces(area, brush)
|
||||
self._draw_overlay(area, brush)
|
||||
match self.is_drawing:
|
||||
case False:
|
||||
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
|
||||
|
||||
def _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
|
||||
|
||||
def _is_not_drawing_draw_background(self, area, brush: cairo.Context):
|
||||
brush.set_source_surface(self.background_surface.area, 0.0, 0.0)
|
||||
self.background_surface.draw()
|
||||
brush.paint()
|
||||
|
||||
def _draw_surfaces(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 each surface.
|
||||
if self.is_drawing:
|
||||
for surface in self.surface_manager:
|
||||
brush.set_source_surface(surface.area, 0.0, 0.0)
|
||||
|
||||
brush.paint()
|
||||
return
|
||||
# Note: While drawing, only overlay needs to re-calculate its stack.
|
||||
# This can just copy what exists than re-calculating the surface.
|
||||
def _is_drawing_draw_background(self, area, brush: cairo.Context):
|
||||
brush.set_source_surface(self.background_surface.area, 0.0, 0.0)
|
||||
brush.paint()
|
||||
|
||||
def _is_not_drawing_draw_surfaces(self, area, brush: cairo.Context):
|
||||
for surface in self.surface_manager:
|
||||
brush.set_source_surface(surface.area, 0.0, 0.0)
|
||||
surface.draw()
|
||||
|
||||
brush.paint()
|
||||
|
||||
def _draw_overlay(self, area, brush: cairo.Context):
|
||||
# Note: When NOT drawing, no overlay data should exist nor be processed...
|
||||
if not self.is_drawing:
|
||||
self.intermediate_surface.clear_surface()
|
||||
return
|
||||
# Note: While drawing, only overlay needs to re-calculate its stack.
|
||||
# This can just copy what exists than re-calculating each surface.
|
||||
def _is_drawing_draw_surfaces(self, area, brush: cairo.Context):
|
||||
for surface in self.surface_manager:
|
||||
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)
|
||||
self.intermediate_surface.draw()
|
||||
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