Skip to content

Commit

Permalink
Merge branch “flood-fill”
Browse files Browse the repository at this point in the history
  • Loading branch information
Nokse22 committed May 15, 2024
2 parents 5c50e44 + 57f1aa9 commit bfb105d
Show file tree
Hide file tree
Showing 11 changed files with 171 additions and 21 deletions.
1 change: 0 additions & 1 deletion .github/workflows/snap.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
on:
push:
branches: [ "master" ]
pull_request:
workflow_dispatch:
name: Snap
Expand Down
1 change: 1 addition & 0 deletions data/ascii-draw.gresource.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@
<file preprocess="xml-stripblanks">icons/16x16/actions/sidebar-show-right-symbolic.svg</file>
<file preprocess="xml-stripblanks">icons/16x16/actions/line-style-symbolic.svg</file>
<file preprocess="xml-stripblanks">icons/16x16/actions/edit-undo-symbolic.svg</file>
<file preprocess="xml-stripblanks">icons/16x16/actions/fill-tool-symbolic.svg</file>
</gresource>
</gresources>
6 changes: 6 additions & 0 deletions data/gtk/help-overlay.ui
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@
<property name="action-name">app.move-tool</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes" context="shortcut window">Fill</property>
<property name="action-name">app.fill-tool</property>
</object>
</child>
</object>
</child>
</object>
Expand Down
2 changes: 2 additions & 0 deletions data/icons/16x16/actions/fill-tool-symbolic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 15 additions & 6 deletions data/io.github.nokse22.asciidraw.metainfo.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,22 @@
<summary>Sketch anything using characters</summary>

<description>
<p>This app lets you draw diagrams, tables, tree view, art and more using only characters.
There are many stiles to choose from and multiple tools available to use such as:</p>
<p>Draw diagrams, tables, tree view, art and more using only characters.
There are many tools and features available such as:</p>
<ul>
<li>Rectangle</li>
<li>Filled Rectangle</li>
<li>Cartesian, freehand and stepped line</li>
<li>Rectangle using multiple line styles</li>
<li>Filled Rectangle using border and fill characters</li>
<li>Cartesian, Freehand and Stepped line, also with arrows</li>
<li>Freehand Brush</li>
<li>Text with FIGlet fonts</li>
<li>Table</li>
<li>Tree View</li>
<li>Eraser</li>
<li>Character Picker</li>
<li>Select and move</li>
<li>Select and Move</li>
<li>Flood Fill</li>
</ul>
You can also organize characters into custom palettes.
</description>

<developer id="io.github.nokse22">
Expand All @@ -44,6 +46,13 @@ There are many stiles to choose from and multiple tools available to use such as
</branding>

<releases>
<release version="0.3.4" date="2024-05-15">
<description translate="no">
<p>Added a tooltip to know the name and code of a character</p>
<p>Added Flood fill tool</p>
<p>Removed soft hyphen character</p>
</description>
</release>
<release version="0.3.3" date="2024-05-10">
<description translate="no">
<p>Split Extended Latin palette in ASCII and Extended ASCII</p>
Expand Down
10 changes: 10 additions & 0 deletions data/ui/window.ui
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,16 @@
<signal name="clicked" handler="on_choose_select"/>
</object>
</child>
<child>
<object class="GtkToggleButton" id="fill_button">
<property name="css-classes">flat</property>
<property name="group">rectangle_button</property>
<property name="halign">center</property>
<property name="icon-name">fill-tool-symbolic</property>
<property name="tooltip-text" translatable="yes">Fill Ctrl+Shift+F</property>
<signal name="clicked" handler="on_choose_fill"/>
</object>
</child>
<child>
<object class="GtkToggleButton" id="primary_char_button">
<property name="active">True</property>
Expand Down
1 change: 1 addition & 0 deletions src/canvas.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ def __init__(self, _styles, _flip):

self.click_gesture = Gtk.GestureClick()
self.click_gesture.set_propagation_phase(Gtk.PropagationPhase.CAPTURE)
self.click_gesture.set_button(0)
self.drawing_area.add_controller(self.click_gesture)

self.zoom_gesture = Gtk.GestureZoom()
Expand Down
32 changes: 18 additions & 14 deletions src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ def __init__(self):
self.create_action('eraser-tool', self.select_eraser_tool, ['<control>e'])
self.create_action('picker-tool', self.select_picker_tool, ['<control>p'])
self.create_action('move-tool', self.select_move_tool, ['<control>m'])
self.create_action('fill-tool', self.select_fill_tool, ['<control><shift>f'])

self.create_action('new-palette', self.on_new_palette_action)
self.create_action('open-palette-folder', self.on_open_palette_folder_action)
Expand Down Expand Up @@ -170,7 +171,7 @@ def on_about_action(self, *args):
application_name=_("ASCII Draw"),
application_icon='io.github.nokse22.asciidraw',
developer_name='Nokse',
version='0.3.3',
version='0.3.4',
website='https://github.com/Nokse22/ascii-draw',
issue_url='https://github.com/Nokse22/ascii-draw/issues',
developers=['Nokse'],
Expand All @@ -180,7 +181,7 @@ def on_about_action(self, *args):
about.set_translator_credits(_("translator-credits"))
about.present(self.props.active_window)

def on_preferences_action(self, widget, _):
def on_preferences_action(self, *args):
"""Callback for the app.preferences action."""
print('app.preferences action activated')

Expand Down Expand Up @@ -253,42 +254,45 @@ def on_save_changes(self, dialog, task, *args):
elif response == "discard":
self.quit()

def select_rectangle_tool(self, widget, _):
def select_rectangle_tool(self, *args):
self.win.select_rectangle_tool()

