Commit 09cf4e5
Merge branch 'stoptask'
Changed files (12)
modifiedbirdfont/GtkWindow.valamodifiedlibbirdfont/DrawingTools.valamodifiedlibbirdfont/MainWindow.valamodifiedlibbirdfont/Menu.valamodifiedlibbirdfont/MenuTab.valaaddedlibbirdfont/MergeTask.valamodifiedlibbirdfont/OverviewTools.valamodifiedlibbirdfont/StrokeTask.valamodifiedlibbirdfont/StrokeTool.valamodifiedlibbirdfont/TabBar.valamodifiedlibbirdfont/Task.valamodifiedresources/icons.bf
Diff
@@ -1,5 +1,5 @@ /*- Copyright (C) 2012, 2013, 2014 Johan Mattsson+ Copyright (C) 2012s 2013 2014 Johan Mattsson 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@@ -629,7 +629,6 @@ class TabbarCanvas : DrawingArea { public TabbarCanvas (TabBar tb) { tabbar = tb; - // FIXME: DELETE set_extension_events (ExtensionMode.CURSOR | EventMask.POINTER_MOTION_MASK); add_events (EventMask.BUTTON_PRESS_MASK | EventMask.POINTER_MOTION_MASK | EventMask.LEAVE_NOTIFY_MASK); motion_notify_event.connect ((t, e)=> {@@ -773,7 +773,7 @@ public class DrawingTools : ToolCollection { auto_trace = new Tool ("autotrace", t_("Autotrace background image")); auto_trace.select_action.connect ((self) => { Task t = new Task (auto_trace_background);- MainWindow.native_window.run_background_thread (t);+ MainWindow.run_blocking_task (t); }); draw_tool_modifiers.add_tool (auto_trace); @@ -31,6 +31,7 @@ public class MainWindow : GLib.Object { public static AbstractMenu menu; public static Dialog dialog; public static SpacingTab spacing_tab; + public static Task blocking_background_task; /** Number of pixels per mm */ public static double units = 1; @@ -51,10 +52,20 @@ public class MainWindow : GLib.Object { menu = new Menu (); dialog = new Dialog (); spacing_tab = new SpacingTab (); + blocking_background_task = new Task (null); tools.select_tool (DrawingTools.bezier_tool); } + public static void abort_task () { + blocking_background_task.cancel (); + } + + public static void run_blocking_task (Task task) { + blocking_background_task = task; + native_window.run_background_thread (task); + } + public static SpacingTab get_spacing_tab () { return spacing_tab; } @@ -168,9 +168,7 @@ public class Menu : AbstractMenu { MenuItem merge_paths = add_menu_item (t_("Merge Paths"), "merge_paths", "Glyph"); merge_paths.action.connect (() => {- Task t = new Task (merge_selected_paths);- MainWindow.native_window.run_background_thread (t);- + merge_selected_paths (); show_menu = false; }); edit_menu.items.add (merge_paths);@@ -500,9 +498,8 @@ public class Menu : AbstractMenu { } void merge_selected_paths () {- // FIXME: make task- StrokeTool s = new StrokeTool ();- s.merge_selected_paths ();+ MergeTask t = new MergeTask ();+ MainWindow.run_blocking_task (t); } } @@ -632,7 +632,7 @@ public class MenuTab : FontDisplay { } Task t = new Task (simplify);- MainWindow.native_window.run_background_thread (t);+ MainWindow.run_blocking_task (t); } private static void simplify () {new file mode 100644@@ -0,0 +1,32 @@+/*+ Copyright (C) 2015 Johan Mattsson++ This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 3 of the + License, or (at your option) any later version.++ This library 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 + Lesser General Public License for more details.+*/++using Cairo;++namespace BirdFont {++class MergeTask : StrokeTask {+ StrokeTool stroke_tool;+ + public MergeTask () {+ base.none ();+ stroke_tool = new StrokeTool.with_task (this);+ }+ + public override void run () {+ stroke_tool.merge_selected_paths (); + }+}++}@@ -136,7 +136,7 @@ public class OverviewTools : ToolCollection { curve_orientation.select_action.connect ((self) => { Task t = new Task (fix_curve_orientation); - MainWindow.native_window.run_background_thread (t);+ MainWindow.run_blocking_task (t); IdleSource idle = new IdleSource (); idle.set_callback (() => {@@ -19,13 +19,13 @@ public class StrokeTask : Task { Path background_path; // path in background thread public StrokeTask (Path path) {- base (null);+ base (null, true); original = path; background_path = path.copy (); } public StrokeTask.none () {- base (null);+ base (null, true); original = new Path (); background_path = new Path (); }@@ -212,7 +212,11 @@ public class StrokeTool : GLib.Object { } } }- ++ if (task.is_cancelled ()) {+ return;+ }+ foreach (Path p in g.active_paths) { g.delete_path (p); }@@ -234,13 +238,15 @@ public class StrokeTool : GLib.Object { PointSelection ps; p.remove_points_on_points ();- + for (int i = 0; i < p.points.size; i++) { EditPoint ep = p.points.get (i); EditPoint next = p.points.get ((i + 1) % p.points.size); if (fabs (ep.get_right_handle ().angle - ep.get_left_handle ().angle) % (2 * PI) < 0.01) {- ps = new PointSelection (ep, p);- PenTool.remove_point_simplify (ps);+ if (ep.get_right_handle ().length > 0 && ep.get_left_handle ().length > 0) {+ ps = new PointSelection (ep, p);+ PenTool.remove_point_simplify (ps);+ } } else if (Path.distance_to_point (ep, next) < 0.01) { ps = new PointSelection (ep, p); PenTool.remove_point_simplify (ps);@@ -2138,7 +2144,11 @@ public class StrokeTool : GLib.Object { np.remove_points_on_points (); r.add (np); }-+ + if (task.is_cancelled ()) {+ return new PathList ();+ }+ r = get_all_parts (r); remove_single_points (r); @@ -2165,7 +2175,13 @@ public class StrokeTool : GLib.Object { p.close (); p.recalculate_linear_handles (); }- ++ if (task.is_cancelled ()) {+ return new PathList ();+ } else {+ print("Task is running\n"); // FIXME: DELETE+ }+ return r; } @@ -1,15 +1,15 @@ /*- Copyright (C) 2012, 2014, 2015 Johan Mattsson+ Copyright (C) 2012 2014 2015 Johan Mattsson - This library is free software; you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 3 of the - License, or (at your option) any later version.+ This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 3 of the + License, or (at your option) any later version. - This library 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 - Lesser General Public License for more details.+ This library 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 + Lesser General Public License for more details. */ using Cairo;@@ -28,6 +28,7 @@ public class TabBar : GLib.Object { static const int PREVIOUS_TAB = -3; static const int PROGRESS_WHEEL = -3; static const int SHOW_MENU = -4;+ static const int STOP_BUTTON = -5; int first_tab = 0; int selected = 0;@@ -43,6 +44,7 @@ public class TabBar : GLib.Object { double scale = 1; // scale images in 320 dpi bool processing = false;+ bool stop_button = false; double wheel_rotation = 0; double background_r = 51 /255.0;@@ -51,6 +53,7 @@ public class TabBar : GLib.Object { Text menu_icon; Text progress_icon;+ Text stop_icon; Text left_arrow; Text right_arrow; @@ -63,6 +66,9 @@ public class TabBar : GLib.Object { progress_icon = new Text ("progress"); progress_icon.load_font (Theme.get_icon_file ()); + stop_icon = new Text ("stop");+ stop_icon.load_font (Theme.get_icon_file ());+ left_arrow = new Text ("left_arrow"); left_arrow.load_font (Theme.get_icon_file ()); @@ -83,17 +89,11 @@ public class TabBar : GLib.Object { } public void motion (double x, double y) {- MainWindow.set_cursor (NativeWindow.VISIBLE);- - if (MenuTab.has_suppress_event ()) {- warn_if_test ("Event suppressed");- return;- }- - over_close (x, y, out over, out over_close_tab);+ MainWindow.set_cursor (NativeWindow.VISIBLE); + motion_event (x, y, out over, out over_close_tab); } - private void over_close (double x, double y, out int over, out int over_close_tab) {+ private void motion_event (double x, double y, out int over, out int over_close_tab) { int i = 0; double offset = 0; bool close_y, close_x;@@ -110,14 +110,27 @@ public class TabBar : GLib.Object { over = SHOW_MENU; return; }- } else if (has_scroll () && has_progress_wheel ()) {- if (x > width - 19) {+ } else if (!has_scroll () && cancelable_task ()) {+ if (x > width - 19 && 10 <= y < height - 10) { over_close_tab = NO_TAB;- over = PROGRESS_WHEEL;+ over = STOP_BUTTON;+ stop_button = true;+ redraw_tab_bar (0, 0, width, height);+ } else {+ stop_button = false;+ }+ } else if (has_scroll () && cancelable_task ()) {+ if (x > width - 19 && 10 <= y < height - 10) {+ over_close_tab = NO_TAB;+ over = STOP_BUTTON;+ stop_button = true;+ redraw_tab_bar (0, 0, width, height);+ return; } else if (x > width - 2 * 19) { over_close_tab = NO_TAB; over = NEXT_TAB; }+ stop_button = false; } else if (!has_scroll () && has_progress_wheel ()) { if (x > width - 19) { over_close_tab = NO_TAB;@@ -158,11 +171,14 @@ public class TabBar : GLib.Object { offset += t.get_width (); i++; }-+ over_close_tab = NO_TAB; over = NO_TAB; } + bool cancelable_task () {+ return MainWindow.blocking_background_task.is_cancellable ();+ } /** Select tab for a glyph by charcode or name. * @return true if the tab was found@@ -447,9 +463,7 @@ public class TabBar : GLib.Object { } selected = index;- t = tabs.get (index);- previous_tab = current_tab; current_tab = t; @@ -510,7 +524,6 @@ public class TabBar : GLib.Object { } foreach (Tab t in tabs) {- if (i < first_tab) { i++; continue;@@ -552,9 +565,11 @@ public class TabBar : GLib.Object { this.height = height; this.scale = height / 117.0; - over_close (x, y, out over, out close);-- if (over_close_tab >= 0 && over == selected) {+ motion_event (x, y, out over, out close);+ + if (stop_button) {+ MainWindow.abort_task ();+ } else if (over_close_tab >= 0 && over == selected) { close_tab (over_close_tab); } else { select_tab (over);@@ -651,26 +666,33 @@ public class TabBar : GLib.Object { right_arrow.draw (cr); } - // progress wheel if (has_progress_wheel ()) { double progress_size = 40 / scale;+ Text wheel = has_stop_button () ? stop_icon : progress_icon; - Theme.text_color (progress_icon, "Text Tab Bar");+ print (@"has_stop_button: $(has_stop_button())\n");+ if (!has_stop_button ()) {+ Theme.text_color (wheel, "Text Tab Bar");+ } else {+ Theme.text_color (wheel, "Highlighted 1");+ } double middley = h / 2;- double middlex = w - (progress_icon.get_sidebearing_extent () / 2) / scale;- progress_icon.set_font_size (progress_size);- progress_icon.widget_x = middlex;- progress_icon.widget_y = middley;+ double middlex = w - (wheel.get_sidebearing_extent () / 2) / scale;+ wheel.set_font_size (progress_size);+ wheel.widget_x = middlex;+ wheel.widget_y = middley; - progress_icon.use_cache (false);+ wheel.use_cache (false); cr.save ();- cr.translate (middlex, middley);- cr.rotate (wheel_rotation);- cr.translate (-middlex, -middley);-- progress_icon.draw_at_baseline (cr, progress_icon.widget_x, progress_icon.widget_y);+ if (!has_stop_button ()) {+ cr.translate (middlex, middley);+ cr.rotate (wheel_rotation);+ cr.translate (-middlex, -middley);+ }+ + wheel.draw_at_baseline (cr, wheel.widget_x, wheel.widget_y); cr.restore (); } else { // menu icon@@ -826,6 +848,11 @@ public class TabBar : GLib.Object { add_tab (new EmptyTab (name, label)); } + bool has_stop_button () {+ return processing + && stop_button;+ }+ bool has_progress_wheel () { return processing; }@@ -840,6 +867,10 @@ public class TabBar : GLib.Object { processing = running; + if (!processing) {+ stop_button = false;+ }+ if (processing) { timer = new TimeoutSource (50); timer.set_callback (() => {@@ -850,6 +881,7 @@ public class TabBar : GLib.Object { } redraw_tab_bar (width - 40, 0, 40, height);+ return processing; }); timer.attach (null);@@ -19,15 +19,36 @@ public class Task : GLib.Object { public delegate void Runnable (); Runnable task; bool cancelled = false;- - public Task (owned Runnable? r) {+ bool cancelable = false;++ public Task.empty () {+ }+ + public Task (owned Runnable? r, bool cancelable = false) { if (r != null) { task = (!) ((owned) r); }+ + this.cancelable = cancelable;+ }+ + public bool is_cancellable () {+ bool c;+ + lock (cancelled) { + c = cancelable;+ }+ + return c; } public void cancel () {- lock (cancelled) { + print("Cancel task.\n");+ lock (cancelled) { + if (unlikely (!cancelable)) {+ warning ("Task is not cancelable.");+ }+ cancelled = true; } }@@ -49,6 +70,7 @@ public class Task : GLib.Object { } task ();+ print("Task finished.\n"); } public void* perform_task() {@@ -1327,6 +1327,14 @@ GNU Lesser General Public License</copyright> </layer> </glyph> </collection>+<collection name="stop">+ <selected id="0"/>+ <glyph id="0" left="-38.02807708356368" right="-11.034366391739779">+ <layer name= "Layer" visible="true">+ <path data="B -46.2079237702,18.7968527394 M -29.8809661359,18.7968527216 M -18.9347484383,7.8506350191 M -18.9347484341,-8.4763225942 M -29.8943710871,-19.4359452494 M -46.4855929037,-19.1448711863 M -57.1541414920,-8.4763225846 M -57.1541415032,7.8506350137 M -46.2079237702,18.7968527394" />+ </layer>+ </glyph>+</collection> <collection name="stroke_to_outline"> <selected id="1"/> <glyph id="1" left="-28" right="28">@@ -1356,6 +1364,8 @@ GNU Lesser General Public License</copyright> <collection unicode="U+74"> <selected id="1"/> <glyph id="1" left="-28" right="28">+ <layer name= "Layer" visible="true">+ </layer> </glyph> </collection> <collection name="theme">@@ -1653,6 +1663,7 @@ GNU Lesser General Public License</copyright> <ligature sequence="t r a c k" replacement="track"/> <ligature sequence="w i d t h" replacement="width"/> <ligature sequence="t h e m e" replacement="theme"/>+<ligature sequence="s t o p" replacement="stop"/> <ligature sequence="n e x t" replacement="next"/> <ligature sequence="p r e v" replacement="prev"/> <ligature sequence="m o v e" replacement="move"/>