Added secondary mode button logic; added arrow bi-directionality; cleaned up primary button box
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
from .brush_event import BrushEvent
|
||||
from .grid import Grid
|
||||
from .arrow import Arrow
|
||||
from .dual_arrow import DualArrow
|
||||
from .line import Line
|
||||
from .circle import Circle
|
||||
from .square import Square
|
||||
|
@@ -6,7 +6,6 @@ import cairo
|
||||
|
||||
# Application imports
|
||||
from data.point import Point
|
||||
from data.points import Points
|
||||
|
||||
from . import BrushEvent
|
||||
|
||||
@@ -15,14 +14,6 @@ class Arrow(BrushEvent):
|
||||
def __init__(self):
|
||||
super(Arrow, self).__init__()
|
||||
|
||||
self.points: Points = Points()
|
||||
|
||||
def __copy__(self):
|
||||
copy = type(self)()
|
||||
copy.color = self.color
|
||||
|
||||
return copy
|
||||
|
||||
|
||||
def update(self, eve = None):
|
||||
if len(self.points) < 2:
|
||||
@@ -44,11 +35,23 @@ class Arrow(BrushEvent):
|
||||
x1, y1 = self.points[0].x, self.points[0].y
|
||||
x2, y2 = self.points[1].x, self.points[1].y
|
||||
|
||||
# Arrow body
|
||||
self.draw_arrow_body(brush, x1, y1, x2, y2)
|
||||
self.draw_end_arrow_head(brush, x1, y1, x2, y2)
|
||||
|
||||
def draw_start_arrow_head(self, brush, x1, y1, x2, y2):
|
||||
ah1, ay1, \
|
||||
ah2, ay2 = self.get_arrow_head_points(x2, y2, x1, y1)
|
||||
|
||||
brush.move_to(x1, y1)
|
||||
brush.line_to(ah1, ay1)
|
||||
brush.move_to(x1, y1)
|
||||
brush.line_to(ah2, ay2)
|
||||
|
||||
def draw_arrow_body(self, brush, x1, y1, x2, y2):
|
||||
brush.move_to(x1, y1)
|
||||
brush.line_to(x2, y2)
|
||||
|
||||
# Arrow head
|
||||
def draw_end_arrow_head(self, brush, x1, y1, x2, y2):
|
||||
ah1, ay1, \
|
||||
ah2, ay2 = self.get_arrow_head_points(x1, y1, x2, y2)
|
||||
|
||||
|
@@ -6,6 +6,9 @@ import cairo
|
||||
# Application imports
|
||||
from data.events.event import Event
|
||||
|
||||
from data.points import Points
|
||||
|
||||
|
||||
|
||||
class UnboundException(Exception):
|
||||
...
|
||||
@@ -19,6 +22,8 @@ class BrushEvent(Event):
|
||||
self.size: int = 12
|
||||
self.color: [] = [0.0, 0.0, 0.0, 1.0]
|
||||
|
||||
self.points: Points = Points()
|
||||
|
||||
|
||||
def update(self, eve):
|
||||
raise UnboundException("Method hasn't been overriden...")
|
||||
|
@@ -5,7 +5,6 @@ import cairo
|
||||
|
||||
# Application imports
|
||||
from data.point import Point
|
||||
from data.points import Points
|
||||
|
||||
from . import BrushEvent
|
||||
|
||||
@@ -14,14 +13,6 @@ class Circle(BrushEvent):
|
||||
def __init__(self):
|
||||
super(Circle, self).__init__()
|
||||
|
||||
self.points: Points = Points()
|
||||
|
||||
def __copy__(self):
|
||||
copy = type(self)()
|
||||
copy.color = self.color
|
||||
|
||||
return copy
|
||||
|
||||
|
||||
def update(self, eve):
|
||||
self.points.append( Point(eve.x, eve.y) )
|
||||
|
24
src/data/events/brushes/dual_arrow.py
Normal file
24
src/data/events/brushes/dual_arrow.py
Normal file
@@ -0,0 +1,24 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import cairo
|
||||
|
||||
# Application imports
|
||||
from .arrow import Arrow
|
||||
|
||||
|
||||
|
||||
class DualArrow(Arrow):
|
||||
def __init__(self):
|
||||
super(DualArrow, self).__init__()
|
||||
|
||||
|
||||
def process(self, brush: cairo.Context):
|
||||
self.set_brush_data(brush)
|
||||
|
||||
x1, y1 = self.points[0].x, self.points[0].y
|
||||
x2, y2 = self.points[1].x, self.points[1].y
|
||||
|
||||
self.draw_start_arrow_head(brush, x1, y1, x2, y2)
|
||||
self.draw_arrow_body(brush, x1, y1, x2, y2)
|
||||
self.draw_end_arrow_head(brush, x1, y1, x2, y2)
|
@@ -4,9 +4,6 @@
|
||||
import cairo
|
||||
|
||||
# Application imports
|
||||
from data.point import Point
|
||||
from data.points import Points
|
||||
|
||||
from . import Line
|
||||
|
||||
|
||||
@@ -14,8 +11,6 @@ class Erase(Line):
|
||||
def __init__(self):
|
||||
super(Erase, self).__init__()
|
||||
|
||||
self.points: Points = Points()
|
||||
|
||||
def set_brush_data(self, brush):
|
||||
brush.set_line_width(self.size)
|
||||
brush.set_line_cap(1) # 0 = BUTT, 1 = ROUND, 2 = SQUARE
|
||||
|
@@ -16,12 +16,6 @@ class Grid(BrushEvent):
|
||||
self.grid_spacing = 12 # px
|
||||
self.color = [0.2, 0.2, 0.2, 0.64] # light gray
|
||||
|
||||
def __copy__(self):
|
||||
copy = type(self)()
|
||||
copy.color = self.color
|
||||
|
||||
return copy
|
||||
|
||||
|
||||
def update(self, eve):
|
||||
self.is_valid = True
|
||||
|
@@ -5,7 +5,6 @@ import cairo
|
||||
|
||||
# Application imports
|
||||
from data.point import Point
|
||||
from data.points import Points
|
||||
|
||||
from . import BrushEvent
|
||||
|
||||
@@ -14,14 +13,6 @@ class Line(BrushEvent):
|
||||
def __init__(self):
|
||||
super(Line, self).__init__()
|
||||
|
||||
self.points: Points = Points()
|
||||
|
||||
def __copy__(self):
|
||||
copy = type(self)()
|
||||
copy.color = self.color
|
||||
|
||||
return copy
|
||||
|
||||
|
||||
def update(self, eve = None):
|
||||
self.points.append( Point(eve.x, eve.y) )
|
||||
|
@@ -5,7 +5,6 @@ import cairo
|
||||
|
||||
# Application imports
|
||||
from data.point import Point
|
||||
from data.points import Points
|
||||
|
||||
from . import BrushEvent
|
||||
|
||||
@@ -14,14 +13,6 @@ class Square(BrushEvent):
|
||||
def __init__(self):
|
||||
super(Square, self).__init__()
|
||||
|
||||
self.points: Points = Points()
|
||||
|
||||
def __copy__(self):
|
||||
copy = type(self)()
|
||||
copy.color = self.color
|
||||
|
||||
return copy
|
||||
|
||||
|
||||
def update(self, eve):
|
||||
if len(self.points) < 2:
|
||||
|
@@ -7,7 +7,8 @@ gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
from widgets.button_box import ButtonBox
|
||||
from widgets.controls.primary_button_box import PrimaryButtonBox
|
||||
from widgets.controls.secondary_button_box import SecondaryButtonBox
|
||||
from widgets.draw_area import DrawArea
|
||||
|
||||
|
||||
@@ -35,6 +36,29 @@ class ScrollWindow(Gtk.ScrolledWindow):
|
||||
view_port.add( DrawArea() )
|
||||
self.add(view_port)
|
||||
|
||||
|
||||
class MainContainer(Gtk.Box):
|
||||
def __init__(self):
|
||||
super(MainContainer, self).__init__()
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._load_widgets()
|
||||
|
||||
self.show()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_orientation(Gtk.Orientation.HORIZONTAL)
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
self.add( SecondaryButtonBox() )
|
||||
self.add( ScrollWindow() )
|
||||
|
||||
|
||||
class Container(Gtk.Box):
|
||||
def __init__(self):
|
||||
super(Container, self).__init__()
|
||||
@@ -53,5 +77,5 @@ class Container(Gtk.Box):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
self.add( ButtonBox() )
|
||||
self.add( ScrollWindow() )
|
||||
self.add( PrimaryButtonBox() )
|
||||
self.add( MainContainer() )
|
||||
|
47
src/widgets/controls/arrows_box.py
Normal file
47
src/widgets/controls/arrows_box.py
Normal file
@@ -0,0 +1,47 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
|
||||
gi.require_version('Gtk', '3.0')
|
||||
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class ArrowsBox(Gtk.ComboBoxText):
|
||||
def __init__(self):
|
||||
super(ArrowsBox, self).__init__()
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._load_widgets()
|
||||
|
||||
self.show_all()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
...
|
||||
|
||||
def _setup_signals(self):
|
||||
self.connect("changed", self._changed)
|
||||
|
||||
|
||||
def _load_widgets(self):
|
||||
self.prepend_text("End Arrow")
|
||||
self.prepend_text("Start-End Arrow")
|
||||
|
||||
self.set_active(0)
|
||||
|
||||
def _changed(self, widget):
|
||||
text = widget.get_active_text()
|
||||
if text == "End Arrow":
|
||||
mode = "Arrow"
|
||||
elif text == "Start-End Arrow":
|
||||
mode = "DualArrow"
|
||||
else:
|
||||
return
|
||||
|
||||
event_system.emit("set-brush-mode", (mode,))
|
43
src/widgets/controls/brush_color_button.py
Normal file
43
src/widgets/controls/brush_color_button.py
Normal file
@@ -0,0 +1,43 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
|
||||
gi.require_version('Gtk', '3.0')
|
||||
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class BrushColorButton(Gtk.ColorButton):
|
||||
def __init__(self):
|
||||
super(BrushColorButton, self).__init__()
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
self.show_all()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_title("Pick a Color")
|
||||
self.set_use_alpha(True)
|
||||
self.set_rgba( Gdk.RGBA(0.0, 0.0, 0.0, 1.0) )
|
||||
|
||||
|
||||
def _setup_signals(self):
|
||||
self.connect("color-set", self.set_brush_color)
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
...
|
||||
|
||||
def set_brush_color(self, widget: any):
|
||||
event_system.emit("set-brush-color", (widget.get_rgba(),))
|
43
src/widgets/controls/brush_size_spinner.py
Normal file
43
src/widgets/controls/brush_size_spinner.py
Normal file
@@ -0,0 +1,43 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
|
||||
gi.require_version('Gtk', '3.0')
|
||||
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
class BrushSizeSpinner(Gtk.SpinButton):
|
||||
def __init__(self):
|
||||
super(BrushSizeSpinner, self).__init__()
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
self.show_all()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_numeric(True)
|
||||
self.set_digits(0)
|
||||
self.set_snap_to_ticks(True)
|
||||
self.set_increments(1.0, 10.0)
|
||||
self.set_range(1.0, 100.0)
|
||||
self.set_value(12.0)
|
||||
|
||||
def _setup_signals(self):
|
||||
self.connect("value-changed", self.set_brush_size)
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
...
|
||||
|
||||
def set_brush_size(self, widget: any):
|
||||
event_system.emit("set-brush-size", (widget.get_value(),))
|
@@ -6,15 +6,19 @@ import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
|
||||
from gi.repository import Gtk
|
||||
from gi.repository import Gdk
|
||||
|
||||
# Application imports
|
||||
from .controls.save_as_button import SaveAsButton
|
||||
from .toggle_button import ToggleButton
|
||||
from .save_as_button import SaveAsButton
|
||||
from .brush_color_button import BrushColorButton
|
||||
from .brush_size_spinner import BrushSizeSpinner
|
||||
from .arrows_box import ArrowsBox
|
||||
|
||||
|
||||
class ButtonBox(Gtk.Box):
|
||||
|
||||
class PrimaryButtonBox(Gtk.Box):
|
||||
def __init__(self):
|
||||
super(ButtonBox, self).__init__()
|
||||
super(PrimaryButtonBox, self).__init__()
|
||||
|
||||
self.active_btn = None
|
||||
|
||||
@@ -33,32 +37,24 @@ class ButtonBox(Gtk.Box):
|
||||
|
||||
|
||||
def _load_widgets(self):
|
||||
arrow_btn = Gtk.ToggleButton(label = "Arrow")
|
||||
line_btn = Gtk.ToggleButton(label = "Line")
|
||||
circle_btn = Gtk.ToggleButton(label = "Circle")
|
||||
square_btn = Gtk.ToggleButton(label = "Square")
|
||||
erase_btn = Gtk.ToggleButton(label = "Erase")
|
||||
arrow_btn = ToggleButton(label = "Arrows")
|
||||
line_btn = ToggleButton(label = "Line")
|
||||
circle_btn = ToggleButton(label = "Circle")
|
||||
square_btn = ToggleButton(label = "Square")
|
||||
erase_btn = ToggleButton(label = "Erase")
|
||||
|
||||
save_btn = SaveAsButton()
|
||||
color_btn = Gtk.ColorButton()
|
||||
size_btn = Gtk.SpinButton()
|
||||
color_btn = BrushColorButton()
|
||||
size_btn = BrushSizeSpinner()
|
||||
|
||||
self.active_btn = line_btn
|
||||
line_btn.set_active(True)
|
||||
|
||||
color_btn.set_title("Pick a Color")
|
||||
color_btn.set_use_alpha(True)
|
||||
color_btn.set_rgba( Gdk.RGBA(0.0, 0.0, 0.0, 1.0) )
|
||||
|
||||
size_btn.set_numeric(True)
|
||||
size_btn.set_digits(0)
|
||||
size_btn.set_snap_to_ticks(True)
|
||||
size_btn.set_increments(1.0, 10.0)
|
||||
size_btn.set_range(1.0, 100.0)
|
||||
size_btn.set_value(12.0)
|
||||
|
||||
color_btn.connect("color-set", self.set_brush_color)
|
||||
size_btn.connect("value-changed", self.set_brush_size)
|
||||
arrow_btn.secondary = ["Arrow", "DualArrow"]
|
||||
line_btn.secondary = []
|
||||
circle_btn.secondary = []
|
||||
square_btn.secondary = []
|
||||
erase_btn.secondary = []
|
||||
|
||||
self.add(arrow_btn)
|
||||
self.add(line_btn)
|
||||
@@ -81,12 +77,6 @@ class ButtonBox(Gtk.Box):
|
||||
except Exception as e:
|
||||
...
|
||||
|
||||
def set_brush_color(self, widget: any):
|
||||
event_system.emit("set-brush-color", (widget.get_rgba(),))
|
||||
|
||||
def set_brush_size(self, widget: any):
|
||||
event_system.emit("set-brush-size", (widget.get_value(),))
|
||||
|
||||
def set_brush_mode(self, widget: any, mode: str):
|
||||
if mode in ["Save As"]: return
|
||||
|
||||
@@ -94,6 +84,10 @@ class ButtonBox(Gtk.Box):
|
||||
widget.set_active(True)
|
||||
self.active_btn = widget
|
||||
|
||||
event_system.emit("load-secondary-buttons", (widget,))
|
||||
if mode in ["Arrows"]:
|
||||
return
|
||||
|
||||
event_system.emit("set-brush-mode", (mode,))
|
||||
|
||||
def save_image(self, widget: any):
|
76
src/widgets/controls/secondary_button_box.py
Normal file
76
src/widgets/controls/secondary_button_box.py
Normal file
@@ -0,0 +1,76 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
|
||||
gi.require_version('Gtk', '3.0')
|
||||
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class SecondaryButtonBox(Gtk.Box):
|
||||
def __init__(self):
|
||||
super(SecondaryButtonBox, self).__init__()
|
||||
|
||||
self.active_btn = None
|
||||
self.signals: [] = []
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
self.show_all()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
margin_px = 24
|
||||
|
||||
self.set_margin_top(margin_px)
|
||||
self.set_orientation(Gtk.Orientation.VERTICAL)
|
||||
self.set_hexpand(False)
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
event_system.subscribe("load-secondary-buttons", self._load_secondary_buttons)
|
||||
|
||||
def _load_widgets(self, mode = None):
|
||||
if not mode: return
|
||||
|
||||
for entry in mode.secondary:
|
||||
child = Gtk.ToggleButton(label = entry)
|
||||
sig_id = child.connect("released", self.set_brush_mode, child.get_label())
|
||||
self.signals.append(sig_id)
|
||||
self.add(child)
|
||||
|
||||
if len(mode.secondary) > 0:
|
||||
child = self.get_children()[0]
|
||||
self.set_brush_mode(child, child.get_label())
|
||||
|
||||
def _load_secondary_buttons(self, mode):
|
||||
self.clear()
|
||||
self._load_widgets(mode)
|
||||
self.show_all()
|
||||
|
||||
def set_brush_mode(self, widget: any, mode: str):
|
||||
if self.active_btn:
|
||||
self.active_btn.set_active(False)
|
||||
|
||||
widget.set_active(True)
|
||||
self.active_btn = widget
|
||||
|
||||
event_system.emit("set-brush-mode", (mode,))
|
||||
|
||||
def clear(self):
|
||||
self.active_btn = None
|
||||
|
||||
for sig_id in self.signals:
|
||||
self.disconnect(sig_id)
|
||||
|
||||
for widget in self.get_children():
|
||||
self.remove(widget)
|
37
src/widgets/controls/toggle_button.py
Normal file
37
src/widgets/controls/toggle_button.py
Normal file
@@ -0,0 +1,37 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
|
||||
gi.require_version('Gtk', '3.0')
|
||||
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
class ToggleButton(Gtk.ToggleButton):
|
||||
def __init__(self, label = ""):
|
||||
super(ToggleButton, self).__init__(label)
|
||||
|
||||
self.secondary: [] = []
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
self.show_all()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
...
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
...
|
Reference in New Issue
Block a user