def select_filled_rectangle_tool(self, widget, _):
def select_filled_rectangle_tool(self, *args):
self.win.select_filled_rectangle_tool()

def select_line_tool(self, widget, _):
def select_line_tool(self, *args):
self.win.select_line_tool()

def select_text_tool(self, widget, _):
def select_text_tool(self, *args):
self.win.select_text_tool()

def select_table_tool(self, widget, _):
def select_table_tool(self, *args):
self.win.select_table_tool()

def select_tree_tool(self, widget, _):
def select_tree_tool(self, *args):
self.win.select_tree_tool()

def select_free_tool(self, widget, _):
def select_free_tool(self, *args):
self.win.select_free_tool()

def select_eraser_tool(self, widget, _):
def select_eraser_tool(self, *args):
self.win.select_eraser_tool()

def select_arrow_tool(self, widget, _):
def select_arrow_tool(self, *args):
self.win.select_arrow_tool()

def select_free_line_tool(self, widget, _):
def select_free_line_tool(self, *args):
self.win.select_free_line_tool()

def select_picker_tool(self, widget, _):
def select_picker_tool(self, *args):
self.win.select_picker_tool()

def select_move_tool(self, widget, _):
def select_move_tool(self, *args):
self.win.select_move_tool()

def select_fill_tool(self, *args):
self.win.select_fill_tool()

def main(version):
"""The application's entry point."""
app = AsciiDrawApplication()
Expand Down
1 change: 1 addition & 0 deletions src/tools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
from .picker import Picker
from .eraser import Eraser
from .tree import Tree
from .flood_fill import Fill
102 changes: 102 additions & 0 deletions src/tools/flood_fill.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# flood_fill.py
#
# Copyright 2023 Nokse
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# SPDX-License-Identifier: GPL-3.0-or-later

from gi.repository import Adw
from gi.repository import Gtk
from gi.repository import Gdk, Gio, GObject

class Fill(GObject.GObject):
def __init__(self, _canvas, *args, **kwargs):
super().__init__(*args, **kwargs)
self.canvas = _canvas

self._active = False

self.canvas.click_gesture.connect("pressed", self.on_click_pressed)
self.canvas.click_gesture.connect("released", self.on_click_released)
self.canvas.click_gesture.connect("stopped", self.on_click_stopped)

self.start_x = 0
self.start_y = 0

self.x_mul = 12
self.y_mul = 24

self.end_x = 0
self.end_y = 0

self._size = 1

@GObject.Property(type=bool, default=False)
def active(self):
return self._active

@active.setter
def active(self, value):
self._active = value
self.notify('active')

def on_click_pressed(self, click, arg, x, y):
if not self._active: return
x_char = int(x / self.x_mul)
y_char = int(y / self.y_mul)

self.canvas.add_undo_action(_("Fill"))

button = click.get_current_button()

if button == 1:
flood_fill(self.canvas, x_char, y_char, self.canvas.get_selected_char())
elif button == 3:
flood_fill(self.canvas, x_char, y_char, self.canvas.get_unselected_char())

self.canvas.update()

def on_click_stopped(self, click):
if not self._active: return
pass

def on_click_released(self, click, arg, x, y):
if not self._active: return
pass

def flood_fill(canvas, start_x, start_y, replacement_char):
target_char = canvas.get_char_at(start_x, start_y)

if target_char == replacement_char:
return

rows, cols = canvas.get_canvas_size()

stack = [(start_x, start_y)]

while stack:
x, y = stack.pop()

if canvas.get_char_at(x, y) == target_char:
canvas.set_char_at(x, y, replacement_char, True)

if x > 0:
stack.append((x - 1, y))
if x < rows - 1:
stack.append((x + 1, y))
if y > 0:
stack.append((x, y - 1))
if y < cols - 1:
stack.append((x, y + 1))
15 changes: 15 additions & 0 deletions src/window.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class AsciiDrawWindow(Adw.ApplicationWindow):
table_button = Gtk.Template.Child()
picker_button = Gtk.Template.Child()
eraser_button = Gtk.Template.Child()
fill_button = Gtk.Template.Child()

eraser_adjustment = Gtk.Template.Child()
line_arrow_switch = Gtk.Template.Child()
Expand Down Expand Up @@ -185,6 +186,9 @@ def __init__(self, **kwargs):
self.tree_tool.bind_property('active', self.tree_button, 'active', GObject.BindingFlags.BIDIRECTIONAL)
self.tree_tool.bind_property('text', self.tree_text_entry_buffer, 'text', GObject.BindingFlags.BIDIRECTIONAL)

self.fill_tool = Fill(self.canvas)
self.fill_tool.bind_property('active', self.fill_button, 'active', GObject.BindingFlags.BIDIRECTIONAL)

prev_btn = None

for style in self.styles:
Expand Down Expand Up @@ -679,6 +683,14 @@ def on_choose_eraser(self, btn):
self.sidebar_stack.set_visible_child_name("eraser_page")
self.canvas.clear_preview()

@Gtk.Template.Callback("on_choose_fill")
def on_choose_fill(self, btn):
print("fill")
current_sidebar = self.sidebar_stack.get_visible_child_name()
if current_sidebar != "character_page" and current_sidebar != "style_page":
self.sidebar_stack.set_visible_child_name("character_page")
self.canvas.clear_preview()

def new_palette_from_canvas(self):
content = self.canvas.get_content()
content = content.replace('\n', '')
Expand Down Expand Up @@ -790,3 +802,6 @@ def select_picker_tool(self):

def select_move_tool(self):
self.move_button.set_active(True)

def select_fill_tool(self):
self.fill_button.set_active(True)

0 comments on commit bfb105d

Please sign in to comment.