From 8d03b07e59d90a97afad9e637b5a2d4abf5f0c78 Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Wed, 23 Jun 2021 10:39:50 +0530 Subject: [PATCH 01/35] Added icons for ColorMode buttons --- data/icons/hicolor/linear-gradient.svg | 1 + data/icons/hicolor/radial-gradient.svg | 1 + data/icons/hicolor/solid-color.svg | 1 + 3 files changed, 3 insertions(+) create mode 100644 data/icons/hicolor/linear-gradient.svg create mode 100644 data/icons/hicolor/radial-gradient.svg create mode 100644 data/icons/hicolor/solid-color.svg diff --git a/data/icons/hicolor/linear-gradient.svg b/data/icons/hicolor/linear-gradient.svg new file mode 100644 index 000000000..95dc44342 --- /dev/null +++ b/data/icons/hicolor/linear-gradient.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/data/icons/hicolor/radial-gradient.svg b/data/icons/hicolor/radial-gradient.svg new file mode 100644 index 000000000..68b13fdfd --- /dev/null +++ b/data/icons/hicolor/radial-gradient.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/data/icons/hicolor/solid-color.svg b/data/icons/hicolor/solid-color.svg new file mode 100644 index 000000000..424c43a50 --- /dev/null +++ b/data/icons/hicolor/solid-color.svg @@ -0,0 +1 @@ + \ No newline at end of file From ab71732ee5397e6b3be74c55ff9bac2cefc363d9 Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Wed, 23 Jun 2021 10:40:56 +0530 Subject: [PATCH 02/35] Added icons are resources --- data/assets.gresource.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/data/assets.gresource.xml b/data/assets.gresource.xml index e6e6359a2..22a350519 100644 --- a/data/assets.gresource.xml +++ b/data/assets.gresource.xml @@ -32,5 +32,9 @@ icons/symbolic/shape-triangle-symbolic.svg icons/symbolic/shape-circle-symbolic.svg icons/symbolic/shape-text-symbolic.svg + + icons/hicolor/solid-color.svg + icons/hicolor/linear-gradient.svg + icons/hicolor/radial-gradient.svg From 3b9eb7fdfff23ea97df6ec1a849fa8acd9b63b21 Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Wed, 23 Jun 2021 10:42:00 +0530 Subject: [PATCH 03/35] Refactor ColorRow The ColorRow widget should be used only for handling widgets in the row. When colors change, the ColorMode class should change colors based on the mode. Also added ColorMode widget --- src/Widgets/ColorRow.vala | 60 ++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 33 deletions(-) diff --git a/src/Widgets/ColorRow.vala b/src/Widgets/ColorRow.vala index 2d39ac5f2..6f8890aec 100644 --- a/src/Widgets/ColorRow.vala +++ b/src/Widgets/ColorRow.vala @@ -33,6 +33,9 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { private Gtk.FlowBox global_colors_flowbox; private ColorField field; private InputField opacity_field; + private ColorMode color_mode_widget; + + public signal void color_changed(string color, double alpha); /* * If the color or alpha are manually set from the ColorPicker. @@ -104,6 +107,7 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { field = new ColorField (window); field.text = Utils.Color.rgba_to_hex (model.color); field.changed.connect (() => { + // Don't do anything if the color change came from the chooser. if (color_set_manually) { return; @@ -119,8 +123,9 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { color_set_manually = true; var new_rgba = Utils.Color.hex_to_rgba (field_hex); - model.color = new_rgba.to_string (); + set_button_color (field_hex, model.alpha); + color_changed(field_hex, opacity_field.entry.value); // Update the chooser widget only if it was already initialized. if (color_chooser_widget != null) { @@ -129,6 +134,7 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { // Reset the bool to allow edits from the color chooser. color_set_manually = false; + }); add (field); @@ -140,21 +146,24 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { opacity_field.entry.value = Math.round ((double) model.alpha / 255 * 100); opacity_field.entry.value_changed.connect (() => { + // Don't do anything if the color change came from the chooser. if (color_set_manually) { return; } - + // Since we will update the color picker, prevent an infinite loop. color_set_manually = true; var alpha = (int) ((double) opacity_field.entry.value / 100 * 255); - model.alpha = alpha; + //model.alpha = alpha; set_button_color (model.color, alpha); + + color_changed(field.text, alpha); // Update the chooser widget only if it was already initialized. if (color_chooser_widget != null) { - set_chooser_color (model.color, alpha); + set_chooser_color (field.text, alpha); } // Reset the bool to allow edits from the color chooser. @@ -214,16 +223,24 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { global_colors_flowbox.add (btn); } - color_grid.attach (color_chooser_widget, 0, 0, 1, 1); - color_grid.attach (global_colors_label, 0, 1, 1, 1); - color_grid.attach (global_colors_flowbox, 0, 2, 1, 1); + color_mode_widget = new ColorMode(model, this); + + color_grid.attach (color_mode_widget.buttons_grid, 0, 0, 1, 1); + color_grid.attach (color_chooser_widget, 0, 1, 1, 1); + color_grid.attach (global_colors_label, 0, 2, 1, 1); + color_grid.attach (global_colors_flowbox, 0, 3, 1, 1); color_grid.show_all (); color_popover.add (color_grid); // Set the chooser color before connecting the signal. set_chooser_color (model.color, model.alpha); - color_chooser_widget.notify["rgba"].connect (on_color_changed); + color_chooser_widget.notify["rgba"].connect (() => { + string new_color = color_chooser_widget.rgba.to_string(); + double alpha = color_chooser_widget.rgba.alpha; + + color_mode_widget.on_color_changed(new_color, alpha); + }); } private int sort_colors_function (Gtk.FlowBoxChild a, Gtk.FlowBoxChild b) { @@ -272,6 +289,7 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { new_rgba.alpha = (double) alpha / 255; var new_color = new_rgba.to_string (); + // TODO: when in gradient mode, add css_style from gradient editor here var css = """.selected-color { background-color: %s; border-color: shade (%s, 0.75); @@ -301,31 +319,6 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { return child; } - private void on_color_changed () { - // The color change came from the input field, prevent an infinite loop. - if (color_set_manually) { - return; - } - - // Prevent visible updated fields like hex and opacity from triggering - // the update of the model values. - color_set_manually = true; - - // Update the model values. - model.color = color_chooser_widget.rgba.to_string (); - model.alpha = (int) (color_chooser_widget.rgba.alpha * 255); - - // Update the UI. - set_button_color (model.color, model.alpha); - field.text = Utils.Color.rgba_to_hex (model.color); - if (model.type == Models.ColorModel.Type.FILL) { - opacity_field.entry.value = Math.round ((double) model.alpha / 255 * 100); - } - - // Allow manual edit from the input fields. - color_set_manually = false; - } - private void on_eyedropper_click () { var eyedropper = new Akira.Utils.ColorPicker (); eyedropper.show_all (); @@ -340,4 +333,5 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { eyedropper.close (); }); } + } From 86689d6c2a307eaccb727eda3a42fa74e837f60c Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Wed, 23 Jun 2021 10:56:59 +0530 Subject: [PATCH 04/35] Added ColorMode widget. This widget consists of 3 buttons that select the Solid, Linear Gradient or Radial Gradient color mode. When the Linear or Radial Gradient mode button is clicked, an EventBox appears. This eventbox an be used to set the stop colors for gradient. --- src/Widgets/ColorMode.vala | 116 +++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 src/Widgets/ColorMode.vala diff --git a/src/Widgets/ColorMode.vala b/src/Widgets/ColorMode.vala new file mode 100644 index 000000000..6d22b8480 --- /dev/null +++ b/src/Widgets/ColorMode.vala @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2021 Alecaddd (https://alecaddd.com) + * + * This file is part of Akira. + * + * Akira 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. + * + * Akira 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 Akira. If not, see . + * + * Authored by: Ashish Shevale + */ + +/* + * Helper class to quickly create a container with a color button and a color + * picker. The color button opens up the GtkColorChooser. + */ + public class Akira.Widgets.ColorMode { + // these buttons will be used to switch between different coloring modes + private Gtk.Button solid_color_button; + private Gtk.Button linear_gradient_button; + private Gtk.Button radial_gradient_button; + // this button will be be used to delete the selected gradient step + private Gtk.Button delete_step_button; + + private GradientEditor gradient_editor; + public string color_mode_type; + + public Gtk.Grid buttons_grid; + private Models.ColorModel model; + private ColorRow color_row; + + public ColorMode (Models.ColorModel _model, ColorRow _color_row) { + model = _model; + color_row = _color_row; + color_mode_type = "solid"; + + color_row.color_changed.connect(on_color_changed); + + init_button_ui (); + } + + private void init_button_ui () { + + solid_color_button = new Gtk.Button.from_icon_name ("solid-color-button", Gtk.IconSize.DND); + solid_color_button.set_tooltip_text (_("Solid Color")); + solid_color_button.can_focus = false; + solid_color_button.valign = Gtk.Align.CENTER; + + linear_gradient_button = new Gtk.Button.from_icon_name ("linear-gradient-button", Gtk.IconSize.DND); + linear_gradient_button.set_tooltip_text (_("Linear Gradient")); + linear_gradient_button.can_focus = false; + linear_gradient_button.valign = Gtk.Align.CENTER; + + radial_gradient_button = new Gtk.Button.from_icon_name ("radial-gradient-button", Gtk.IconSize.DND); + radial_gradient_button.set_tooltip_text (_("Radial Gradient")); + radial_gradient_button.can_focus = false; + radial_gradient_button.valign = Gtk.Align.CENTER; + + delete_step_button = new Gtk.Button.from_icon_name ("user-trash-symbolic"); + delete_step_button.set_tooltip_text(_("Delete Gradient Step")); + delete_step_button.can_focus = false; + delete_step_button.valign = Gtk.Align.CENTER; + delete_step_button.halign = Gtk.Align.CENTER; + + solid_color_button.clicked.connect ( () => mode_button_pressed ("solid")); + linear_gradient_button.clicked.connect ( () => mode_button_pressed ("linear")); + radial_gradient_button.clicked.connect ( () => mode_button_pressed ("radial")); + delete_step_button.clicked.connect (delete_selected_step); + + gradient_editor = new GradientEditor(this); + + Gtk.Separator separator = new Gtk.Separator (Gtk.Orientation.VERTICAL); + separator.hexpand = true; + + buttons_grid = new Gtk.Grid(); + buttons_grid.attach (solid_color_button, 0, 0); + buttons_grid.attach (linear_gradient_button, 1, 0); + buttons_grid.attach (radial_gradient_button, 2, 0); + buttons_grid.attach (separator, 3, 0); + + buttons_grid.attach (gradient_editor, 0, 1, 4, 4); + buttons_grid.attach (delete_step_button, 4, 1); + } + + private void mode_button_pressed(string _color_mode_type) { + color_mode_type = _color_mode_type; + gradient_editor.on_color_mode_changed(); + + } + + public void on_color_changed (string color, double alpha) { + if(color_mode_type == "solid") { + // Update the model values. + model.color = color; + model.alpha = (int) (alpha * 255); + + } else { + gradient_editor.on_color_changed (color, alpha); + } + + } + + private void delete_selected_step () { + + } + + } From d8a1d33d59791d38d34167baaf80e3ed8f88522f Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Wed, 23 Jun 2021 10:59:54 +0530 Subject: [PATCH 05/35] Added GradientEditor widget This is a Gtk.EventBox. It only becomes active in Linear or Radial gradient mode. Clicking on the event box adds a new stop color. --- src/Widgets/GradientEditor.vala | 228 ++++++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 src/Widgets/GradientEditor.vala diff --git a/src/Widgets/GradientEditor.vala b/src/Widgets/GradientEditor.vala new file mode 100644 index 000000000..d0a11601f --- /dev/null +++ b/src/Widgets/GradientEditor.vala @@ -0,0 +1,228 @@ +public class Akira.Widgets.GradientEditor : Gtk.EventBox { + // dimensions of GradientEditor that we will fetch after size has been allocated to it + private int widget_width; + private int widget_height; + private int widget_x; + private int widget_y; + + private ColorMode color_mode_widget; + private bool is_gradient_mode = false; + + private Gdk.RGBA color; + public string css_style; + + // list to store all stop colors in order + private Gee.ArrayList stop_colors; + private StopColor selected_stop_color; + + public GradientEditor(ColorMode _color_mode_widget) { + color_mode_widget = _color_mode_widget; + + set_hexpand(true); + height_request = 35; + + set_events(Gdk.EventMask.BUTTON_PRESS_MASK); + set_above_child(false); + + color.parse("#333"); + + // the stop colors at start and end are fixed. StopColor has been defined at the end + stop_colors = new Gee.ArrayList(); + stop_colors.insert(0, new StopColor("#000", 0)); + stop_colors.insert(1, new StopColor("#fff", 100)); + + selected_stop_color = stop_colors[0]; + + size_allocate.connect( () => { + widget_width = get_allocated_width(); + widget_height = get_allocated_height(); + + draw.connect_after ( (context) => {return redraw_editor(context);}); + + button_press_event.connect( (event) => {return on_button_press(event);}); + + }); + + } + + private bool redraw_editor(Cairo.Context context) { + if (is_gradient_mode) { + double center_y = widget_y + widget_height / 2; + + // line through the center. acts as a guideline for the user to place the stop colors + context.set_source_rgba(0,0,0,1); + context.move_to(widget_x, center_y); + context.line_to(widget_x + widget_width, center_y); + context.stroke(); + + foreach(var item in stop_colors) { + double center_x = widget_x + item.position * widget_width / 100; + double radius = 5; + + // outer circle of light color. + context.set_source_rgba(1,1,1,1); + context.arc(center_x, center_y, radius + 2, 0, 2 * Math.PI); + context.fill(); + + // inner circle of dark color. contrast makes it easier to find stop colors. + if(item.position == selected_stop_color.position) { + context.set_source_rgba(0, 0, 1, 1); + } else { + context.set_source_rgba(0,0,0, 1); + } + context.arc(center_x, center_y, radius, 0, 2 * Math.PI); + context.fill(); + } + + // here we are calling update style with the button_type argument as linear. + // this is because in order to display a gradient at the background, anything other + // than "solid" can be used. + update_style("linear"); + } + + return false; + } + + private bool on_button_press (Gdk.EventButton event) { + if (is_gradient_mode) { + var position = (event.x / widget_width) * 100; + get_stop_color_at(position); + + // trigger redraw for the Editor. This renders the stop color + queue_draw_area(widget_x, widget_y, widget_width, widget_height); + } + + return false; + } + + private bool on_motion_event (Gdk.EventMotion event) { + + return false; + } + + private void on_button_release (Gdk.EventButton event) { + motion_notify_event.disconnect (on_motion_event); + } + + public void on_color_changed(string color, double alpha) { + + } + + private void get_stop_color_at(double position) { + int index; + + if(is_stop_color_at_coordinate(position, out index)) { + selected_stop_color = stop_colors[index]; + } else { + string prev_color = stop_colors[index].color; + stop_colors.insert(index, new StopColor(prev_color, position)); + selected_stop_color = stop_colors[index]; + } + + } + + private bool is_stop_color_at_coordinate(double coordinate, out int index) { + index = 0; + + for(index = 0; index < stop_colors.size; ++index) { + if(stop_colors[index].is_close_to(coordinate)) { + return true; + } else if (stop_colors[index].position > coordinate) { + return false; + } + } + + return false; + } + + private void update_style(string button_type) { + css_style = ""; + string stop_color_string = stop_colors_as_string(); + + if(button_type != "solid") { + is_gradient_mode = true; + } else { + is_gradient_mode = false; + } + + switch(button_type) { + case "solid": + color.parse("#333"); + css_style = """ + *{ + background: none; + background-color: @bg_color; + border: none; + }"""; + break; + + case "linear": + color.parse("#212121"); + css_style = """ + * { + border: 1px solid @fg_color; + background: linear-gradient(to right%s); + }""".printf( stop_color_string); + break; + case "radial": + color.parse("#212121"); + css_style = """ + *{ + border: 1px solid @fg_color; + background: linear-gradient(to right %s); + }""".printf(stop_color_string); + break; + } + + try { + var provider = new Gtk.CssProvider (); + var context = get_style_context (); + + provider.load_from_data (css_style, css_style.length); + context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + } catch (Error e) { + warning ("Style error: %s", e.message); + debug ("%s %s\n", name, css_style); + } + } + + private string stop_colors_as_string() { + string colors_string = ""; + + foreach(StopColor item in stop_colors) { + colors_string += ", " + "%s ".printf( item.color) + item.position.to_string() + "%"; + } + return colors_string; + } + + public void on_color_mode_changed () { + + if(color_mode_widget.color_mode_type != "solid") { + is_gradient_mode = true; + } else { + is_gradient_mode = false; + } + + update_style(color_mode_widget.color_mode_type); + } + + private class StopColor { + public string color; + // position denotes position of stop color in percentage + public double position; + + public StopColor(string _color, double _position) { + color = _color; + position = _position; + } + + public bool is_close_to (double other_position) { + // there has to be a min distance between 2 stop colors to easily select them + if( (position - other_position).abs() < 1 ) { + return true; + } + + return false; + } + } +} From ef4dd677a7ff8f121eba6e30f3a8870a0e6773bf Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Wed, 23 Jun 2021 11:01:51 +0530 Subject: [PATCH 06/35] Updated meson.build to build ColorMode and GradientEditor --- src/meson.build | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/meson.build b/src/meson.build index 402bd3b23..fe0754b8a 100644 --- a/src/meson.build +++ b/src/meson.build @@ -68,6 +68,8 @@ sources = files( 'Widgets/PanelSeparator.vala', 'Widgets/RoundedColorButton.vala', 'Widgets/ZoomButton.vala', + 'Widgets/ColorMode.vala', + 'Widgets/GradientEditor.vala', 'Models/ColorModel.vala', 'Models/ExportModel.vala', From 0f1eeceb555fde34541364afe981e88e62f8b7bb Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Wed, 23 Jun 2021 12:02:40 +0530 Subject: [PATCH 07/35] Added functionality to delete a stop color --- src/Widgets/ColorMode.vala | 11 +++++-- src/Widgets/GradientEditor.vala | 56 ++++++++++++++++++--------------- 2 files changed, 38 insertions(+), 29 deletions(-) diff --git a/src/Widgets/ColorMode.vala b/src/Widgets/ColorMode.vala index 6d22b8480..3abe8b409 100644 --- a/src/Widgets/ColorMode.vala +++ b/src/Widgets/ColorMode.vala @@ -74,7 +74,7 @@ solid_color_button.clicked.connect ( () => mode_button_pressed ("solid")); linear_gradient_button.clicked.connect ( () => mode_button_pressed ("linear")); radial_gradient_button.clicked.connect ( () => mode_button_pressed ("radial")); - delete_step_button.clicked.connect (delete_selected_step); + delete_step_button.clicked.connect (on_delete_button_pressed); gradient_editor = new GradientEditor(this); @@ -109,8 +109,13 @@ } - private void delete_selected_step () { - + public string get_css_style() { + return gradient_editor.css_style; + } + + private void on_delete_button_pressed () { + print("calling delete stop\n"); + gradient_editor.delete_selected_step(); } } diff --git a/src/Widgets/GradientEditor.vala b/src/Widgets/GradientEditor.vala index d0a11601f..51c211ff5 100644 --- a/src/Widgets/GradientEditor.vala +++ b/src/Widgets/GradientEditor.vala @@ -8,7 +8,6 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { private ColorMode color_mode_widget; private bool is_gradient_mode = false; - private Gdk.RGBA color; public string css_style; // list to store all stop colors in order @@ -24,8 +23,6 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { set_events(Gdk.EventMask.BUTTON_PRESS_MASK); set_above_child(false); - color.parse("#333"); - // the stop colors at start and end are fixed. StopColor has been defined at the end stop_colors = new Gee.ArrayList(); stop_colors.insert(0, new StopColor("#000", 0)); @@ -105,7 +102,27 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { } public void on_color_changed(string color, double alpha) { - + int index = stop_colors.index_of(selected_stop_color); + + stop_colors[index].color = color; + + queue_draw_area(widget_x, widget_y, widget_width, widget_height); + } + + public void delete_selected_step () { + // get the index of selected step + int index = stop_colors.index_of(selected_stop_color); + + // the first and stop colors are fixed and should not be deleted + if(index == 0 || index == stop_colors.size - 1) { + return; + } + + selected_stop_color = stop_colors[index-1]; + stop_colors.remove_at(index); + + // redraw the new widget + queue_draw_area(widget_x, widget_y, widget_width, widget_height); } private void get_stop_color_at(double position) { @@ -147,38 +164,25 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { switch(button_type) { case "solid": - color.parse("#333"); - css_style = """ - *{ - background: none; - background-color: @bg_color; - border: none; - }"""; + css_style = "@bg_color"; break; - case "linear": - color.parse("#212121"); - css_style = """ - * { - border: 1px solid @fg_color; - background: linear-gradient(to right%s); - }""".printf( stop_color_string); + css_style = """linear-gradient(to right %s)""".printf(stop_color_string); break; case "radial": - color.parse("#212121"); - css_style = """ - *{ - border: 1px solid @fg_color; - background: linear-gradient(to right %s); - }""".printf(stop_color_string); - break; + css_style = """radial-gradient(circle farthest-side %s)""".printf(stop_color_string); + break; } try { var provider = new Gtk.CssProvider (); var context = get_style_context (); + + var editor_css_style = """*{ + background: %s + }""".printf(css_style); - provider.load_from_data (css_style, css_style.length); + provider.load_from_data (editor_css_style, editor_css_style.length); context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); } catch (Error e) { warning ("Style error: %s", e.message); From 508b6171c50ae80904de529aedc821ac86ef4d70 Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Wed, 23 Jun 2021 13:29:01 +0530 Subject: [PATCH 08/35] Functionality to move StopColors using cursor --- src/Widgets/ColorMode.vala | 6 ----- src/Widgets/GradientEditor.vala | 40 +++++++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/src/Widgets/ColorMode.vala b/src/Widgets/ColorMode.vala index 3abe8b409..0ae8f2e09 100644 --- a/src/Widgets/ColorMode.vala +++ b/src/Widgets/ColorMode.vala @@ -18,11 +18,6 @@ * * Authored by: Ashish Shevale */ - -/* - * Helper class to quickly create a container with a color button and a color - * picker. The color button opens up the GtkColorChooser. - */ public class Akira.Widgets.ColorMode { // these buttons will be used to switch between different coloring modes private Gtk.Button solid_color_button; @@ -114,7 +109,6 @@ } private void on_delete_button_pressed () { - print("calling delete stop\n"); gradient_editor.delete_selected_step(); } diff --git a/src/Widgets/GradientEditor.vala b/src/Widgets/GradientEditor.vala index 51c211ff5..9b2b7b2f3 100644 --- a/src/Widgets/GradientEditor.vala +++ b/src/Widgets/GradientEditor.vala @@ -1,4 +1,24 @@ -public class Akira.Widgets.GradientEditor : Gtk.EventBox { +/* + * Copyright (c) 2021 Alecaddd (https://alecaddd.com) + * + * This file is part of Akira. + * + * Akira 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. + * + * Akira 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 Akira. If not, see . + * + * Authored by: Ashish Shevale + */ + public class Akira.Widgets.GradientEditor : Gtk.EventBox { // dimensions of GradientEditor that we will fetch after size has been allocated to it private int widget_width; private int widget_height; @@ -37,6 +57,7 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { draw.connect_after ( (context) => {return redraw_editor(context);}); button_press_event.connect( (event) => {return on_button_press(event);}); + button_release_event.connect ( (event) => {return on_button_release(event); }); }); @@ -89,16 +110,27 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { queue_draw_area(widget_x, widget_y, widget_width, widget_height); } + // start the on motion event handler + // this will drag the stop color around as long as the button is pressed + motion_notify_event.connect( on_motion_event ); + return false; } private bool on_motion_event (Gdk.EventMotion event) { - + int index = stop_colors.index_of(selected_stop_color); + + stop_colors[index].position = (event.x / widget_width) * 100; + + queue_draw_area(widget_x, widget_y, widget_width, widget_height); return false; } - - private void on_button_release (Gdk.EventButton event) { + + private bool on_button_release (Gdk.EventButton event) { + // after user releases the button, stop dragging the stop color motion_notify_event.disconnect (on_motion_event); + + return false; } public void on_color_changed(string color, double alpha) { From e326245bfc1d15c98e0aaf8213909bacf904c497 Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Wed, 23 Jun 2021 13:34:20 +0530 Subject: [PATCH 09/35] Bug fixes in moving StopColors --- src/Widgets/GradientEditor.vala | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Widgets/GradientEditor.vala b/src/Widgets/GradientEditor.vala index 9b2b7b2f3..8441dac97 100644 --- a/src/Widgets/GradientEditor.vala +++ b/src/Widgets/GradientEditor.vala @@ -118,11 +118,18 @@ } private bool on_motion_event (Gdk.EventMotion event) { - int index = stop_colors.index_of(selected_stop_color); - - stop_colors[index].position = (event.x / widget_width) * 100; + if(is_gradient_mode) { + int index = stop_colors.index_of(selected_stop_color); + + if(index == 0 || index == stop_colors.size - 1) { + return false; + } + + stop_colors[index].position = (event.x / widget_width) * 100; + + queue_draw_area(widget_x, widget_y, widget_width, widget_height); + } - queue_draw_area(widget_x, widget_y, widget_width, widget_height); return false; } From b05d96e8ef7b19ff29a8841fe5c89b5ef50230b2 Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Wed, 23 Jun 2021 13:53:01 +0530 Subject: [PATCH 10/35] Accessibility fixes when interacting with StopColors --- src/Widgets/ColorMode.vala | 3 ++- src/Widgets/GradientEditor.vala | 10 +++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Widgets/ColorMode.vala b/src/Widgets/ColorMode.vala index 0ae8f2e09..464ee2c0e 100644 --- a/src/Widgets/ColorMode.vala +++ b/src/Widgets/ColorMode.vala @@ -65,6 +65,7 @@ delete_step_button.can_focus = false; delete_step_button.valign = Gtk.Align.CENTER; delete_step_button.halign = Gtk.Align.CENTER; + delete_step_button.margin = 10; solid_color_button.clicked.connect ( () => mode_button_pressed ("solid")); linear_gradient_button.clicked.connect ( () => mode_button_pressed ("linear")); @@ -82,7 +83,7 @@ buttons_grid.attach (radial_gradient_button, 2, 0); buttons_grid.attach (separator, 3, 0); - buttons_grid.attach (gradient_editor, 0, 1, 4, 4); + buttons_grid.attach (gradient_editor, 0, 1, 4, 1); buttons_grid.attach (delete_step_button, 4, 1); } diff --git a/src/Widgets/GradientEditor.vala b/src/Widgets/GradientEditor.vala index 8441dac97..689e3fc7b 100644 --- a/src/Widgets/GradientEditor.vala +++ b/src/Widgets/GradientEditor.vala @@ -181,7 +181,7 @@ index = 0; for(index = 0; index < stop_colors.size; ++index) { - if(stop_colors[index].is_close_to(coordinate)) { + if(stop_colors[index].is_close_to(coordinate, widget_width)) { return true; } else if (stop_colors[index].position > coordinate) { return false; @@ -259,9 +259,13 @@ position = _position; } - public bool is_close_to (double other_position) { + public bool is_close_to (double other_position, double width) { + var distance = (position - other_position).abs(); + distance = (distance * width ) / 100; // there has to be a min distance between 2 stop colors to easily select them - if( (position - other_position).abs() < 1 ) { + // this distance is taken as 7 because that is the radius the StopColor is drawn + // in the gradient editor + if( distance <= 7 ) { return true; } From ee86fca403389e6cb3b574c6bd3c1562da83e2d9 Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Wed, 23 Jun 2021 22:45:30 +0530 Subject: [PATCH 11/35] Displaying gradients in CanvasItem --- src/Lib/Components/Fill.vala | 7 ++++ src/Lib/Components/Fills.vala | 21 +++++++++- src/Models/ColorModel.vala | 29 +++++++++++++- src/Widgets/ColorMode.vala | 8 +--- src/Widgets/GradientEditor.vala | 69 ++++++++++++++++++++++++++------- 5 files changed, 110 insertions(+), 24 deletions(-) diff --git a/src/Lib/Components/Fill.vala b/src/Lib/Components/Fill.vala index 6bdeabdee..99b127fff 100644 --- a/src/Lib/Components/Fill.vala +++ b/src/Lib/Components/Fill.vala @@ -29,6 +29,7 @@ public class Akira.Lib.Components.Fill : Component { public int id { get; set; } public Gdk.RGBA color { get; set; } + public Cairo.Pattern gradient_pattern { get; set; } // Store the hexadecimal string version of the color (E.g.: #FF00CC) public string hex { get; set; } @@ -42,6 +43,7 @@ public class Akira.Lib.Components.Fill : Component { color = init_color; hex = color.to_string (); alpha = 255; + gradient_pattern = new Cairo.Pattern.linear(0,0,0,0); // Listen for changed to the fill attributes to properly trigger the color generation. this.notify["color"].connect (() => { @@ -59,6 +61,11 @@ public class Akira.Lib.Components.Fill : Component { rgba.alpha = ((double) alpha) / 255; color = rgba; }); + + this.notify["gradient-pattern"].connect (() => { + fills.reload (); + }); + } public void remove () { diff --git a/src/Lib/Components/Fills.vala b/src/Lib/Components/Fills.vala index cbf92e862..8dca80d4b 100644 --- a/src/Lib/Components/Fills.vala +++ b/src/Lib/Components/Fills.vala @@ -51,8 +51,8 @@ public class Akira.Lib.Components.Fills : Component { id++; // Trigger the generation of the fill color. - reload (); - + reload (); + return new_fill; } @@ -68,8 +68,10 @@ public class Akira.Lib.Components.Fills : Component { if (count () == 0) { if (item is Items.CanvasArtboard) { ((Items.CanvasArtboard) item).background.set ("fill-color-rgba", null); + ((Items.CanvasArtboard) item).background.set ("fill-pattern", null); } else { item.set ("fill-color-rgba", null); + item.set ("fill-pattern", null); } return; } @@ -86,6 +88,21 @@ public class Akira.Lib.Components.Fills : Component { continue; } + var stop_colors = 0; + fill.gradient_pattern.get_color_stop_count(out stop_colors); + + // if for this fill, either of the gradient modes have been selected, + // the stop_colors value would not be zero. + if(stop_colors != 0 && has_colors == false) { + if(item is Items.CanvasArtboard) { + ((Items.CanvasArtboard) item).background.set ("fill-pattern", fill.gradient_pattern); + } else { + item.set("fill-pattern", fill.gradient_pattern); + } + + // since we dont have the functionality of blending gradients, + return; + } // Set the new blended color. rgba_fill = Utils.Color.blend_colors (rgba_fill, fill.color); has_colors = true; diff --git a/src/Models/ColorModel.vala b/src/Models/ColorModel.vala index 059fcce9a..7ab49f820 100644 --- a/src/Models/ColorModel.vala +++ b/src/Models/ColorModel.vala @@ -32,6 +32,17 @@ public class Akira.Models.ColorModel : GLib.Object { FILL, BORDER } + + public Cairo.Pattern pattern { + owned get { + return pattern; + } + set { + if(type == Type.FILL) { + fill.gradient_pattern = value; + } + } + } public string color { owned get { @@ -83,7 +94,23 @@ public class Akira.Models.ColorModel : GLib.Object { border.size = value; } } - + + public double width { + get { + double width; + fill.item.size.get("width", out width); + return width; + } + } + + public double height { + get { + double height; + fill.item.get("height", out height); + return height; + } + } + public ColorModel (Lib.Components.Fill? fill, Lib.Components.Border? border = null) { type = fill != null ? Type.FILL : Type.BORDER; this.fill = fill; diff --git a/src/Widgets/ColorMode.vala b/src/Widgets/ColorMode.vala index 464ee2c0e..0ec48478f 100644 --- a/src/Widgets/ColorMode.vala +++ b/src/Widgets/ColorMode.vala @@ -72,7 +72,7 @@ radial_gradient_button.clicked.connect ( () => mode_button_pressed ("radial")); delete_step_button.clicked.connect (on_delete_button_pressed); - gradient_editor = new GradientEditor(this); + gradient_editor = new GradientEditor(this, model); Gtk.Separator separator = new Gtk.Separator (Gtk.Orientation.VERTICAL); separator.hexpand = true; @@ -104,11 +104,7 @@ } } - - public string get_css_style() { - return gradient_editor.css_style; - } - + private void on_delete_button_pressed () { gradient_editor.delete_selected_step(); } diff --git a/src/Widgets/GradientEditor.vala b/src/Widgets/GradientEditor.vala index 689e3fc7b..4a69430d2 100644 --- a/src/Widgets/GradientEditor.vala +++ b/src/Widgets/GradientEditor.vala @@ -26,16 +26,19 @@ private int widget_y; private ColorMode color_mode_widget; + private Models.ColorModel model; private bool is_gradient_mode = false; - public string css_style; - // list to store all stop colors in order private Gee.ArrayList stop_colors; private StopColor selected_stop_color; + + // Cairo.Pattern to color the Canvas.Item + private Cairo.Pattern gradient_pattern; - public GradientEditor(ColorMode _color_mode_widget) { + public GradientEditor(ColorMode _color_mode_widget, Models.ColorModel _model) { color_mode_widget = _color_mode_widget; + model = _model; set_hexpand(true); height_request = 35; @@ -95,7 +98,12 @@ // here we are calling update style with the button_type argument as linear. // this is because in order to display a gradient at the background, anything other // than "solid" can be used. - update_style("linear"); + //update_style("linear"); + if(color_mode_widget.color_mode_type == "linear") { + update_style("linear"); + } else { + update_style("radial"); + } } return false; @@ -192,7 +200,7 @@ } private void update_style(string button_type) { - css_style = ""; + string css_style = ""; string stop_color_string = stop_colors_as_string(); if(button_type != "solid") { @@ -201,16 +209,10 @@ is_gradient_mode = false; } - switch(button_type) { - case "solid": - css_style = "@bg_color"; - break; - case "linear": - css_style = """linear-gradient(to right %s)""".printf(stop_color_string); - break; - case "radial": - css_style = """radial-gradient(circle farthest-side %s)""".printf(stop_color_string); - break; + if(button_type == "solid") { + css_style = "@bg_color"; + } else { + css_style = """linear-gradient(to right %s)""".printf(stop_color_string); } try { @@ -223,10 +225,13 @@ provider.load_from_data (editor_css_style, editor_css_style.length); context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + } catch (Error e) { warning ("Style error: %s", e.message); debug ("%s %s\n", name, css_style); } + + create_gradient_pattern(button_type); } private string stop_colors_as_string() { @@ -248,11 +253,45 @@ update_style(color_mode_widget.color_mode_type); } + + private void create_gradient_pattern (string color_mode) { + double item_height, item_width; + model.get("height", out item_height); + model.get("width", out item_width); + + if(color_mode == "solid") { + // for solid color, create an empty pattern. In Fills, we check if stop colors exists + // for this pattern. If they dont, then the Pattern is not applied + gradient_pattern = new Cairo.Pattern.linear(0,0,0,0); + model.pattern = gradient_pattern; + return; + } else if(color_mode == "linear") { + gradient_pattern = new Cairo.Pattern.linear(0, 0, + item_width, item_height); + } else { + int radius = (int) Math.sqrt( item_width * item_width + item_height * item_height); + gradient_pattern = new Cairo.Pattern.radial(0, 0, 0, 0, 0, radius); + } + + for(int index = 0; index < stop_colors.size; ++index) { + var stop_color = stop_colors[index]; + + var rgba = Gdk.RGBA(); + rgba.parse(stop_color.color); + + double offset = stop_color.position / 100; + + gradient_pattern.add_color_stop_rgba(offset, rgba.red, rgba.green, rgba.blue, 1); + } + + model.pattern = gradient_pattern; + } private class StopColor { public string color; // position denotes position of stop color in percentage public double position; + // TODO: add alpha here public StopColor(string _color, double _position) { color = _color; From 06e30b220c3c3a8ba3d0c4d990622afd44bad9c1 Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Wed, 23 Jun 2021 22:51:29 +0530 Subject: [PATCH 12/35] Minor bugfixes related to delete button --- src/Widgets/ColorMode.vala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Widgets/ColorMode.vala b/src/Widgets/ColorMode.vala index 0ec48478f..b0e6ec43c 100644 --- a/src/Widgets/ColorMode.vala +++ b/src/Widgets/ColorMode.vala @@ -106,7 +106,9 @@ } private void on_delete_button_pressed () { - gradient_editor.delete_selected_step(); + if(color_mode_type != "solid") { + gradient_editor.delete_selected_step(); + } } } From 5acc76b79ed8b75792637b61af7d01d5bf6ab243 Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Sat, 26 Jun 2021 11:55:47 +0530 Subject: [PATCH 13/35] Alpha values to StopColors --- src/Widgets/GradientEditor.vala | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/src/Widgets/GradientEditor.vala b/src/Widgets/GradientEditor.vala index 4a69430d2..690531b95 100644 --- a/src/Widgets/GradientEditor.vala +++ b/src/Widgets/GradientEditor.vala @@ -48,8 +48,8 @@ // the stop colors at start and end are fixed. StopColor has been defined at the end stop_colors = new Gee.ArrayList(); - stop_colors.insert(0, new StopColor("#000", 0)); - stop_colors.insert(1, new StopColor("#fff", 100)); + stop_colors.insert(0, new StopColor("#000", 1, 0)); + stop_colors.insert(1, new StopColor("#fff", 1, 100)); selected_stop_color = stop_colors[0]; @@ -152,6 +152,7 @@ int index = stop_colors.index_of(selected_stop_color); stop_colors[index].color = color; + stop_colors[index].alpha = alpha; queue_draw_area(widget_x, widget_y, widget_width, widget_height); } @@ -179,7 +180,8 @@ selected_stop_color = stop_colors[index]; } else { string prev_color = stop_colors[index].color; - stop_colors.insert(index, new StopColor(prev_color, position)); + double prev_alpha = stop_colors[index].alpha; + stop_colors.insert(index, new StopColor(prev_color, prev_alpha, position)); selected_stop_color = stop_colors[index]; } @@ -214,7 +216,7 @@ } else { css_style = """linear-gradient(to right %s)""".printf(stop_color_string); } - + try { var provider = new Gtk.CssProvider (); var context = get_style_context (); @@ -238,8 +240,10 @@ string colors_string = ""; foreach(StopColor item in stop_colors) { - colors_string += ", " + "%s ".printf( item.color) + item.position.to_string() + "%"; + //colors_string += ", " + "%s ".printf( item.color) + item.position.to_string() + "%"; + colors_string += "," + item.to_string(); } + return colors_string; } @@ -281,7 +285,7 @@ double offset = stop_color.position / 100; - gradient_pattern.add_color_stop_rgba(offset, rgba.red, rgba.green, rgba.blue, 1); + gradient_pattern.add_color_stop_rgba(offset, rgba.red, rgba.green, rgba.blue, stop_color.alpha); } model.pattern = gradient_pattern; @@ -291,11 +295,12 @@ public string color; // position denotes position of stop color in percentage public double position; - // TODO: add alpha here + public double alpha; - public StopColor(string _color, double _position) { + public StopColor(string _color, double _alpha, double _position) { color = _color; position = _position; + alpha = _alpha; } public bool is_close_to (double other_position, double width) { @@ -310,5 +315,17 @@ return false; } + + public string to_string() { + Gdk.RGBA color_rgba = Gdk.RGBA(); + color_rgba.parse(color); + + int red = (int) (color_rgba.red * 255); + int green = (int) (color_rgba.green * 255); + int blue = (int) (color_rgba.blue * 255); + int alpha = (int) (alpha * 255); + + return """ rgba(%d, %d, %d, %d) %f""".printf(red, green, blue, alpha, position) + "%"; + } } } From 5051082a8b445c942a510682d379ffe6e4f36b9b Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Sat, 26 Jun 2021 13:33:22 +0530 Subject: [PATCH 14/35] Use EventBus signals to change color and gradient --- src/Services/EventBus.vala | 4 +++ src/Widgets/ColorMode.vala | 25 +++------------ src/Widgets/ColorRow.vala | 11 +++---- src/Widgets/GradientEditor.vala | 57 ++++++++++++--------------------- 4 files changed, 35 insertions(+), 62 deletions(-) diff --git a/src/Services/EventBus.vala b/src/Services/EventBus.vala index 4555ec70b..bba983b1c 100644 --- a/src/Services/EventBus.vala +++ b/src/Services/EventBus.vala @@ -51,6 +51,10 @@ public class Akira.Services.EventBus : Object { public signal void update_snaps_color (); public signal void update_snap_decorators (); + // this signal will be triggered every time color gets modified + public signal void color_changed(string color, double alpha); + public signal void color_mode_changed(string color_mode); + // Options panel signals. public signal void align_items (string align_action); public signal void init_state_coords (); diff --git a/src/Widgets/ColorMode.vala b/src/Widgets/ColorMode.vala index b0e6ec43c..22067b615 100644 --- a/src/Widgets/ColorMode.vala +++ b/src/Widgets/ColorMode.vala @@ -31,14 +31,12 @@ public Gtk.Grid buttons_grid; private Models.ColorModel model; - private ColorRow color_row; + private Window window; - public ColorMode (Models.ColorModel _model, ColorRow _color_row) { + public ColorMode (Models.ColorModel _model, Window _window) { model = _model; - color_row = _color_row; color_mode_type = "solid"; - - color_row.color_changed.connect(on_color_changed); + window = _window; init_button_ui (); } @@ -72,7 +70,7 @@ radial_gradient_button.clicked.connect ( () => mode_button_pressed ("radial")); delete_step_button.clicked.connect (on_delete_button_pressed); - gradient_editor = new GradientEditor(this, model); + gradient_editor = new GradientEditor(window, model); Gtk.Separator separator = new Gtk.Separator (Gtk.Orientation.VERTICAL); separator.hexpand = true; @@ -89,20 +87,7 @@ private void mode_button_pressed(string _color_mode_type) { color_mode_type = _color_mode_type; - gradient_editor.on_color_mode_changed(); - - } - - public void on_color_changed (string color, double alpha) { - if(color_mode_type == "solid") { - // Update the model values. - model.color = color; - model.alpha = (int) (alpha * 255); - - } else { - gradient_editor.on_color_changed (color, alpha); - } - + window.event_bus.color_mode_changed(color_mode_type); } private void on_delete_button_pressed () { diff --git a/src/Widgets/ColorRow.vala b/src/Widgets/ColorRow.vala index 6f8890aec..8e2ca44ea 100644 --- a/src/Widgets/ColorRow.vala +++ b/src/Widgets/ColorRow.vala @@ -35,8 +35,6 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { private InputField opacity_field; private ColorMode color_mode_widget; - public signal void color_changed(string color, double alpha); - /* * If the color or alpha are manually set from the ColorPicker. * If true, the ColorChooserWidget doesn't need to be updated. @@ -125,7 +123,7 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { var new_rgba = Utils.Color.hex_to_rgba (field_hex); set_button_color (field_hex, model.alpha); - color_changed(field_hex, opacity_field.entry.value); + window.event_bus.color_changed(field_hex, opacity_field.entry.value); // Update the chooser widget only if it was already initialized. if (color_chooser_widget != null) { @@ -159,7 +157,7 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { //model.alpha = alpha; set_button_color (model.color, alpha); - color_changed(field.text, alpha); + window.event_bus.color_changed(field.text, alpha); // Update the chooser widget only if it was already initialized. if (color_chooser_widget != null) { @@ -223,7 +221,7 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { global_colors_flowbox.add (btn); } - color_mode_widget = new ColorMode(model, this); + color_mode_widget = new ColorMode(model, this.window); color_grid.attach (color_mode_widget.buttons_grid, 0, 0, 1, 1); color_grid.attach (color_chooser_widget, 0, 1, 1, 1); @@ -239,7 +237,8 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { string new_color = color_chooser_widget.rgba.to_string(); double alpha = color_chooser_widget.rgba.alpha; - color_mode_widget.on_color_changed(new_color, alpha); + //color_mode_widget.on_color_changed(new_color, alpha); + window.event_bus.color_changed(new_color, alpha); }); } diff --git a/src/Widgets/GradientEditor.vala b/src/Widgets/GradientEditor.vala index 690531b95..2b1e49b4f 100644 --- a/src/Widgets/GradientEditor.vala +++ b/src/Widgets/GradientEditor.vala @@ -25,9 +25,9 @@ private int widget_x; private int widget_y; - private ColorMode color_mode_widget; + private Window window; private Models.ColorModel model; - private bool is_gradient_mode = false; + private string color_mode_type; // list to store all stop colors in order private Gee.ArrayList stop_colors; @@ -36,9 +36,10 @@ // Cairo.Pattern to color the Canvas.Item private Cairo.Pattern gradient_pattern; - public GradientEditor(ColorMode _color_mode_widget, Models.ColorModel _model) { - color_mode_widget = _color_mode_widget; + public GradientEditor(Window _window, Models.ColorModel _model) { + window = _window; model = _model; + color_mode_type = "solid"; set_hexpand(true); height_request = 35; @@ -61,13 +62,16 @@ button_press_event.connect( (event) => {return on_button_press(event);}); button_release_event.connect ( (event) => {return on_button_release(event); }); + + window.event_bus.color_mode_changed.connect(on_color_mode_changed); + window.event_bus.color_changed.connect(on_color_changed); }); } private bool redraw_editor(Cairo.Context context) { - if (is_gradient_mode) { + if (color_mode_type != "solid") { double center_y = widget_y + widget_height / 2; // line through the center. acts as a guideline for the user to place the stop colors @@ -95,22 +99,14 @@ context.fill(); } - // here we are calling update style with the button_type argument as linear. - // this is because in order to display a gradient at the background, anything other - // than "solid" can be used. - //update_style("linear"); - if(color_mode_widget.color_mode_type == "linear") { - update_style("linear"); - } else { - update_style("radial"); - } + update_style(); } return false; } private bool on_button_press (Gdk.EventButton event) { - if (is_gradient_mode) { + if (color_mode_type != "solid") { var position = (event.x / widget_width) * 100; get_stop_color_at(position); @@ -126,7 +122,7 @@ } private bool on_motion_event (Gdk.EventMotion event) { - if(is_gradient_mode) { + if(color_mode_type != "solid") { int index = stop_colors.index_of(selected_stop_color); if(index == 0 || index == stop_colors.size - 1) { @@ -201,17 +197,11 @@ return false; } - private void update_style(string button_type) { + private void update_style() { string css_style = ""; string stop_color_string = stop_colors_as_string(); - if(button_type != "solid") { - is_gradient_mode = true; - } else { - is_gradient_mode = false; - } - - if(button_type == "solid") { + if(color_mode_type == "solid") { css_style = "@bg_color"; } else { css_style = """linear-gradient(to right %s)""".printf(stop_color_string); @@ -233,43 +223,38 @@ debug ("%s %s\n", name, css_style); } - create_gradient_pattern(button_type); + create_gradient_pattern(); } private string stop_colors_as_string() { string colors_string = ""; foreach(StopColor item in stop_colors) { - //colors_string += ", " + "%s ".printf( item.color) + item.position.to_string() + "%"; colors_string += "," + item.to_string(); } return colors_string; } - public void on_color_mode_changed () { + private void on_color_mode_changed (string _color_mode_type) { - if(color_mode_widget.color_mode_type != "solid") { - is_gradient_mode = true; - } else { - is_gradient_mode = false; - } + color_mode_type = _color_mode_type; - update_style(color_mode_widget.color_mode_type); + update_style(); } - private void create_gradient_pattern (string color_mode) { + private void create_gradient_pattern () { double item_height, item_width; model.get("height", out item_height); model.get("width", out item_width); - if(color_mode == "solid") { + if(color_mode_type == "solid") { // for solid color, create an empty pattern. In Fills, we check if stop colors exists // for this pattern. If they dont, then the Pattern is not applied gradient_pattern = new Cairo.Pattern.linear(0,0,0,0); model.pattern = gradient_pattern; return; - } else if(color_mode == "linear") { + } else if(color_mode_type == "linear") { gradient_pattern = new Cairo.Pattern.linear(0, 0, item_width, item_height); } else { From dd179c7761f4191c9ad1b8de0b07aa2404d796d7 Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Tue, 29 Jun 2021 13:43:32 +0530 Subject: [PATCH 15/35] Create DirectionLine class and draw when color mode changes --- src/Lib/Managers/NobManager.vala | 4 ++- src/Widgets/DirectionLine.vala | 58 ++++++++++++++++++++++++++++++++ src/Widgets/GradientEditor.vala | 7 ++-- src/meson.build | 1 + 4 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 src/Widgets/DirectionLine.vala diff --git a/src/Lib/Managers/NobManager.vala b/src/Lib/Managers/NobManager.vala index ce8be6e71..1bbd95366 100644 --- a/src/Lib/Managers/NobManager.vala +++ b/src/Lib/Managers/NobManager.vala @@ -45,7 +45,9 @@ public class Akira.Lib.Managers.NobManager : Object { BOTTOM_CENTER, BOTTOM_LEFT, LEFT_CENTER, - ROTATE + ROTATE, + GRADIENT_START, + GRADIENT_END } /* diff --git a/src/Widgets/DirectionLine.vala b/src/Widgets/DirectionLine.vala new file mode 100644 index 000000000..a66974457 --- /dev/null +++ b/src/Widgets/DirectionLine.vala @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021 Alecaddd (https://alecaddd.com) + * + * This file is part of Akira. + * + * Akira 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. + * + * Akira 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 Akira. If not, see . + * + * Authored by: Ashish Shevale +*/ +public class Akira.Widgets.DirectionLine { + private Lib.Selection.Nob start_nob; + private Lib.Selection.Nob end_nob; + + public DirectionLine (Window window, GradientEditor gradient_editor) { + var root = window.main_window.main_canvas.canvas.get_root_item(); + start_nob = new Lib.Selection.Nob(root, Lib.Managers.NobManager.Nob.GRADIENT_START); + end_nob = new Lib.Selection.Nob(root, Lib.Managers.NobManager.Nob.GRADIENT_END); + + start_nob.set_rectangle(); + end_nob.set_rectangle(); + + start_nob.update_state(Cairo.Matrix.identity(), 50, 50, false); + end_nob.update_state(Cairo.Matrix.identity(), 150, 150, false); + + window.event_bus.color_mode_changed.connect(update_visibility); + } + + private void update_visibility(string color_mode) { + if(color_mode == "solid") { + var start_x = start_nob.center_x; + var start_y = start_nob.center_y; + var end_x = end_nob.center_x; + var end_y = end_nob.center_y; + + start_nob.update_state(Cairo.Matrix.identity(), start_x, start_y, false); + end_nob.update_state(Cairo.Matrix.identity(), end_x, end_y, false); + } else { + var start_x = start_nob.center_x; + var start_y = start_nob.center_y; + var end_x = end_nob.center_x; + var end_y = end_nob.center_y; + + start_nob.update_state(Cairo.Matrix.identity(), start_x, start_y, true); + end_nob.update_state(Cairo.Matrix.identity(), end_x, end_y, true); + } + } +} \ No newline at end of file diff --git a/src/Widgets/GradientEditor.vala b/src/Widgets/GradientEditor.vala index 2b1e49b4f..08c22bf7a 100644 --- a/src/Widgets/GradientEditor.vala +++ b/src/Widgets/GradientEditor.vala @@ -18,7 +18,7 @@ * * Authored by: Ashish Shevale */ - public class Akira.Widgets.GradientEditor : Gtk.EventBox { +public class Akira.Widgets.GradientEditor : Gtk.EventBox { // dimensions of GradientEditor that we will fetch after size has been allocated to it private int widget_width; private int widget_height; @@ -35,12 +35,15 @@ // Cairo.Pattern to color the Canvas.Item private Cairo.Pattern gradient_pattern; + private DirectionLine direction_line; public GradientEditor(Window _window, Models.ColorModel _model) { window = _window; model = _model; color_mode_type = "solid"; + direction_line = new DirectionLine(_window, this); + set_hexpand(true); height_request = 35; @@ -237,9 +240,7 @@ } private void on_color_mode_changed (string _color_mode_type) { - color_mode_type = _color_mode_type; - update_style(); } diff --git a/src/meson.build b/src/meson.build index fe0754b8a..2a8fa566c 100644 --- a/src/meson.build +++ b/src/meson.build @@ -70,6 +70,7 @@ sources = files( 'Widgets/ZoomButton.vala', 'Widgets/ColorMode.vala', 'Widgets/GradientEditor.vala', + 'Widgets/DirectionLine.vala', 'Models/ColorModel.vala', 'Models/ExportModel.vala', From 114595d3dade380908ee0883670ecda264e7bded Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Tue, 29 Jun 2021 14:38:56 +0530 Subject: [PATCH 16/35] Set initial position direction line --- src/Lib/Selection/Nob.vala | 4 +++- src/Widgets/DirectionLine.vala | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/Lib/Selection/Nob.vala b/src/Lib/Selection/Nob.vala index 8962883a6..70dd948e4 100644 --- a/src/Lib/Selection/Nob.vala +++ b/src/Lib/Selection/Nob.vala @@ -79,7 +79,9 @@ public class Akira.Lib.Selection.Nob : Goo.CanvasRect { update_state (Cairo.Matrix.identity (), 0, 0, false); - if (handle_id == Managers.NobManager.Nob.ROTATE) { + if (handle_id == Managers.NobManager.Nob.ROTATE || + handle_id == Managers.NobManager.Nob.GRADIENT_START || + handle_id == Managers.NobManager.Nob.GRADIENT_END) { set ("radius-x", nob_size); set ("radius-y", nob_size); } diff --git a/src/Widgets/DirectionLine.vala b/src/Widgets/DirectionLine.vala index a66974457..3eb72411f 100644 --- a/src/Widgets/DirectionLine.vala +++ b/src/Widgets/DirectionLine.vala @@ -21,17 +21,25 @@ public class Akira.Widgets.DirectionLine { private Lib.Selection.Nob start_nob; private Lib.Selection.Nob end_nob; + + // dummy identity matrix + private Cairo.Matrix identity_mat = Cairo.Matrix.identity(); public DirectionLine (Window window, GradientEditor gradient_editor) { - var root = window.main_window.main_canvas.canvas.get_root_item(); + var canvas = window.main_window.main_canvas.canvas as Lib.Canvas; + var root = canvas.get_root_item(); + start_nob = new Lib.Selection.Nob(root, Lib.Managers.NobManager.Nob.GRADIENT_START); end_nob = new Lib.Selection.Nob(root, Lib.Managers.NobManager.Nob.GRADIENT_END); start_nob.set_rectangle(); end_nob.set_rectangle(); - start_nob.update_state(Cairo.Matrix.identity(), 50, 50, false); - end_nob.update_state(Cairo.Matrix.identity(), 150, 150, false); + start_nob.update_state(identity_mat, 50, 50, false); + end_nob.update_state(identity_mat, 150, 150, false); + + set_initial_position(canvas.selected_bound_manager.selected_items); + update_visibility("solid"); window.event_bus.color_mode_changed.connect(update_visibility); } @@ -55,4 +63,23 @@ public class Akira.Widgets.DirectionLine { end_nob.update_state(Cairo.Matrix.identity(), end_x, end_y, true); } } + + private void set_initial_position (List items) { + if(items.length() == 1) { + var item = items.first().data; + + double pos_x = item.coordinates.x; + double pos_y = item.coordinates.y; + double width = item.size.width; + double height = item.size.height; + + // TODO: get the rotation matrix and artboard matrix from item and recalculate position + + start_nob.update_state(identity_mat, pos_x+10, pos_y+10, true); + end_nob.update_state(identity_mat, pos_x+width-10, pos_y+height-10, true); + + } else { + // TODO: implement gradients when multiple items are selected + } + } } \ No newline at end of file From e14305c7dc77ae4ffbdf3ba49ff7e360a5881602 Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Tue, 29 Jun 2021 15:11:38 +0530 Subject: [PATCH 17/35] Dynamic show/hide direction line based on selection --- src/Widgets/DirectionLine.vala | 50 ++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/src/Widgets/DirectionLine.vala b/src/Widgets/DirectionLine.vala index 3eb72411f..0c2bd05f1 100644 --- a/src/Widgets/DirectionLine.vala +++ b/src/Widgets/DirectionLine.vala @@ -22,6 +22,8 @@ public class Akira.Widgets.DirectionLine { private Lib.Selection.Nob start_nob; private Lib.Selection.Nob end_nob; + private string color_mode_type; + // dummy identity matrix private Cairo.Matrix identity_mat = Cairo.Matrix.identity(); @@ -42,28 +44,48 @@ public class Akira.Widgets.DirectionLine { update_visibility("solid"); window.event_bus.color_mode_changed.connect(update_visibility); + + window.event_bus.selected_items_list_changed.connect (() => { + if(canvas.selected_bound_manager.selected_items.length() == 0) { + hide_direction_line(); + } else { + if(color_mode_type != "solid") { + show_direction_line(); + } + } + }); + + start_nob.button_press_event.connect((event) => {return on_button_press(event);}); + } + + private bool on_button_press (Goo.CanvasItem event) { + print("button pressed\n"); + + return false; } private void update_visibility(string color_mode) { - if(color_mode == "solid") { - var start_x = start_nob.center_x; - var start_y = start_nob.center_y; - var end_x = end_nob.center_x; - var end_y = end_nob.center_y; + color_mode_type = color_mode; - start_nob.update_state(Cairo.Matrix.identity(), start_x, start_y, false); - end_nob.update_state(Cairo.Matrix.identity(), end_x, end_y, false); + if(color_mode == "solid") { + hide_direction_line(); } else { - var start_x = start_nob.center_x; - var start_y = start_nob.center_y; - var end_x = end_nob.center_x; - var end_y = end_nob.center_y; - - start_nob.update_state(Cairo.Matrix.identity(), start_x, start_y, true); - end_nob.update_state(Cairo.Matrix.identity(), end_x, end_y, true); + show_direction_line(); } } + private void hide_direction_line() { + print("hide selection\n"); + start_nob.set("visibility", Goo.CanvasItemVisibility.HIDDEN); + end_nob.set("visibility", Goo.CanvasItemVisibility.HIDDEN); + } + + private void show_direction_line() { + print("show selection\n"); + start_nob.set("visibility", Goo.CanvasItemVisibility.VISIBLE); + end_nob.set("visibility", Goo.CanvasItemVisibility.VISIBLE); + } + private void set_initial_position (List items) { if(items.length() == 1) { var item = items.first().data; From 2b28f567c25e0e978d8449d32d82b125443284ab Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Wed, 30 Jun 2021 23:54:38 +0530 Subject: [PATCH 18/35] Drag nobs to change gradient direction --- src/Widgets/DirectionLine.vala | 56 +++++++++++++++++++++++++++------ src/Widgets/GradientEditor.vala | 23 +++++++++++--- 2 files changed, 65 insertions(+), 14 deletions(-) diff --git a/src/Widgets/DirectionLine.vala b/src/Widgets/DirectionLine.vala index 0c2bd05f1..cd4331af2 100644 --- a/src/Widgets/DirectionLine.vala +++ b/src/Widgets/DirectionLine.vala @@ -19,17 +19,24 @@ * Authored by: Ashish Shevale */ public class Akira.Widgets.DirectionLine { - private Lib.Selection.Nob start_nob; - private Lib.Selection.Nob end_nob; + public Lib.Selection.Nob start_nob; + public Lib.Selection.Nob end_nob; + private Lib.Selection.Nob selected_nob; private string color_mode_type; + private Lib.Canvas canvas; + private Lib.Items.CanvasItem selected_item; + private GradientEditor gradient_editor; + // dummy identity matrix private Cairo.Matrix identity_mat = Cairo.Matrix.identity(); - public DirectionLine (Window window, GradientEditor gradient_editor) { - var canvas = window.main_window.main_canvas.canvas as Lib.Canvas; + public DirectionLine (Window window, GradientEditor _gradient_editor) { + canvas = window.main_window.main_canvas.canvas as Lib.Canvas; + selected_item = canvas.selected_bound_manager.selected_items.nth_data(0); var root = canvas.get_root_item(); + gradient_editor = _gradient_editor; start_nob = new Lib.Selection.Nob(root, Lib.Managers.NobManager.Nob.GRADIENT_START); end_nob = new Lib.Selection.Nob(root, Lib.Managers.NobManager.Nob.GRADIENT_END); @@ -44,6 +51,8 @@ public class Akira.Widgets.DirectionLine { update_visibility("solid"); window.event_bus.color_mode_changed.connect(update_visibility); + canvas.button_press_event.connect(on_buton_press_event); + canvas.button_release_event.connect(on_button_release_event); window.event_bus.selected_items_list_changed.connect (() => { if(canvas.selected_bound_manager.selected_items.length() == 0) { @@ -54,13 +63,44 @@ public class Akira.Widgets.DirectionLine { } } }); + } + + public void get_direction_coords(out double x0, out double y0, out double x1, out double y1) { + x0 = start_nob.center_x - selected_item.coordinates.x; + y0 = start_nob.center_y - selected_item.coordinates.y; + x1 = end_nob.center_x - selected_item.coordinates.x; + y1 = end_nob.center_y - selected_item.coordinates.y; - start_nob.button_press_event.connect((event) => {return on_button_press(event);}); } - private bool on_button_press (Goo.CanvasItem event) { - print("button pressed\n"); + private bool on_buton_press_event(Gdk.EventButton event) { + if(start_nob.hit_test(event.x, event.y, canvas.get_scale())) { + selected_nob = start_nob; + + canvas.motion_notify_event.connect(on_motion_event); + + // return true here to prevent the button press event from propogating. + // this is because in transform_manager, this event causes the canvas item to move + return true; + } else if(end_nob.hit_test(event.x, event.y, canvas.get_scale())) { + selected_nob = end_nob; + + canvas.motion_notify_event.connect(on_motion_event); + + return true; + } + return false; + } + + private bool on_motion_event(Gdk.EventMotion event) { + selected_nob.update_state(identity_mat, event.x, event.y, true); + gradient_editor.create_gradient_pattern(); + + return true; + } + private bool on_button_release_event(Gdk.EventButton event) { + canvas.motion_notify_event.disconnect(on_motion_event); return false; } @@ -75,13 +115,11 @@ public class Akira.Widgets.DirectionLine { } private void hide_direction_line() { - print("hide selection\n"); start_nob.set("visibility", Goo.CanvasItemVisibility.HIDDEN); end_nob.set("visibility", Goo.CanvasItemVisibility.HIDDEN); } private void show_direction_line() { - print("show selection\n"); start_nob.set("visibility", Goo.CanvasItemVisibility.VISIBLE); end_nob.set("visibility", Goo.CanvasItemVisibility.VISIBLE); } diff --git a/src/Widgets/GradientEditor.vala b/src/Widgets/GradientEditor.vala index 08c22bf7a..518519bcf 100644 --- a/src/Widgets/GradientEditor.vala +++ b/src/Widgets/GradientEditor.vala @@ -40,6 +40,17 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { public GradientEditor(Window _window, Models.ColorModel _model) { window = _window; model = _model; + + /* + if(model.pattern.get_type() == Cairo.PatternType.LINEAR) { + color_mode_type = "linear"; + } else if(model.pattern.get_type() == Cairo.PatternType.RADIAL) { + color_mode_type = "radial"; + } else { + print("set color solid\n"); + color_mode_type = "solid"; + } + */ color_mode_type = "solid"; direction_line = new DirectionLine(_window, this); @@ -244,23 +255,25 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { update_style(); } - private void create_gradient_pattern () { + public void create_gradient_pattern () { double item_height, item_width; model.get("height", out item_height); model.get("width", out item_width); + + double x0, y0, x1, y1; + direction_line.get_direction_coords(out x0, out y0, out x1, out y1); if(color_mode_type == "solid") { // for solid color, create an empty pattern. In Fills, we check if stop colors exists // for this pattern. If they dont, then the Pattern is not applied - gradient_pattern = new Cairo.Pattern.linear(0,0,0,0); + gradient_pattern = new Cairo.Pattern.linear(x0, y0, x1, y1); model.pattern = gradient_pattern; return; } else if(color_mode_type == "linear") { - gradient_pattern = new Cairo.Pattern.linear(0, 0, - item_width, item_height); + gradient_pattern = new Cairo.Pattern.linear(x0, y0, x1, y1); } else { int radius = (int) Math.sqrt( item_width * item_width + item_height * item_height); - gradient_pattern = new Cairo.Pattern.radial(0, 0, 0, 0, 0, radius); + gradient_pattern = new Cairo.Pattern.radial(x0, y0, 0, x1, y1, radius); } for(int index = 0; index < stop_colors.size; ++index) { From 6ef1d3690ba7bf3e6ef3fc545942dcc10ea2c5c9 Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Fri, 2 Jul 2021 10:17:22 +0530 Subject: [PATCH 19/35] Minor bug fix in Nobs --- src/Widgets/DirectionLine.vala | 20 ++++++++++++++++++-- src/Widgets/GradientEditor.vala | 11 +---------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/Widgets/DirectionLine.vala b/src/Widgets/DirectionLine.vala index cd4331af2..6da64000a 100644 --- a/src/Widgets/DirectionLine.vala +++ b/src/Widgets/DirectionLine.vala @@ -28,11 +28,14 @@ public class Akira.Widgets.DirectionLine { private Lib.Canvas canvas; private Lib.Items.CanvasItem selected_item; private GradientEditor gradient_editor; + private Window window; // dummy identity matrix private Cairo.Matrix identity_mat = Cairo.Matrix.identity(); - public DirectionLine (Window window, GradientEditor _gradient_editor) { + public DirectionLine (Window _window, GradientEditor _gradient_editor) { + print("create new direction \n"); + window = _window; canvas = window.main_window.main_canvas.canvas as Lib.Canvas; selected_item = canvas.selected_bound_manager.selected_items.nth_data(0); var root = canvas.get_root_item(); @@ -56,7 +59,7 @@ public class Akira.Widgets.DirectionLine { window.event_bus.selected_items_list_changed.connect (() => { if(canvas.selected_bound_manager.selected_items.length() == 0) { - hide_direction_line(); + destroy_direction_line(); } else { if(color_mode_type != "solid") { show_direction_line(); @@ -124,6 +127,19 @@ public class Akira.Widgets.DirectionLine { end_nob.set("visibility", Goo.CanvasItemVisibility.VISIBLE); } + private void destroy_direction_line() { + // we need to destroy direction line everytime an item is deselected. This is because + // when and item is selected, it creates a new instance of DirectionLine. This results in duplicate + // start_nob and end_nob + window.event_bus.color_mode_changed.disconnect(update_visibility); + canvas.button_press_event.disconnect(on_buton_press_event); + canvas.button_release_event.disconnect(on_button_release_event); + + hide_direction_line(); + start_nob.remove(); + end_nob.remove(); + } + private void set_initial_position (List items) { if(items.length() == 1) { var item = items.first().data; diff --git a/src/Widgets/GradientEditor.vala b/src/Widgets/GradientEditor.vala index 518519bcf..d3f3360fe 100644 --- a/src/Widgets/GradientEditor.vala +++ b/src/Widgets/GradientEditor.vala @@ -41,19 +41,10 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { window = _window; model = _model; - /* - if(model.pattern.get_type() == Cairo.PatternType.LINEAR) { - color_mode_type = "linear"; - } else if(model.pattern.get_type() == Cairo.PatternType.RADIAL) { - color_mode_type = "radial"; - } else { - print("set color solid\n"); - color_mode_type = "solid"; - } - */ color_mode_type = "solid"; direction_line = new DirectionLine(_window, this); + gradient_pattern = new Cairo.Pattern.linear(0,0,0,0); set_hexpand(true); height_request = 35; From 838b6d98a4703f9f4f89525c00660e7b074be310 Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Fri, 2 Jul 2021 11:29:40 +0530 Subject: [PATCH 20/35] Disable gradients for borders --- src/Widgets/DirectionLine.vala | 7 ++++++- src/Widgets/GradientEditor.vala | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Widgets/DirectionLine.vala b/src/Widgets/DirectionLine.vala index 6da64000a..b89fb71c8 100644 --- a/src/Widgets/DirectionLine.vala +++ b/src/Widgets/DirectionLine.vala @@ -33,7 +33,12 @@ public class Akira.Widgets.DirectionLine { // dummy identity matrix private Cairo.Matrix identity_mat = Cairo.Matrix.identity(); - public DirectionLine (Window _window, GradientEditor _gradient_editor) { + public DirectionLine (Window _window, GradientEditor _gradient_editor, Akira.Models.ColorModel.Type type) { + // since gradients on borders are not yet supported, dont draw direction line + if(type == Akira.Models.ColorModel.Type.BORDER) { + return; + } + print("create new direction \n"); window = _window; canvas = window.main_window.main_canvas.canvas as Lib.Canvas; diff --git a/src/Widgets/GradientEditor.vala b/src/Widgets/GradientEditor.vala index d3f3360fe..65aad4682 100644 --- a/src/Widgets/GradientEditor.vala +++ b/src/Widgets/GradientEditor.vala @@ -43,7 +43,7 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { color_mode_type = "solid"; - direction_line = new DirectionLine(_window, this); + direction_line = new DirectionLine(_window, this, model.type); gradient_pattern = new Cairo.Pattern.linear(0,0,0,0); set_hexpand(true); @@ -203,6 +203,11 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { } private void update_style() { + // since gradients on direction line are not supported, dont draw direction line + if(model.type == Akira.Models.ColorModel.Type.BORDER) { + return; + } + string css_style = ""; string stop_color_string = stop_colors_as_string(); From 5ac7421eceefc924d9b99e003b52d4cfa341dc19 Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Fri, 2 Jul 2021 11:32:44 +0530 Subject: [PATCH 21/35] Fix Radial gradient positions --- src/Widgets/GradientEditor.vala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Widgets/GradientEditor.vala b/src/Widgets/GradientEditor.vala index 65aad4682..761a7ef8a 100644 --- a/src/Widgets/GradientEditor.vala +++ b/src/Widgets/GradientEditor.vala @@ -268,8 +268,10 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { } else if(color_mode_type == "linear") { gradient_pattern = new Cairo.Pattern.linear(x0, y0, x1, y1); } else { - int radius = (int) Math.sqrt( item_width * item_width + item_height * item_height); - gradient_pattern = new Cairo.Pattern.radial(x0, y0, 0, x1, y1, radius); + double dx = x0 - x1; + double dy = y0 - y1; + int radius = (int) Math.sqrt( dx*dx + dy*dy ); + gradient_pattern = new Cairo.Pattern.radial(x0, y0, 0, x0, y0, radius); } for(int index = 0; index < stop_colors.size; ++index) { From bbace66bd41d90873b955d2332804c6cc90e2d86 Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Fri, 2 Jul 2021 15:06:06 +0530 Subject: [PATCH 22/35] Disable gradients for Border --- src/Widgets/.fuse_hidden0000003e00000009 | 167 +++++++++++++++++++++++ src/Widgets/ColorMode.vala | 13 +- src/Widgets/ColorRow.vala | 23 +++- src/Widgets/DirectionLine.vala | 47 +++++-- src/Widgets/GradientEditor.vala | 40 +++--- 5 files changed, 257 insertions(+), 33 deletions(-) create mode 100644 src/Widgets/.fuse_hidden0000003e00000009 diff --git a/src/Widgets/.fuse_hidden0000003e00000009 b/src/Widgets/.fuse_hidden0000003e00000009 new file mode 100644 index 000000000..cd953ffba --- /dev/null +++ b/src/Widgets/.fuse_hidden0000003e00000009 @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2021 Alecaddd (https://alecaddd.com) + * + * This file is part of Akira. + * + * Akira 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. + * + * Akira 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 Akira. If not, see . + * + * Authored by: Ashish Shevale +*/ +public class Akira.Widgets.DirectionLine { + public Lib.Selection.Nob start_nob; + public Lib.Selection.Nob end_nob; + private Lib.Selection.Nob selected_nob; + + private string color_mode_type; + + private Lib.Canvas canvas; + private Lib.Items.CanvasItem selected_item; + private unowned GradientEditor gradient_editor; + private unowned Akira.Window window; + + // dummy identity matrix + private Cairo.Matrix identity_mat = Cairo.Matrix.identity(); + + public DirectionLine (Window _window, GradientEditor _gradient_editor, Akira.Models.ColorModel.Type type) { + print("create direction line\n"); + // since gradients on borders are not yet supported, dont draw direction line + if(type == Akira.Models.ColorModel.Type.BORDER) { + return; + } + + print("create new direction \n"); + window = _window; + canvas = window.main_window.main_canvas.canvas as Lib.Canvas; + selected_item = canvas.selected_bound_manager.selected_items.nth_data(0); + var root = canvas.get_root_item(); + gradient_editor = _gradient_editor; + + start_nob = new Lib.Selection.Nob(root, Lib.Managers.NobManager.Nob.GRADIENT_START); + end_nob = new Lib.Selection.Nob(root, Lib.Managers.NobManager.Nob.GRADIENT_END); + + start_nob.set_rectangle(); + end_nob.set_rectangle(); + + start_nob.update_state(identity_mat, 50, 50, false); + end_nob.update_state(identity_mat, 150, 150, false); + + set_initial_position(canvas.selected_bound_manager.selected_items); + update_visibility("solid"); + + window.event_bus.color_mode_changed.connect(update_visibility); + canvas.button_press_event.connect(on_buton_press_event); + canvas.button_release_event.connect(on_button_release_event); + + window.event_bus.selected_items_list_changed.connect (() => { + if(canvas.selected_bound_manager.selected_items.length() == 0) { + destroy_direction_line(); + } else { + if(color_mode_type != "solid") { + show_direction_line(); + } + } + }); + } + + public void get_direction_coords(out double x0, out double y0, out double x1, out double y1) { + x0 = start_nob.center_x - selected_item.coordinates.x; + y0 = start_nob.center_y - selected_item.coordinates.y; + x1 = end_nob.center_x - selected_item.coordinates.x; + y1 = end_nob.center_y - selected_item.coordinates.y; + + } + + private bool on_buton_press_event(Gdk.EventButton event) { + if(start_nob.hit_test(event.x, event.y, canvas.get_scale())) { + selected_nob = start_nob; + + canvas.motion_notify_event.connect(on_motion_event); + + // return true here to prevent the button press event from propogating. + // this is because in transform_manager, this event causes the canvas item to move + return true; + } else if(end_nob.hit_test(event.x, event.y, canvas.get_scale())) { + selected_nob = end_nob; + + canvas.motion_notify_event.connect(on_motion_event); + + return true; + } + return false; + } + + private bool on_motion_event(Gdk.EventMotion event) { + selected_nob.update_state(identity_mat, event.x, event.y, true); + gradient_editor.create_gradient_pattern(); + + return true; + } + + private bool on_button_release_event(Gdk.EventButton event) { + canvas.motion_notify_event.disconnect(on_motion_event); + return false; + } + + private void update_visibility(string color_mode) { + color_mode_type = color_mode; + + if(color_mode == "solid") { + hide_direction_line(); + } else { + show_direction_line(); + } + } + + private void hide_direction_line() { + start_nob.set("visibility", Goo.CanvasItemVisibility.HIDDEN); + end_nob.set("visibility", Goo.CanvasItemVisibility.HIDDEN); + } + + private void show_direction_line() { + start_nob.set("visibility", Goo.CanvasItemVisibility.VISIBLE); + end_nob.set("visibility", Goo.CanvasItemVisibility.VISIBLE); + } + + private void destroy_direction_line() { + // we need to destroy direction line everytime an item is deselected. This is because + // when and item is selected, it creates a new instance of DirectionLine. This results in duplicate + // start_nob and end_nob + window.event_bus.color_mode_changed.disconnect(update_visibility); + canvas.button_press_event.disconnect(on_buton_press_event); + canvas.button_release_event.disconnect(on_button_release_event); + + hide_direction_line(); + start_nob.remove(); + end_nob.remove(); + } + + private void set_initial_position (List items) { + if(items.length() == 1) { + var item = items.first().data; + + double pos_x = item.coordinates.x; + double pos_y = item.coordinates.y; + double width = item.size.width; + double height = item.size.height; + + // TODO: get the rotation matrix and artboard matrix from item and recalculate position + + start_nob.update_state(identity_mat, pos_x+10, pos_y+10, true); + end_nob.update_state(identity_mat, pos_x+width-10, pos_y+height-10, true); + + } else { + // TODO: implement gradients when multiple items are selected + } + } +} \ No newline at end of file diff --git a/src/Widgets/ColorMode.vala b/src/Widgets/ColorMode.vala index 22067b615..e377d2960 100644 --- a/src/Widgets/ColorMode.vala +++ b/src/Widgets/ColorMode.vala @@ -30,8 +30,8 @@ public string color_mode_type; public Gtk.Grid buttons_grid; - private Models.ColorModel model; - private Window window; + private unowned Models.ColorModel model; + private unowned Window window; public ColorMode (Models.ColorModel _model, Window _window) { model = _model; @@ -72,6 +72,15 @@ gradient_editor = new GradientEditor(window, model); + // since color modes on border havent been implmented yet, disable these buttons + if(model.type == Akira.Models.ColorModel.Type.BORDER) { + solid_color_button.sensitive = false; + linear_gradient_button.sensitive = false; + radial_gradient_button.sensitive = false; + delete_step_button.sensitive = false; + + } + Gtk.Separator separator = new Gtk.Separator (Gtk.Orientation.VERTICAL); separator.hexpand = true; diff --git a/src/Widgets/ColorRow.vala b/src/Widgets/ColorRow.vala index 8e2ca44ea..9b6cc766c 100644 --- a/src/Widgets/ColorRow.vala +++ b/src/Widgets/ColorRow.vala @@ -79,6 +79,8 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { color_popover = new Gtk.Popover (color_button); color_popover.position = Gtk.PositionType.BOTTOM; + color_mode_widget = new ColorMode(model, this.window); + color_button.clicked.connect (() => { init_color_chooser (); color_popover.popup (); @@ -123,7 +125,11 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { var new_rgba = Utils.Color.hex_to_rgba (field_hex); set_button_color (field_hex, model.alpha); - window.event_bus.color_changed(field_hex, opacity_field.entry.value); + window.event_bus.color_changed(new_rgba.to_string(), model.alpha / 255.0); + + if(color_mode_widget.color_mode_type == "solid") { + model.color = new_rgba.to_string(); + } // Update the chooser widget only if it was already initialized. if (color_chooser_widget != null) { @@ -149,7 +155,16 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { if (color_set_manually) { return; } - + + // we need to get the RGBA value from field to trigger color_changed signal + var field_hex = field.text; + // Interrupt if what's written is not a valid color value. + if (!Utils.Color.is_valid_hex (field_hex)) { + return; + } + + var new_rgba = Utils.Color.hex_to_rgba (field_hex); + // Since we will update the color picker, prevent an infinite loop. color_set_manually = true; @@ -157,7 +172,7 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { //model.alpha = alpha; set_button_color (model.color, alpha); - window.event_bus.color_changed(field.text, alpha); + window.event_bus.color_changed(new_rgba.to_string(), alpha); // Update the chooser widget only if it was already initialized. if (color_chooser_widget != null) { @@ -221,8 +236,6 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { global_colors_flowbox.add (btn); } - color_mode_widget = new ColorMode(model, this.window); - color_grid.attach (color_mode_widget.buttons_grid, 0, 0, 1, 1); color_grid.attach (color_chooser_widget, 0, 1, 1, 1); color_grid.attach (global_colors_label, 0, 2, 1, 1); diff --git a/src/Widgets/DirectionLine.vala b/src/Widgets/DirectionLine.vala index b89fb71c8..c411207ef 100644 --- a/src/Widgets/DirectionLine.vala +++ b/src/Widgets/DirectionLine.vala @@ -27,25 +27,28 @@ public class Akira.Widgets.DirectionLine { private Lib.Canvas canvas; private Lib.Items.CanvasItem selected_item; - private GradientEditor gradient_editor; - private Window window; + private unowned GradientEditor gradient_editor; + private unowned Window window; + private unowned Akira.Models.ColorModel.Type type; // dummy identity matrix private Cairo.Matrix identity_mat = Cairo.Matrix.identity(); public DirectionLine (Window _window, GradientEditor _gradient_editor, Akira.Models.ColorModel.Type type) { + this.type = type; // since gradients on borders are not yet supported, dont draw direction line + if(type == Akira.Models.ColorModel.Type.BORDER) { return; } - - print("create new direction \n"); + window = _window; canvas = window.main_window.main_canvas.canvas as Lib.Canvas; selected_item = canvas.selected_bound_manager.selected_items.nth_data(0); var root = canvas.get_root_item(); gradient_editor = _gradient_editor; + print("create new direction line\n"); start_nob = new Lib.Selection.Nob(root, Lib.Managers.NobManager.Nob.GRADIENT_START); end_nob = new Lib.Selection.Nob(root, Lib.Managers.NobManager.Nob.GRADIENT_END); @@ -61,16 +64,18 @@ public class Akira.Widgets.DirectionLine { window.event_bus.color_mode_changed.connect(update_visibility); canvas.button_press_event.connect(on_buton_press_event); canvas.button_release_event.connect(on_button_release_event); - + window.event_bus.selected_items_list_changed.connect (() => { + if(type == Akira.Models.ColorModel.Type.BORDER) { + return; + } + if(canvas.selected_bound_manager.selected_items.length() == 0) { destroy_direction_line(); - } else { - if(color_mode_type != "solid") { - show_direction_line(); - } } + }); + } public void get_direction_coords(out double x0, out double y0, out double x1, out double y1) { @@ -82,6 +87,10 @@ public class Akira.Widgets.DirectionLine { } private bool on_buton_press_event(Gdk.EventButton event) { + if(type == Akira.Models.ColorModel.Type.BORDER) { + return false; + } + if(start_nob.hit_test(event.x, event.y, canvas.get_scale())) { selected_nob = start_nob; @@ -108,11 +117,19 @@ public class Akira.Widgets.DirectionLine { } private bool on_button_release_event(Gdk.EventButton event) { + if(type == Akira.Models.ColorModel.Type.BORDER) { + return false; + } + canvas.motion_notify_event.disconnect(on_motion_event); return false; } private void update_visibility(string color_mode) { + if(type == Akira.Models.ColorModel.Type.BORDER) { + return; + } + color_mode_type = color_mode; if(color_mode == "solid") { @@ -123,16 +140,28 @@ public class Akira.Widgets.DirectionLine { } private void hide_direction_line() { + if(type == Akira.Models.ColorModel.Type.BORDER) { + return; + } + start_nob.set("visibility", Goo.CanvasItemVisibility.HIDDEN); end_nob.set("visibility", Goo.CanvasItemVisibility.HIDDEN); } private void show_direction_line() { + if(type == Akira.Models.ColorModel.Type.BORDER) { + return; + } + start_nob.set("visibility", Goo.CanvasItemVisibility.VISIBLE); end_nob.set("visibility", Goo.CanvasItemVisibility.VISIBLE); } private void destroy_direction_line() { + if(type == Akira.Models.ColorModel.Type.BORDER) { + return; + } + // we need to destroy direction line everytime an item is deselected. This is because // when and item is selected, it creates a new instance of DirectionLine. This results in duplicate // start_nob and end_nob diff --git a/src/Widgets/GradientEditor.vala b/src/Widgets/GradientEditor.vala index 761a7ef8a..8b8f2a20d 100644 --- a/src/Widgets/GradientEditor.vala +++ b/src/Widgets/GradientEditor.vala @@ -25,8 +25,8 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { private int widget_x; private int widget_y; - private Window window; - private Models.ColorModel model; + private unowned Window window; + private unowned Models.ColorModel model; private string color_mode_type; // list to store all stop colors in order @@ -60,19 +60,20 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { selected_stop_color = stop_colors[0]; size_allocate.connect( () => { - widget_width = get_allocated_width(); - widget_height = get_allocated_height(); + widget_width = get_allocated_width(); + widget_height = get_allocated_height(); - draw.connect_after ( (context) => {return redraw_editor(context);}); - - button_press_event.connect( (event) => {return on_button_press(event);}); - button_release_event.connect ( (event) => {return on_button_release(event); }); - - window.event_bus.color_mode_changed.connect(on_color_mode_changed); - window.event_bus.color_changed.connect(on_color_changed); + draw.connect_after ( (context) => {return redraw_editor(context);}); + + button_press_event.connect( (event) => {return on_button_press(event);}); + button_release_event.connect ( (event) => {return on_button_release(event); }); + + window.event_bus.color_mode_changed.connect(on_color_mode_changed); + window.event_bus.color_changed.connect(on_color_changed); }); + //window.event_bus.color_changed.connect(on_color_changed); } private bool redraw_editor(Cairo.Context context) { @@ -150,12 +151,17 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { } public void on_color_changed(string color, double alpha) { - int index = stop_colors.index_of(selected_stop_color); - - stop_colors[index].color = color; - stop_colors[index].alpha = alpha; - - queue_draw_area(widget_x, widget_y, widget_width, widget_height); + if(color_mode_type != "solid") { + int index = stop_colors.index_of(selected_stop_color); + + stop_colors[index].color = color; + stop_colors[index].alpha = alpha; + + queue_draw_area(widget_x, widget_y, widget_width, widget_height); + } else { + model.color = color; + model.alpha = (int) (alpha * 255); + } } public void delete_selected_step () { From 3e3c1ebbffbb8bfab261c74f7d1941b2c24f7899 Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Fri, 2 Jul 2021 20:35:02 +0530 Subject: [PATCH 23/35] Select Deselect crash fix --- src/Widgets/DirectionLine.vala | 1 - src/Widgets/GradientEditor.vala | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Widgets/DirectionLine.vala b/src/Widgets/DirectionLine.vala index c411207ef..f70098278 100644 --- a/src/Widgets/DirectionLine.vala +++ b/src/Widgets/DirectionLine.vala @@ -48,7 +48,6 @@ public class Akira.Widgets.DirectionLine { var root = canvas.get_root_item(); gradient_editor = _gradient_editor; - print("create new direction line\n"); start_nob = new Lib.Selection.Nob(root, Lib.Managers.NobManager.Nob.GRADIENT_START); end_nob = new Lib.Selection.Nob(root, Lib.Managers.NobManager.Nob.GRADIENT_END); diff --git a/src/Widgets/GradientEditor.vala b/src/Widgets/GradientEditor.vala index 8b8f2a20d..4e872c465 100644 --- a/src/Widgets/GradientEditor.vala +++ b/src/Widgets/GradientEditor.vala @@ -25,8 +25,8 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { private int widget_x; private int widget_y; - private unowned Window window; - private unowned Models.ColorModel model; + private Window window; + private Models.ColorModel model; private string color_mode_type; // list to store all stop colors in order @@ -238,7 +238,7 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { warning ("Style error: %s", e.message); debug ("%s %s\n", name, css_style); } - + create_gradient_pattern(); } From 6fc6f7029bfeb2477d1a95acb0538988d9652d94 Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Fri, 2 Jul 2021 20:59:01 +0530 Subject: [PATCH 24/35] Set initial position of direction line --- src/Widgets/DirectionLine.vala | 44 ++++++++++++++++------------------ 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/src/Widgets/DirectionLine.vala b/src/Widgets/DirectionLine.vala index f70098278..9f33fdac1 100644 --- a/src/Widgets/DirectionLine.vala +++ b/src/Widgets/DirectionLine.vala @@ -54,12 +54,13 @@ public class Akira.Widgets.DirectionLine { start_nob.set_rectangle(); end_nob.set_rectangle(); - start_nob.update_state(identity_mat, 50, 50, false); - end_nob.update_state(identity_mat, 150, 150, false); - - set_initial_position(canvas.selected_bound_manager.selected_items); update_visibility("solid"); + // initial position of direction nobs will be outside the canvas. + // when CanvasItem gets selected, they will be placed along the diagonal + start_nob.update_state(identity_mat, -10, -10, false); + end_nob.update_state(identity_mat, -10, -10, false); + window.event_bus.color_mode_changed.connect(update_visibility); canvas.button_press_event.connect(on_buton_press_event); canvas.button_release_event.connect(on_button_release_event); @@ -129,6 +130,22 @@ public class Akira.Widgets.DirectionLine { return; } + if(start_nob.center_x == -10 || start_nob.center_y == -10) { + print("first time setup\n"); + // if this is the first time the direction line is being displayed, + // set its default position along diagonal + double pos_x = selected_item.coordinates.x; + double pos_y = selected_item.coordinates.y; + double width = selected_item.size.width; + double height = selected_item.size.height; + double offset = Akira.Lib.Selection.Nob.NOB_SIZE; + + // TODO: get the rotation matrix and artboard matrix from item and recalculate position + + start_nob.update_state(identity_mat, pos_x+offset, pos_y+offset, true); + end_nob.update_state(identity_mat, pos_x+width-offset, pos_y+height-offset, true); + } + color_mode_type = color_mode; if(color_mode == "solid") { @@ -172,23 +189,4 @@ public class Akira.Widgets.DirectionLine { start_nob.remove(); end_nob.remove(); } - - private void set_initial_position (List items) { - if(items.length() == 1) { - var item = items.first().data; - - double pos_x = item.coordinates.x; - double pos_y = item.coordinates.y; - double width = item.size.width; - double height = item.size.height; - - // TODO: get the rotation matrix and artboard matrix from item and recalculate position - - start_nob.update_state(identity_mat, pos_x+10, pos_y+10, true); - end_nob.update_state(identity_mat, pos_x+width-10, pos_y+height-10, true); - - } else { - // TODO: implement gradients when multiple items are selected - } - } } \ No newline at end of file From 7508cd8de5ad44bd35497c187ac7857b48a2f03e Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Fri, 2 Jul 2021 21:46:57 +0530 Subject: [PATCH 25/35] Linting related fixes --- src/Lib/Components/Fill.vala | 2 +- src/Lib/Components/Fills.vala | 14 +- src/Models/ColorModel.vala | 14 +- src/Services/EventBus.vala | 4 +- src/Widgets/ColorMode.vala | 23 ++- src/Widgets/ColorRow.vala | 19 ++- src/Widgets/DirectionLine.vala | 126 ++++++++-------- src/Widgets/GradientEditor.vala | 254 ++++++++++++++++---------------- 8 files changed, 224 insertions(+), 232 deletions(-) diff --git a/src/Lib/Components/Fill.vala b/src/Lib/Components/Fill.vala index 99b127fff..781c22228 100644 --- a/src/Lib/Components/Fill.vala +++ b/src/Lib/Components/Fill.vala @@ -43,7 +43,7 @@ public class Akira.Lib.Components.Fill : Component { color = init_color; hex = color.to_string (); alpha = 255; - gradient_pattern = new Cairo.Pattern.linear(0,0,0,0); + gradient_pattern = new Cairo.Pattern.linear (0,0,0,0); // Listen for changed to the fill attributes to properly trigger the color generation. this.notify["color"].connect (() => { diff --git a/src/Lib/Components/Fills.vala b/src/Lib/Components/Fills.vala index 8dca80d4b..0fc5779f4 100644 --- a/src/Lib/Components/Fills.vala +++ b/src/Lib/Components/Fills.vala @@ -52,7 +52,7 @@ public class Akira.Lib.Components.Fills : Component { // Trigger the generation of the fill color. reload (); - + return new_fill; } @@ -89,17 +89,17 @@ public class Akira.Lib.Components.Fills : Component { } var stop_colors = 0; - fill.gradient_pattern.get_color_stop_count(out stop_colors); - + fill.gradient_pattern.get_color_stop_count (out stop_colors); + // if for this fill, either of the gradient modes have been selected, // the stop_colors value would not be zero. - if(stop_colors != 0 && has_colors == false) { - if(item is Items.CanvasArtboard) { + if (stop_colors != 0 && has_colors == false) { + if (item is Items.CanvasArtboard) { ((Items.CanvasArtboard) item).background.set ("fill-pattern", fill.gradient_pattern); } else { - item.set("fill-pattern", fill.gradient_pattern); + item.set ("fill-pattern", fill.gradient_pattern); } - + // since we dont have the functionality of blending gradients, return; } diff --git a/src/Models/ColorModel.vala b/src/Models/ColorModel.vala index 7ab49f820..7c5d3b258 100644 --- a/src/Models/ColorModel.vala +++ b/src/Models/ColorModel.vala @@ -32,13 +32,13 @@ public class Akira.Models.ColorModel : GLib.Object { FILL, BORDER } - + public Cairo.Pattern pattern { owned get { return pattern; } set { - if(type == Type.FILL) { + if (type == Type.FILL) { fill.gradient_pattern = value; } } @@ -94,23 +94,23 @@ public class Akira.Models.ColorModel : GLib.Object { border.size = value; } } - + public double width { get { double width; - fill.item.size.get("width", out width); + fill.item.size.get ("width", out width); return width; } } - + public double height { get { double height; - fill.item.get("height", out height); + fill.item.get ("height", out height); return height; } } - + public ColorModel (Lib.Components.Fill? fill, Lib.Components.Border? border = null) { type = fill != null ? Type.FILL : Type.BORDER; this.fill = fill; diff --git a/src/Services/EventBus.vala b/src/Services/EventBus.vala index bba983b1c..1cfd17737 100644 --- a/src/Services/EventBus.vala +++ b/src/Services/EventBus.vala @@ -52,8 +52,8 @@ public class Akira.Services.EventBus : Object { public signal void update_snap_decorators (); // this signal will be triggered every time color gets modified - public signal void color_changed(string color, double alpha); - public signal void color_mode_changed(string color_mode); + public signal void color_changed (string color, double alpha); + public signal void color_mode_changed (string color_mode); // Options panel signals. public signal void align_items (string align_action); diff --git a/src/Widgets/ColorMode.vala b/src/Widgets/ColorMode.vala index e377d2960..a888412c6 100644 --- a/src/Widgets/ColorMode.vala +++ b/src/Widgets/ColorMode.vala @@ -52,14 +52,14 @@ linear_gradient_button.set_tooltip_text (_("Linear Gradient")); linear_gradient_button.can_focus = false; linear_gradient_button.valign = Gtk.Align.CENTER; - + radial_gradient_button = new Gtk.Button.from_icon_name ("radial-gradient-button", Gtk.IconSize.DND); radial_gradient_button.set_tooltip_text (_("Radial Gradient")); radial_gradient_button.can_focus = false; radial_gradient_button.valign = Gtk.Align.CENTER; delete_step_button = new Gtk.Button.from_icon_name ("user-trash-symbolic"); - delete_step_button.set_tooltip_text(_("Delete Gradient Step")); + delete_step_button.set_tooltip_text (_("Delete Gradient Step")); delete_step_button.can_focus = false; delete_step_button.valign = Gtk.Align.CENTER; delete_step_button.halign = Gtk.Align.CENTER; @@ -70,38 +70,37 @@ radial_gradient_button.clicked.connect ( () => mode_button_pressed ("radial")); delete_step_button.clicked.connect (on_delete_button_pressed); - gradient_editor = new GradientEditor(window, model); + gradient_editor = new GradientEditor (window, model); // since color modes on border havent been implmented yet, disable these buttons - if(model.type == Akira.Models.ColorModel.Type.BORDER) { + if (model.type == Akira.Models.ColorModel.Type.BORDER) { solid_color_button.sensitive = false; linear_gradient_button.sensitive = false; radial_gradient_button.sensitive = false; delete_step_button.sensitive = false; - } Gtk.Separator separator = new Gtk.Separator (Gtk.Orientation.VERTICAL); separator.hexpand = true; - - buttons_grid = new Gtk.Grid(); + + buttons_grid = new Gtk.Grid (); buttons_grid.attach (solid_color_button, 0, 0); buttons_grid.attach (linear_gradient_button, 1, 0); buttons_grid.attach (radial_gradient_button, 2, 0); buttons_grid.attach (separator, 3, 0); - + buttons_grid.attach (gradient_editor, 0, 1, 4, 1); buttons_grid.attach (delete_step_button, 4, 1); } - private void mode_button_pressed(string _color_mode_type) { + private void mode_button_pressed (string _color_mode_type) { color_mode_type = _color_mode_type; - window.event_bus.color_mode_changed(color_mode_type); + window.event_bus.color_mode_changed (color_mode_type); } private void on_delete_button_pressed () { - if(color_mode_type != "solid") { - gradient_editor.delete_selected_step(); + if (color_mode_type != "solid") { + gradient_editor.delete_selected_step (); } } diff --git a/src/Widgets/ColorRow.vala b/src/Widgets/ColorRow.vala index 9b6cc766c..9e45db4de 100644 --- a/src/Widgets/ColorRow.vala +++ b/src/Widgets/ColorRow.vala @@ -79,7 +79,7 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { color_popover = new Gtk.Popover (color_button); color_popover.position = Gtk.PositionType.BOTTOM; - color_mode_widget = new ColorMode(model, this.window); + color_mode_widget = new ColorMode (model, this.window); color_button.clicked.connect (() => { init_color_chooser (); @@ -123,12 +123,12 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { color_set_manually = true; var new_rgba = Utils.Color.hex_to_rgba (field_hex); - + set_button_color (field_hex, model.alpha); - window.event_bus.color_changed(new_rgba.to_string(), model.alpha / 255.0); + window.event_bus.color_changed (new_rgba.to_string (), model.alpha / 255.0); - if(color_mode_widget.color_mode_type == "solid") { - model.color = new_rgba.to_string(); + if (color_mode_widget.color_mode_type == "solid") { + model.color = new_rgba.to_string (); } // Update the chooser widget only if it was already initialized. @@ -150,7 +150,6 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { opacity_field.entry.value = Math.round ((double) model.alpha / 255 * 100); opacity_field.entry.value_changed.connect (() => { - // Don't do anything if the color change came from the chooser. if (color_set_manually) { return; @@ -171,8 +170,8 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { var alpha = (int) ((double) opacity_field.entry.value / 100 * 255); //model.alpha = alpha; set_button_color (model.color, alpha); - - window.event_bus.color_changed(new_rgba.to_string(), alpha); + + window.event_bus.color_changed (new_rgba.to_string (), alpha); // Update the chooser widget only if it was already initialized. if (color_chooser_widget != null) { @@ -247,11 +246,11 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { set_chooser_color (model.color, model.alpha); color_chooser_widget.notify["rgba"].connect (() => { - string new_color = color_chooser_widget.rgba.to_string(); + string new_color = color_chooser_widget.rgba.to_string (); double alpha = color_chooser_widget.rgba.alpha; //color_mode_widget.on_color_changed(new_color, alpha); - window.event_bus.color_changed(new_color, alpha); + window.event_bus.color_changed (new_color, alpha); }); } diff --git a/src/Widgets/DirectionLine.vala b/src/Widgets/DirectionLine.vala index 9f33fdac1..cb8c729b5 100644 --- a/src/Widgets/DirectionLine.vala +++ b/src/Widgets/DirectionLine.vala @@ -32,106 +32,102 @@ public class Akira.Widgets.DirectionLine { private unowned Akira.Models.ColorModel.Type type; // dummy identity matrix - private Cairo.Matrix identity_mat = Cairo.Matrix.identity(); - + private Cairo.Matrix identity_mat = Cairo.Matrix.identity (); + public DirectionLine (Window _window, GradientEditor _gradient_editor, Akira.Models.ColorModel.Type type) { this.type = type; // since gradients on borders are not yet supported, dont draw direction line - if(type == Akira.Models.ColorModel.Type.BORDER) { + if (type == Akira.Models.ColorModel.Type.BORDER) { return; } - - window = _window; + + window = _window; canvas = window.main_window.main_canvas.canvas as Lib.Canvas; - selected_item = canvas.selected_bound_manager.selected_items.nth_data(0); - var root = canvas.get_root_item(); + selected_item = canvas.selected_bound_manager.selected_items.nth_data (0); + var root = canvas.get_root_item (); gradient_editor = _gradient_editor; - start_nob = new Lib.Selection.Nob(root, Lib.Managers.NobManager.Nob.GRADIENT_START); - end_nob = new Lib.Selection.Nob(root, Lib.Managers.NobManager.Nob.GRADIENT_END); + start_nob = new Lib.Selection.Nob (root, Lib.Managers.NobManager.Nob.GRADIENT_START); + end_nob = new Lib.Selection.Nob (root, Lib.Managers.NobManager.Nob.GRADIENT_END); - start_nob.set_rectangle(); - end_nob.set_rectangle(); + start_nob.set_rectangle (); + end_nob.set_rectangle (); - update_visibility("solid"); + update_visibility ("solid"); // initial position of direction nobs will be outside the canvas. // when CanvasItem gets selected, they will be placed along the diagonal - start_nob.update_state(identity_mat, -10, -10, false); - end_nob.update_state(identity_mat, -10, -10, false); + start_nob.update_state (identity_mat, -10, -10, false); + end_nob.update_state (identity_mat, -10, -10, false); + + window.event_bus.color_mode_changed.connect (update_visibility); + canvas.button_press_event.connect (on_buton_press_event); + canvas.button_release_event.connect (on_button_release_event); - window.event_bus.color_mode_changed.connect(update_visibility); - canvas.button_press_event.connect(on_buton_press_event); - canvas.button_release_event.connect(on_button_release_event); - window.event_bus.selected_items_list_changed.connect (() => { - if(type == Akira.Models.ColorModel.Type.BORDER) { + if (type == Akira.Models.ColorModel.Type.BORDER) { return; } - if(canvas.selected_bound_manager.selected_items.length() == 0) { - destroy_direction_line(); + if (canvas.selected_bound_manager.selected_items.length () == 0) { + destroy_direction_line (); } - + }); - + } - public void get_direction_coords(out double x0, out double y0, out double x1, out double y1) { + public void get_direction_coords (out double x0, out double y0, out double x1, out double y1) { x0 = start_nob.center_x - selected_item.coordinates.x; y0 = start_nob.center_y - selected_item.coordinates.y; x1 = end_nob.center_x - selected_item.coordinates.x; y1 = end_nob.center_y - selected_item.coordinates.y; - } - private bool on_buton_press_event(Gdk.EventButton event) { - if(type == Akira.Models.ColorModel.Type.BORDER) { + private bool on_buton_press_event (Gdk.EventButton event) { + if (type == Akira.Models.ColorModel.Type.BORDER) { return false; } - if(start_nob.hit_test(event.x, event.y, canvas.get_scale())) { + if (start_nob.hit_test (event.x, event.y, canvas.get_scale ())) { selected_nob = start_nob; - - canvas.motion_notify_event.connect(on_motion_event); + canvas.motion_notify_event.connect (on_motion_event); // return true here to prevent the button press event from propogating. // this is because in transform_manager, this event causes the canvas item to move return true; - } else if(end_nob.hit_test(event.x, event.y, canvas.get_scale())) { + } else if (end_nob.hit_test (event.x, event.y, canvas.get_scale ())) { selected_nob = end_nob; - - canvas.motion_notify_event.connect(on_motion_event); + canvas.motion_notify_event.connect (on_motion_event); return true; } return false; } - private bool on_motion_event(Gdk.EventMotion event) { - selected_nob.update_state(identity_mat, event.x, event.y, true); - gradient_editor.create_gradient_pattern(); + private bool on_motion_event (Gdk.EventMotion event) { + selected_nob.update_state (identity_mat, event.x, event.y, true); + gradient_editor.create_gradient_pattern (); return true; } - private bool on_button_release_event(Gdk.EventButton event) { - if(type == Akira.Models.ColorModel.Type.BORDER) { + private bool on_button_release_event (Gdk.EventButton event) { + if (type == Akira.Models.ColorModel.Type.BORDER) { return false; } - canvas.motion_notify_event.disconnect(on_motion_event); + canvas.motion_notify_event.disconnect (on_motion_event); return false; } - private void update_visibility(string color_mode) { - if(type == Akira.Models.ColorModel.Type.BORDER) { + private void update_visibility (string color_mode) { + if (type == Akira.Models.ColorModel.Type.BORDER) { return; } - if(start_nob.center_x == -10 || start_nob.center_y == -10) { - print("first time setup\n"); + if (start_nob.center_x == -10 || start_nob.center_y == -10) { // if this is the first time the direction line is being displayed, // set its default position along diagonal double pos_x = selected_item.coordinates.x; @@ -142,51 +138,51 @@ public class Akira.Widgets.DirectionLine { // TODO: get the rotation matrix and artboard matrix from item and recalculate position - start_nob.update_state(identity_mat, pos_x+offset, pos_y+offset, true); - end_nob.update_state(identity_mat, pos_x+width-offset, pos_y+height-offset, true); + start_nob.update_state (identity_mat, pos_x + offset, pos_y + offset, true); + end_nob.update_state (identity_mat, pos_x + width - offset, pos_y + height - offset, true); } color_mode_type = color_mode; - if(color_mode == "solid") { - hide_direction_line(); + if (color_mode == "solid") { + hide_direction_line (); } else { - show_direction_line(); + show_direction_line (); } } - private void hide_direction_line() { - if(type == Akira.Models.ColorModel.Type.BORDER) { + private void hide_direction_line () { + if (type == Akira.Models.ColorModel.Type.BORDER) { return; } - start_nob.set("visibility", Goo.CanvasItemVisibility.HIDDEN); - end_nob.set("visibility", Goo.CanvasItemVisibility.HIDDEN); + start_nob.set ("visibility", Goo.CanvasItemVisibility.HIDDEN); + end_nob.set ("visibility", Goo.CanvasItemVisibility.HIDDEN); } - private void show_direction_line() { - if(type == Akira.Models.ColorModel.Type.BORDER) { + private void show_direction_line () { + if (type == Akira.Models.ColorModel.Type.BORDER) { return; } - start_nob.set("visibility", Goo.CanvasItemVisibility.VISIBLE); - end_nob.set("visibility", Goo.CanvasItemVisibility.VISIBLE); + start_nob.set ("visibility", Goo.CanvasItemVisibility.VISIBLE); + end_nob.set ("visibility", Goo.CanvasItemVisibility.VISIBLE); } - private void destroy_direction_line() { - if(type == Akira.Models.ColorModel.Type.BORDER) { + private void destroy_direction_line () { + if (type == Akira.Models.ColorModel.Type.BORDER) { return; } // we need to destroy direction line everytime an item is deselected. This is because // when and item is selected, it creates a new instance of DirectionLine. This results in duplicate // start_nob and end_nob - window.event_bus.color_mode_changed.disconnect(update_visibility); - canvas.button_press_event.disconnect(on_buton_press_event); - canvas.button_release_event.disconnect(on_button_release_event); + window.event_bus.color_mode_changed.disconnect (update_visibility); + canvas.button_press_event.disconnect (on_buton_press_event); + canvas.button_release_event.disconnect (on_button_release_event); - hide_direction_line(); - start_nob.remove(); - end_nob.remove(); + hide_direction_line (); + start_nob.remove (); + end_nob.remove (); } -} \ No newline at end of file +} diff --git a/src/Widgets/GradientEditor.vala b/src/Widgets/GradientEditor.vala index 4e872c465..802e32738 100644 --- a/src/Widgets/GradientEditor.vala +++ b/src/Widgets/GradientEditor.vala @@ -24,7 +24,7 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { private int widget_height; private int widget_x; private int widget_y; - + private Window window; private Models.ColorModel model; private string color_mode_type; @@ -32,173 +32,171 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { // list to store all stop colors in order private Gee.ArrayList stop_colors; private StopColor selected_stop_color; - + // Cairo.Pattern to color the Canvas.Item private Cairo.Pattern gradient_pattern; private DirectionLine direction_line; - public GradientEditor(Window _window, Models.ColorModel _model) { + public GradientEditor (Window _window, Models.ColorModel _model) { window = _window; model = _model; - + color_mode_type = "solid"; - direction_line = new DirectionLine(_window, this, model.type); - gradient_pattern = new Cairo.Pattern.linear(0,0,0,0); + direction_line = new DirectionLine (_window, this, model.type); + gradient_pattern = new Cairo.Pattern.linear (0,0,0,0); - set_hexpand(true); + set_hexpand (true); height_request = 35; - set_events(Gdk.EventMask.BUTTON_PRESS_MASK); - set_above_child(false); + set_events (Gdk.EventMask.BUTTON_PRESS_MASK); + set_above_child (false); // the stop colors at start and end are fixed. StopColor has been defined at the end - stop_colors = new Gee.ArrayList(); - stop_colors.insert(0, new StopColor("#000", 1, 0)); - stop_colors.insert(1, new StopColor("#fff", 1, 100)); - + stop_colors = new Gee.ArrayList (); + stop_colors.insert (0, new StopColor ("#000", 1, 0)); + stop_colors.insert (1, new StopColor ("#fff", 1, 100)); + selected_stop_color = stop_colors[0]; - size_allocate.connect( () => { - widget_width = get_allocated_width(); - widget_height = get_allocated_height(); + size_allocate.connect ( () => { + widget_width = get_allocated_width (); + widget_height = get_allocated_height (); - draw.connect_after ( (context) => {return redraw_editor(context);}); - - button_press_event.connect( (event) => {return on_button_press(event);}); - button_release_event.connect ( (event) => {return on_button_release(event); }); - - window.event_bus.color_mode_changed.connect(on_color_mode_changed); - window.event_bus.color_changed.connect(on_color_changed); + draw.connect_after ( (context) => {return redraw_editor (context);}); - }); + button_press_event.connect ( (event) => {return on_button_press (event);}); + button_release_event.connect ( (event) => {return on_button_release (event); }); + + window.event_bus.color_mode_changed.connect (on_color_mode_changed); + window.event_bus.color_changed.connect (on_color_changed); - //window.event_bus.color_changed.connect(on_color_changed); + }); } - private bool redraw_editor(Cairo.Context context) { + private bool redraw_editor (Cairo.Context context) { if (color_mode_type != "solid") { double center_y = widget_y + widget_height / 2; - + // line through the center. acts as a guideline for the user to place the stop colors - context.set_source_rgba(0,0,0,1); - context.move_to(widget_x, center_y); - context.line_to(widget_x + widget_width, center_y); - context.stroke(); + context.set_source_rgba (0, 0, 0, 1); + context.move_to (widget_x, center_y); + context.line_to (widget_x + widget_width, center_y); + context.stroke (); - foreach(var item in stop_colors) { + foreach (var item in stop_colors) { double center_x = widget_x + item.position * widget_width / 100; double radius = 5; - + // outer circle of light color. - context.set_source_rgba(1,1,1,1); - context.arc(center_x, center_y, radius + 2, 0, 2 * Math.PI); - context.fill(); - + context.set_source_rgba (1, 1, 1, 1); + context.arc (center_x, center_y, radius + 2, 0, 2 * Math.PI); + context.fill (); + // inner circle of dark color. contrast makes it easier to find stop colors. - if(item.position == selected_stop_color.position) { - context.set_source_rgba(0, 0, 1, 1); + if (item.position == selected_stop_color.position) { + context.set_source_rgba (0, 0, 1, 1); } else { - context.set_source_rgba(0,0,0, 1); + context.set_source_rgba (0, 0, 0, 1); } - context.arc(center_x, center_y, radius, 0, 2 * Math.PI); - context.fill(); + context.arc (center_x, center_y, radius, 0, 2 * Math.PI); + context.fill (); } - - update_style(); + + update_style (); } - + return false; } private bool on_button_press (Gdk.EventButton event) { if (color_mode_type != "solid") { var position = (event.x / widget_width) * 100; - get_stop_color_at(position); - + get_stop_color_at (position); + // trigger redraw for the Editor. This renders the stop color - queue_draw_area(widget_x, widget_y, widget_width, widget_height); + queue_draw_area (widget_x, widget_y, widget_width, widget_height); } - + // start the on motion event handler // this will drag the stop color around as long as the button is pressed - motion_notify_event.connect( on_motion_event ); - + motion_notify_event.connect ( on_motion_event ); + return false; } private bool on_motion_event (Gdk.EventMotion event) { - if(color_mode_type != "solid") { - int index = stop_colors.index_of(selected_stop_color); - - if(index == 0 || index == stop_colors.size - 1) { + if (color_mode_type != "solid") { + int index = stop_colors.index_of (selected_stop_color); + + if (index == 0 || index == stop_colors.size - 1) { return false; } - + stop_colors[index].position = (event.x / widget_width) * 100; - - queue_draw_area(widget_x, widget_y, widget_width, widget_height); + + queue_draw_area (widget_x, widget_y, widget_width, widget_height); } - + return false; } - + private bool on_button_release (Gdk.EventButton event) { // after user releases the button, stop dragging the stop color motion_notify_event.disconnect (on_motion_event); - + return false; } - public void on_color_changed(string color, double alpha) { - if(color_mode_type != "solid") { - int index = stop_colors.index_of(selected_stop_color); - + public void on_color_changed (string color, double alpha) { + if (color_mode_type != "solid") { + int index = stop_colors.index_of (selected_stop_color); + stop_colors[index].color = color; stop_colors[index].alpha = alpha; - - queue_draw_area(widget_x, widget_y, widget_width, widget_height); + + queue_draw_area (widget_x, widget_y, widget_width, widget_height); } else { model.color = color; model.alpha = (int) (alpha * 255); } } - + public void delete_selected_step () { // get the index of selected step - int index = stop_colors.index_of(selected_stop_color); - + int index = stop_colors.index_of (selected_stop_color); + // the first and stop colors are fixed and should not be deleted - if(index == 0 || index == stop_colors.size - 1) { + if (index == 0 || index == stop_colors.size - 1) { return; } - - selected_stop_color = stop_colors[index-1]; - stop_colors.remove_at(index); - + + selected_stop_color = stop_colors[index - 1]; + stop_colors.remove_at (index); + // redraw the new widget - queue_draw_area(widget_x, widget_y, widget_width, widget_height); + queue_draw_area (widget_x, widget_y, widget_width, widget_height); } - private void get_stop_color_at(double position) { + private void get_stop_color_at (double position) { int index; - if(is_stop_color_at_coordinate(position, out index)) { + if (is_stop_color_at_coordinate (position, out index)) { selected_stop_color = stop_colors[index]; } else { string prev_color = stop_colors[index].color; double prev_alpha = stop_colors[index].alpha; - stop_colors.insert(index, new StopColor(prev_color, prev_alpha, position)); + stop_colors.insert (index, new StopColor (prev_color, prev_alpha, position)); selected_stop_color = stop_colors[index]; } } - - private bool is_stop_color_at_coordinate(double coordinate, out int index) { + + private bool is_stop_color_at_coordinate (double coordinate, out int index) { index = 0; - for(index = 0; index < stop_colors.size; ++index) { - if(stop_colors[index].is_close_to(coordinate, widget_width)) { + for (index = 0; index < stop_colors.size; ++index) { + if (stop_colors[index].is_close_to (coordinate, widget_width)) { return true; } else if (stop_colors[index].position > coordinate) { return false; @@ -208,89 +206,89 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { return false; } - private void update_style() { + private void update_style () { // since gradients on direction line are not supported, dont draw direction line - if(model.type == Akira.Models.ColorModel.Type.BORDER) { + if (model.type == Akira.Models.ColorModel.Type.BORDER) { return; } string css_style = ""; - string stop_color_string = stop_colors_as_string(); + string stop_color_string = stop_colors_as_string (); - if(color_mode_type == "solid") { + if (color_mode_type == "solid") { css_style = "@bg_color"; } else { - css_style = """linear-gradient(to right %s)""".printf(stop_color_string); + css_style = """linear-gradient(to right %s)""".printf (stop_color_string); } - + try { var provider = new Gtk.CssProvider (); var context = get_style_context (); - + var editor_css_style = """*{ background: %s - }""".printf(css_style); + }""".printf (css_style); provider.load_from_data (editor_css_style, editor_css_style.length); context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); - + } catch (Error e) { warning ("Style error: %s", e.message); debug ("%s %s\n", name, css_style); } - create_gradient_pattern(); + create_gradient_pattern (); } - private string stop_colors_as_string() { + private string stop_colors_as_string () { string colors_string = ""; - foreach(StopColor item in stop_colors) { - colors_string += "," + item.to_string(); + foreach (StopColor item in stop_colors) { + colors_string += "," + item.to_string (); } - + return colors_string; } private void on_color_mode_changed (string _color_mode_type) { color_mode_type = _color_mode_type; - update_style(); + update_style (); } - + public void create_gradient_pattern () { double item_height, item_width; - model.get("height", out item_height); - model.get("width", out item_width); + model.get ("height", out item_height); + model.get ("width", out item_width); double x0, y0, x1, y1; - direction_line.get_direction_coords(out x0, out y0, out x1, out y1); - - if(color_mode_type == "solid") { + direction_line.get_direction_coords (out x0, out y0, out x1, out y1); + + if (color_mode_type == "solid") { // for solid color, create an empty pattern. In Fills, we check if stop colors exists // for this pattern. If they dont, then the Pattern is not applied - gradient_pattern = new Cairo.Pattern.linear(x0, y0, x1, y1); + gradient_pattern = new Cairo.Pattern.linear (x0, y0, x1, y1); model.pattern = gradient_pattern; return; - } else if(color_mode_type == "linear") { - gradient_pattern = new Cairo.Pattern.linear(x0, y0, x1, y1); + } else if (color_mode_type == "linear") { + gradient_pattern = new Cairo.Pattern.linear (x0, y0, x1, y1); } else { double dx = x0 - x1; double dy = y0 - y1; - int radius = (int) Math.sqrt( dx*dx + dy*dy ); - gradient_pattern = new Cairo.Pattern.radial(x0, y0, 0, x0, y0, radius); + int radius = (int) Math.sqrt ( dx * dx + dy * dy ); + gradient_pattern = new Cairo.Pattern.radial (x0, y0, 0, x0, y0, radius); } - - for(int index = 0; index < stop_colors.size; ++index) { + + for (int index = 0; index < stop_colors.size; ++index) { var stop_color = stop_colors[index]; - - var rgba = Gdk.RGBA(); - rgba.parse(stop_color.color); - + + var rgba = Gdk.RGBA (); + rgba.parse (stop_color.color); + double offset = stop_color.position / 100; - - gradient_pattern.add_color_stop_rgba(offset, rgba.red, rgba.green, rgba.blue, stop_color.alpha); + + gradient_pattern.add_color_stop_rgba (offset, rgba.red, rgba.green, rgba.blue, stop_color.alpha); } - + model.pattern = gradient_pattern; } @@ -300,35 +298,35 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { public double position; public double alpha; - public StopColor(string _color, double _alpha, double _position) { + public StopColor (string _color, double _alpha, double _position) { color = _color; position = _position; alpha = _alpha; } public bool is_close_to (double other_position, double width) { - var distance = (position - other_position).abs(); + var distance = (position - other_position).abs (); distance = (distance * width ) / 100; // there has to be a min distance between 2 stop colors to easily select them // this distance is taken as 7 because that is the radius the StopColor is drawn // in the gradient editor - if( distance <= 7 ) { + if ( distance <= 7 ) { return true; } return false; } - - public string to_string() { - Gdk.RGBA color_rgba = Gdk.RGBA(); - color_rgba.parse(color); - + + public string to_string () { + Gdk.RGBA color_rgba = Gdk.RGBA (); + color_rgba.parse (color); + int red = (int) (color_rgba.red * 255); int green = (int) (color_rgba.green * 255); int blue = (int) (color_rgba.blue * 255); int alpha = (int) (alpha * 255); - - return """ rgba(%d, %d, %d, %d) %f""".printf(red, green, blue, alpha, position) + "%"; + + return """ rgba(%d, %d, %d, %d) %f""".printf (red, green, blue, alpha, position) + "%"; } } } From d9b9b393ae38e5286bf9f9ce9a7703ab58a7831b Mon Sep 17 00:00:00 2001 From: Ashish Shevale <64722310+AshishS-1123@users.noreply.github.com> Date: Sat, 3 Jul 2021 13:58:17 +0530 Subject: [PATCH 26/35] Delete wrongly added hidden file --- src/Widgets/.fuse_hidden0000003e00000009 | 167 ----------------------- 1 file changed, 167 deletions(-) delete mode 100644 src/Widgets/.fuse_hidden0000003e00000009 diff --git a/src/Widgets/.fuse_hidden0000003e00000009 b/src/Widgets/.fuse_hidden0000003e00000009 deleted file mode 100644 index cd953ffba..000000000 --- a/src/Widgets/.fuse_hidden0000003e00000009 +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2021 Alecaddd (https://alecaddd.com) - * - * This file is part of Akira. - * - * Akira 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. - * - * Akira 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 Akira. If not, see . - * - * Authored by: Ashish Shevale -*/ -public class Akira.Widgets.DirectionLine { - public Lib.Selection.Nob start_nob; - public Lib.Selection.Nob end_nob; - private Lib.Selection.Nob selected_nob; - - private string color_mode_type; - - private Lib.Canvas canvas; - private Lib.Items.CanvasItem selected_item; - private unowned GradientEditor gradient_editor; - private unowned Akira.Window window; - - // dummy identity matrix - private Cairo.Matrix identity_mat = Cairo.Matrix.identity(); - - public DirectionLine (Window _window, GradientEditor _gradient_editor, Akira.Models.ColorModel.Type type) { - print("create direction line\n"); - // since gradients on borders are not yet supported, dont draw direction line - if(type == Akira.Models.ColorModel.Type.BORDER) { - return; - } - - print("create new direction \n"); - window = _window; - canvas = window.main_window.main_canvas.canvas as Lib.Canvas; - selected_item = canvas.selected_bound_manager.selected_items.nth_data(0); - var root = canvas.get_root_item(); - gradient_editor = _gradient_editor; - - start_nob = new Lib.Selection.Nob(root, Lib.Managers.NobManager.Nob.GRADIENT_START); - end_nob = new Lib.Selection.Nob(root, Lib.Managers.NobManager.Nob.GRADIENT_END); - - start_nob.set_rectangle(); - end_nob.set_rectangle(); - - start_nob.update_state(identity_mat, 50, 50, false); - end_nob.update_state(identity_mat, 150, 150, false); - - set_initial_position(canvas.selected_bound_manager.selected_items); - update_visibility("solid"); - - window.event_bus.color_mode_changed.connect(update_visibility); - canvas.button_press_event.connect(on_buton_press_event); - canvas.button_release_event.connect(on_button_release_event); - - window.event_bus.selected_items_list_changed.connect (() => { - if(canvas.selected_bound_manager.selected_items.length() == 0) { - destroy_direction_line(); - } else { - if(color_mode_type != "solid") { - show_direction_line(); - } - } - }); - } - - public void get_direction_coords(out double x0, out double y0, out double x1, out double y1) { - x0 = start_nob.center_x - selected_item.coordinates.x; - y0 = start_nob.center_y - selected_item.coordinates.y; - x1 = end_nob.center_x - selected_item.coordinates.x; - y1 = end_nob.center_y - selected_item.coordinates.y; - - } - - private bool on_buton_press_event(Gdk.EventButton event) { - if(start_nob.hit_test(event.x, event.y, canvas.get_scale())) { - selected_nob = start_nob; - - canvas.motion_notify_event.connect(on_motion_event); - - // return true here to prevent the button press event from propogating. - // this is because in transform_manager, this event causes the canvas item to move - return true; - } else if(end_nob.hit_test(event.x, event.y, canvas.get_scale())) { - selected_nob = end_nob; - - canvas.motion_notify_event.connect(on_motion_event); - - return true; - } - return false; - } - - private bool on_motion_event(Gdk.EventMotion event) { - selected_nob.update_state(identity_mat, event.x, event.y, true); - gradient_editor.create_gradient_pattern(); - - return true; - } - - private bool on_button_release_event(Gdk.EventButton event) { - canvas.motion_notify_event.disconnect(on_motion_event); - return false; - } - - private void update_visibility(string color_mode) { - color_mode_type = color_mode; - - if(color_mode == "solid") { - hide_direction_line(); - } else { - show_direction_line(); - } - } - - private void hide_direction_line() { - start_nob.set("visibility", Goo.CanvasItemVisibility.HIDDEN); - end_nob.set("visibility", Goo.CanvasItemVisibility.HIDDEN); - } - - private void show_direction_line() { - start_nob.set("visibility", Goo.CanvasItemVisibility.VISIBLE); - end_nob.set("visibility", Goo.CanvasItemVisibility.VISIBLE); - } - - private void destroy_direction_line() { - // we need to destroy direction line everytime an item is deselected. This is because - // when and item is selected, it creates a new instance of DirectionLine. This results in duplicate - // start_nob and end_nob - window.event_bus.color_mode_changed.disconnect(update_visibility); - canvas.button_press_event.disconnect(on_buton_press_event); - canvas.button_release_event.disconnect(on_button_release_event); - - hide_direction_line(); - start_nob.remove(); - end_nob.remove(); - } - - private void set_initial_position (List items) { - if(items.length() == 1) { - var item = items.first().data; - - double pos_x = item.coordinates.x; - double pos_y = item.coordinates.y; - double width = item.size.width; - double height = item.size.height; - - // TODO: get the rotation matrix and artboard matrix from item and recalculate position - - start_nob.update_state(identity_mat, pos_x+10, pos_y+10, true); - end_nob.update_state(identity_mat, pos_x+width-10, pos_y+height-10, true); - - } else { - // TODO: implement gradients when multiple items are selected - } - } -} \ No newline at end of file From d0420bbc5b3c6f8932c0d25f888093620fe30254 Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Thu, 15 Jul 2021 12:46:11 +0530 Subject: [PATCH 27/35] Load initial color mode from ColorModel --- src/Models/ColorModel.vala | 9 +++++++++ src/Widgets/DirectionLine.vala | 15 ++++++++------- src/Widgets/GradientEditor.vala | 4 ++-- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/Models/ColorModel.vala b/src/Models/ColorModel.vala index 7c5d3b258..0fcdd7c47 100644 --- a/src/Models/ColorModel.vala +++ b/src/Models/ColorModel.vala @@ -33,6 +33,15 @@ public class Akira.Models.ColorModel : GLib.Object { BORDER } + public string color_mode { + get { + return "solid"; + } + set { + color_mode = value; + } + } + public Cairo.Pattern pattern { owned get { return pattern; diff --git a/src/Widgets/DirectionLine.vala b/src/Widgets/DirectionLine.vala index cb8c729b5..3668bc752 100644 --- a/src/Widgets/DirectionLine.vala +++ b/src/Widgets/DirectionLine.vala @@ -27,17 +27,17 @@ public class Akira.Widgets.DirectionLine { private Lib.Canvas canvas; private Lib.Items.CanvasItem selected_item; - private unowned GradientEditor gradient_editor; - private unowned Window window; - private unowned Akira.Models.ColorModel.Type type; + private GradientEditor gradient_editor; + private Window window; + private Akira.Models.ColorModel.Type type; // dummy identity matrix private Cairo.Matrix identity_mat = Cairo.Matrix.identity (); - public DirectionLine (Window _window, GradientEditor _gradient_editor, Akira.Models.ColorModel.Type type) { - this.type = type; - // since gradients on borders are not yet supported, dont draw direction line + public DirectionLine (Window _window, GradientEditor _gradient_editor, Akira.Models.ColorModel model) { + type = model.type; + // since gradients on borders are not yet supported, dont draw direction line if (type == Akira.Models.ColorModel.Type.BORDER) { return; } @@ -54,7 +54,8 @@ public class Akira.Widgets.DirectionLine { start_nob.set_rectangle (); end_nob.set_rectangle (); - update_visibility ("solid"); + color_mode_type = model.color_mode; + update_visibility (model.color_mode); // initial position of direction nobs will be outside the canvas. // when CanvasItem gets selected, they will be placed along the diagonal diff --git a/src/Widgets/GradientEditor.vala b/src/Widgets/GradientEditor.vala index 802e32738..03f92d617 100644 --- a/src/Widgets/GradientEditor.vala +++ b/src/Widgets/GradientEditor.vala @@ -41,9 +41,9 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { window = _window; model = _model; - color_mode_type = "solid"; + color_mode_type = model.color_mode; - direction_line = new DirectionLine (_window, this, model.type); + direction_line = new DirectionLine (_window, this, _model); gradient_pattern = new Cairo.Pattern.linear (0,0,0,0); set_hexpand (true); From 58ab966739f39c44b3a92cc95418ed793e4b4d53 Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Thu, 15 Jul 2021 13:14:05 +0530 Subject: [PATCH 28/35] Load Cairo.Pattern in ColorModel from Fill property --- src/Models/ColorModel.vala | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/Models/ColorModel.vala b/src/Models/ColorModel.vala index 0fcdd7c47..76dbb1322 100644 --- a/src/Models/ColorModel.vala +++ b/src/Models/ColorModel.vala @@ -35,6 +35,22 @@ public class Akira.Models.ColorModel : GLib.Object { public string color_mode { get { + if(type == Type.FILL) { + + int stop_count; + fill.gradient_pattern.get_color_stop_count(out stop_count); + + if(stop_count != 0) { + // if the gradient pattern has at least 1 stop color and is of linear type + if(fill.gradient_pattern.get_type() == Cairo.PatternType.LINEAR) { + return "linear"; + } + + return "radial"; + } + } + + // in all other cases and for border type, color mode is solid return "solid"; } set { From 5b2a84c9639e4b8e4c8333f2fbee66c45237e34a Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Fri, 16 Jul 2021 10:00:53 +0530 Subject: [PATCH 29/35] Load pattern when item selected after deselection --- src/Lib/Components/Fill.vala | 1 + src/Lib/Components/Fills.vala | 3 +- src/Models/ColorModel.vala | 26 ++++---------- src/Widgets/ColorMode.vala | 5 +-- src/Widgets/ColorRow.vala | 3 +- src/Widgets/DirectionLine.vala | 7 ---- src/Widgets/GradientEditor.vala | 63 ++++++++++++++++++++++----------- 7 files changed, 57 insertions(+), 51 deletions(-) diff --git a/src/Lib/Components/Fill.vala b/src/Lib/Components/Fill.vala index 781c22228..71b744837 100644 --- a/src/Lib/Components/Fill.vala +++ b/src/Lib/Components/Fill.vala @@ -30,6 +30,7 @@ public class Akira.Lib.Components.Fill : Component { public Gdk.RGBA color { get; set; } public Cairo.Pattern gradient_pattern { get; set; } + public string color_mode { get; set; default = "solid"; } // Store the hexadecimal string version of the color (E.g.: #FF00CC) public string hex { get; set; } diff --git a/src/Lib/Components/Fills.vala b/src/Lib/Components/Fills.vala index 0fc5779f4..7f73c7b88 100644 --- a/src/Lib/Components/Fills.vala +++ b/src/Lib/Components/Fills.vala @@ -97,7 +97,8 @@ public class Akira.Lib.Components.Fills : Component { if (item is Items.CanvasArtboard) { ((Items.CanvasArtboard) item).background.set ("fill-pattern", fill.gradient_pattern); } else { - item.set ("fill-pattern", fill.gradient_pattern); + item.set ("fill-pattern", fill.gradient_pattern); double x0, y0, x1, y1; + fill.gradient_pattern.get_linear_points(out x0, out y0, out x1, out y1); } // since we dont have the functionality of blending gradients, diff --git a/src/Models/ColorModel.vala b/src/Models/ColorModel.vala index 76dbb1322..5b1606453 100644 --- a/src/Models/ColorModel.vala +++ b/src/Models/ColorModel.vala @@ -35,36 +35,22 @@ public class Akira.Models.ColorModel : GLib.Object { public string color_mode { get { - if(type == Type.FILL) { - - int stop_count; - fill.gradient_pattern.get_color_stop_count(out stop_count); - - if(stop_count != 0) { - // if the gradient pattern has at least 1 stop color and is of linear type - if(fill.gradient_pattern.get_type() == Cairo.PatternType.LINEAR) { - return "linear"; - } - - return "radial"; - } - } - - // in all other cases and for border type, color mode is solid - return "solid"; + return type == Type.FILL ? fill.color_mode : "solid"; } set { - color_mode = value; + if(type == Type.FILL) { + fill.color_mode = value; + } } } public Cairo.Pattern pattern { owned get { - return pattern; + return type == Type.FILL ? fill.gradient_pattern : new Cairo.Pattern.linear(0,0,0,0); } set { if (type == Type.FILL) { - fill.gradient_pattern = value; + fill.set("gradient-pattern", value); } } } diff --git a/src/Widgets/ColorMode.vala b/src/Widgets/ColorMode.vala index a888412c6..0a2adcf61 100644 --- a/src/Widgets/ColorMode.vala +++ b/src/Widgets/ColorMode.vala @@ -35,7 +35,7 @@ public ColorMode (Models.ColorModel _model, Window _window) { model = _model; - color_mode_type = "solid"; + color_mode_type = model.color_mode; window = _window; init_button_ui (); @@ -70,7 +70,7 @@ radial_gradient_button.clicked.connect ( () => mode_button_pressed ("radial")); delete_step_button.clicked.connect (on_delete_button_pressed); - gradient_editor = new GradientEditor (window, model); + gradient_editor = new GradientEditor (window, model, model.pattern); // since color modes on border havent been implmented yet, disable these buttons if (model.type == Akira.Models.ColorModel.Type.BORDER) { @@ -95,6 +95,7 @@ private void mode_button_pressed (string _color_mode_type) { color_mode_type = _color_mode_type; + model.color_mode = color_mode_type; window.event_bus.color_mode_changed (color_mode_type); } diff --git a/src/Widgets/ColorRow.vala b/src/Widgets/ColorRow.vala index 9e45db4de..2693ecf32 100644 --- a/src/Widgets/ColorRow.vala +++ b/src/Widgets/ColorRow.vala @@ -245,11 +245,12 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { // Set the chooser color before connecting the signal. set_chooser_color (model.color, model.alpha); + window.event_bus.color_mode_changed(model.color_mode); + color_chooser_widget.notify["rgba"].connect (() => { string new_color = color_chooser_widget.rgba.to_string (); double alpha = color_chooser_widget.rgba.alpha; - //color_mode_widget.on_color_changed(new_color, alpha); window.event_bus.color_changed (new_color, alpha); }); } diff --git a/src/Widgets/DirectionLine.vala b/src/Widgets/DirectionLine.vala index 3668bc752..ea1ae3878 100644 --- a/src/Widgets/DirectionLine.vala +++ b/src/Widgets/DirectionLine.vala @@ -23,8 +23,6 @@ public class Akira.Widgets.DirectionLine { public Lib.Selection.Nob end_nob; private Lib.Selection.Nob selected_nob; - private string color_mode_type; - private Lib.Canvas canvas; private Lib.Items.CanvasItem selected_item; private GradientEditor gradient_editor; @@ -54,7 +52,6 @@ public class Akira.Widgets.DirectionLine { start_nob.set_rectangle (); end_nob.set_rectangle (); - color_mode_type = model.color_mode; update_visibility (model.color_mode); // initial position of direction nobs will be outside the canvas. @@ -137,14 +134,10 @@ public class Akira.Widgets.DirectionLine { double height = selected_item.size.height; double offset = Akira.Lib.Selection.Nob.NOB_SIZE; - // TODO: get the rotation matrix and artboard matrix from item and recalculate position - start_nob.update_state (identity_mat, pos_x + offset, pos_y + offset, true); end_nob.update_state (identity_mat, pos_x + width - offset, pos_y + height - offset, true); } - color_mode_type = color_mode; - if (color_mode == "solid") { hide_direction_line (); } else { diff --git a/src/Widgets/GradientEditor.vala b/src/Widgets/GradientEditor.vala index 03f92d617..f7731521e 100644 --- a/src/Widgets/GradientEditor.vala +++ b/src/Widgets/GradientEditor.vala @@ -27,7 +27,6 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { private Window window; private Models.ColorModel model; - private string color_mode_type; // list to store all stop colors in order private Gee.ArrayList stop_colors; @@ -37,14 +36,13 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { private Cairo.Pattern gradient_pattern; private DirectionLine direction_line; - public GradientEditor (Window _window, Models.ColorModel _model) { + public GradientEditor (Window _window, Models.ColorModel _model, Cairo.Pattern pattern) { window = _window; model = _model; - color_mode_type = model.color_mode; - direction_line = new DirectionLine (_window, this, _model); - gradient_pattern = new Cairo.Pattern.linear (0,0,0,0); + gradient_pattern = pattern; + parse_stop_colors_from_pattern(); set_hexpand (true); height_request = 35; @@ -52,11 +50,6 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { set_events (Gdk.EventMask.BUTTON_PRESS_MASK); set_above_child (false); - // the stop colors at start and end are fixed. StopColor has been defined at the end - stop_colors = new Gee.ArrayList (); - stop_colors.insert (0, new StopColor ("#000", 1, 0)); - stop_colors.insert (1, new StopColor ("#fff", 1, 100)); - selected_stop_color = stop_colors[0]; size_allocate.connect ( () => { @@ -75,7 +68,7 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { } private bool redraw_editor (Cairo.Context context) { - if (color_mode_type != "solid") { + if (model.color_mode != "solid") { double center_y = widget_y + widget_height / 2; // line through the center. acts as a guideline for the user to place the stop colors @@ -110,7 +103,7 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { } private bool on_button_press (Gdk.EventButton event) { - if (color_mode_type != "solid") { + if (model.color_mode != "solid") { var position = (event.x / widget_width) * 100; get_stop_color_at (position); @@ -126,7 +119,7 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { } private bool on_motion_event (Gdk.EventMotion event) { - if (color_mode_type != "solid") { + if (model.color_mode != "solid") { int index = stop_colors.index_of (selected_stop_color); if (index == 0 || index == stop_colors.size - 1) { @@ -149,7 +142,7 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { } public void on_color_changed (string color, double alpha) { - if (color_mode_type != "solid") { + if (model.color_mode != "solid") { int index = stop_colors.index_of (selected_stop_color); stop_colors[index].color = color; @@ -162,6 +155,37 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { } } + private void parse_stop_colors_from_pattern() { + stop_colors = new Gee.ArrayList (); + + int stop_color_count; + gradient_pattern.get_color_stop_count(out stop_color_count); + + if(stop_color_count == 0) { + // default value when no gradient has been added + stop_colors.insert (0, new StopColor ("#000", 1, 0)); + stop_colors.insert (1, new StopColor ("#fff", 1, 100)); + + return; + } + + for(int i = 0; i < stop_color_count; ++i) { + double offset, red, green, blue, alpha; + gradient_pattern.get_color_stop_rgba(i, out offset, out red, out green, out blue, out alpha); + + Gdk.RGBA color = Gdk.RGBA(); + color.red = red; + color.green = green; + color.blue = blue; + + StopColor stop_color = new StopColor(color.to_string(), alpha, offset * 100); + + print("offsets %f\n", offset*100); + stop_colors.insert(i, stop_color); + } + + } + public void delete_selected_step () { // get the index of selected step int index = stop_colors.index_of (selected_stop_color); @@ -206,7 +230,7 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { return false; } - private void update_style () { + public void update_style () { // since gradients on direction line are not supported, dont draw direction line if (model.type == Akira.Models.ColorModel.Type.BORDER) { return; @@ -215,7 +239,7 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { string css_style = ""; string stop_color_string = stop_colors_as_string (); - if (color_mode_type == "solid") { + if (model.color_mode == "solid") { css_style = "@bg_color"; } else { css_style = """linear-gradient(to right %s)""".printf (stop_color_string); @@ -250,8 +274,7 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { return colors_string; } - private void on_color_mode_changed (string _color_mode_type) { - color_mode_type = _color_mode_type; + private void on_color_mode_changed (string color_mode) { update_style (); } @@ -263,13 +286,13 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { double x0, y0, x1, y1; direction_line.get_direction_coords (out x0, out y0, out x1, out y1); - if (color_mode_type == "solid") { + if (model.color_mode == "solid") { // for solid color, create an empty pattern. In Fills, we check if stop colors exists // for this pattern. If they dont, then the Pattern is not applied gradient_pattern = new Cairo.Pattern.linear (x0, y0, x1, y1); model.pattern = gradient_pattern; return; - } else if (color_mode_type == "linear") { + } else if (model.color_mode == "linear") { gradient_pattern = new Cairo.Pattern.linear (x0, y0, x1, y1); } else { double dx = x0 - x1; From 7a2db2fcb685df3474251910db1f2de0bd240b9e Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Sat, 17 Jul 2021 14:39:45 +0530 Subject: [PATCH 30/35] Load gradient direction for previously applied gradients --- src/Widgets/DirectionLine.vala | 23 +++++++++++++++++------ src/Widgets/GradientEditor.vala | 21 ++++++++++++++------- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/Widgets/DirectionLine.vala b/src/Widgets/DirectionLine.vala index ea1ae3878..6c0b41249 100644 --- a/src/Widgets/DirectionLine.vala +++ b/src/Widgets/DirectionLine.vala @@ -32,7 +32,7 @@ public class Akira.Widgets.DirectionLine { // dummy identity matrix private Cairo.Matrix identity_mat = Cairo.Matrix.identity (); - public DirectionLine (Window _window, GradientEditor _gradient_editor, Akira.Models.ColorModel model) { + public DirectionLine (Window _window, GradientEditor _gradient_editor, Akira.Models.ColorModel model, double[] coords) { type = model.type; // since gradients on borders are not yet supported, dont draw direction line @@ -53,11 +53,7 @@ public class Akira.Widgets.DirectionLine { end_nob.set_rectangle (); update_visibility (model.color_mode); - - // initial position of direction nobs will be outside the canvas. - // when CanvasItem gets selected, they will be placed along the diagonal - start_nob.update_state (identity_mat, -10, -10, false); - end_nob.update_state (identity_mat, -10, -10, false); + set_nob_initial_position(coords); window.event_bus.color_mode_changed.connect (update_visibility); canvas.button_press_event.connect (on_buton_press_event); @@ -83,6 +79,21 @@ public class Akira.Widgets.DirectionLine { y1 = end_nob.center_y - selected_item.coordinates.y; } + private void set_nob_initial_position(double[] coords) { + double x = 0, y = 0; + + // if this is the first time we are applying gradients to the item, + // set the nobs outside the canvas. + if(coords[0] != -10 || coords[1] != -10) { + x = selected_item.coordinates.x; + y = selected_item.coordinates.y; + } + + start_nob.update_state (identity_mat, coords[0] + x, coords[1] + y, false); + end_nob.update_state (identity_mat, coords[2] + x, coords[3] + y, false); + + } + private bool on_buton_press_event (Gdk.EventButton event) { if (type == Akira.Models.ColorModel.Type.BORDER) { return false; diff --git a/src/Widgets/GradientEditor.vala b/src/Widgets/GradientEditor.vala index f7731521e..cee1d9fe5 100644 --- a/src/Widgets/GradientEditor.vala +++ b/src/Widgets/GradientEditor.vala @@ -40,9 +40,10 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { window = _window; model = _model; - direction_line = new DirectionLine (_window, this, _model); gradient_pattern = pattern; - parse_stop_colors_from_pattern(); + double[] coords = parse_stop_colors_from_pattern(); + + direction_line = new DirectionLine (_window, this, _model, coords); set_hexpand (true); height_request = 35; @@ -56,7 +57,7 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { widget_width = get_allocated_width (); widget_height = get_allocated_height (); - draw.connect_after ( (context) => {return redraw_editor (context);}); + draw.connect_after (redraw_editor); button_press_event.connect ( (event) => {return on_button_press (event);}); button_release_event.connect ( (event) => {return on_button_release (event); }); @@ -155,8 +156,11 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { } } - private void parse_stop_colors_from_pattern() { + // this method retrieves the stop colors from gradient_pattern from model. + // returns a list of points [x0, y0, x1, y1] representing the coordinates of start and end nob + private double[] parse_stop_colors_from_pattern() { stop_colors = new Gee.ArrayList (); + double[] coords = new double[4]; int stop_color_count; gradient_pattern.get_color_stop_count(out stop_color_count); @@ -166,7 +170,8 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { stop_colors.insert (0, new StopColor ("#000", 1, 0)); stop_colors.insert (1, new StopColor ("#fff", 1, 100)); - return; + coords[0] = coords[1] = coords[2] = coords[3] = -10; + return coords; } for(int i = 0; i < stop_color_count; ++i) { @@ -180,10 +185,12 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { StopColor stop_color = new StopColor(color.to_string(), alpha, offset * 100); - print("offsets %f\n", offset*100); stop_colors.insert(i, stop_color); } + gradient_pattern.get_linear_points(out coords[0], out coords[1], out coords[2], out coords[3]); + return coords; + } public void delete_selected_step () { @@ -230,7 +237,7 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { return false; } - public void update_style () { + private void update_style () { // since gradients on direction line are not supported, dont draw direction line if (model.type == Akira.Models.ColorModel.Type.BORDER) { return; From 833835eae80ec42ed057808009c37dbc5b2ad2f3 Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Sat, 17 Jul 2021 21:36:02 +0530 Subject: [PATCH 31/35] Change color picker color when stop color changes --- src/Services/EventBus.vala | 2 ++ src/Widgets/ColorRow.vala | 11 +++++++++++ src/Widgets/GradientEditor.vala | 19 ++++++++++++++++++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/Services/EventBus.vala b/src/Services/EventBus.vala index 1cfd17737..70ff662bc 100644 --- a/src/Services/EventBus.vala +++ b/src/Services/EventBus.vala @@ -54,6 +54,8 @@ public class Akira.Services.EventBus : Object { // this signal will be triggered every time color gets modified public signal void color_changed (string color, double alpha); public signal void color_mode_changed (string color_mode); + // this signal is used to change color in ColorChooserWidget when new stop color selected + public signal void change_editor_color(Gdk.RGBA color); // Options panel signals. public signal void align_items (string align_action); diff --git a/src/Widgets/ColorRow.vala b/src/Widgets/ColorRow.vala index 2693ecf32..2026c0dfd 100644 --- a/src/Widgets/ColorRow.vala +++ b/src/Widgets/ColorRow.vala @@ -248,11 +248,22 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { window.event_bus.color_mode_changed(model.color_mode); color_chooser_widget.notify["rgba"].connect (() => { + if(color_set_manually) { + color_set_manually = false; + return; + } + + color_set_manually = true; string new_color = color_chooser_widget.rgba.to_string (); double alpha = color_chooser_widget.rgba.alpha; window.event_bus.color_changed (new_color, alpha); }); + + window.event_bus.change_editor_color.connect((color) => { + color_set_manually = true; + color_chooser_widget.rgba = color; + }); } private int sort_colors_function (Gtk.FlowBoxChild a, Gtk.FlowBoxChild b) { diff --git a/src/Widgets/GradientEditor.vala b/src/Widgets/GradientEditor.vala index cee1d9fe5..f9436b1b0 100644 --- a/src/Widgets/GradientEditor.vala +++ b/src/Widgets/GradientEditor.vala @@ -108,6 +108,13 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { var position = (event.x / widget_width) * 100; get_stop_color_at (position); + Gdk.RGBA selected_color = Gdk.RGBA(); + selected_color.parse(selected_stop_color.color); + selected_color.alpha = selected_stop_color.alpha; + window.event_bus.change_editor_color(selected_color); + + print("selected color %s\n", selected_stop_color.color); + // trigger redraw for the Editor. This renders the stop color queue_draw_area (widget_x, widget_y, widget_width, widget_height); } @@ -147,7 +154,10 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { int index = stop_colors.index_of (selected_stop_color); stop_colors[index].color = color; + selected_stop_color.color = color; + stop_colors[index].alpha = alpha; + selected_stop_color.alpha = alpha; queue_draw_area (widget_x, widget_y, widget_width, widget_height); } else { @@ -188,7 +198,14 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { stop_colors.insert(i, stop_color); } - gradient_pattern.get_linear_points(out coords[0], out coords[1], out coords[2], out coords[3]); + // TODO: there's a bug here. Cant retrieve coordinates if gradient is radial + // will fix when I update to libcairo 1.4 + if(gradient_pattern.get_type() == Cairo.PatternType.LINEAR) { + gradient_pattern.get_linear_points(out coords[0], out coords[1], out coords[2], out coords[3]); + } else { + coords[0] = coords[1] = coords[2] = coords[3] = -10; + } + return coords; } From 7a27e8684af00d9dad4794a3d66e2cb84831e1d2 Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Sat, 17 Jul 2021 22:32:17 +0530 Subject: [PATCH 32/35] Allow user to modify direction line with color chooser open --- src/Services/EventBus.vala | 1 + src/Widgets/ColorRow.vala | 8 ++++++++ src/Widgets/DirectionLine.vala | 3 +++ 3 files changed, 12 insertions(+) diff --git a/src/Services/EventBus.vala b/src/Services/EventBus.vala index 70ff662bc..774f23025 100644 --- a/src/Services/EventBus.vala +++ b/src/Services/EventBus.vala @@ -56,6 +56,7 @@ public class Akira.Services.EventBus : Object { public signal void color_mode_changed (string color_mode); // this signal is used to change color in ColorChooserWidget when new stop color selected public signal void change_editor_color(Gdk.RGBA color); + public signal void color_chooser_popdown(); // Options panel signals. public signal void align_items (string align_action); diff --git a/src/Widgets/ColorRow.vala b/src/Widgets/ColorRow.vala index 2026c0dfd..675bba8ed 100644 --- a/src/Widgets/ColorRow.vala +++ b/src/Widgets/ColorRow.vala @@ -202,6 +202,14 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { return; } + // makeing color_popover non modal allows recieving events in the window. + // this will allow user to modify direction line with the color picker open + color_popover.modal = false; + + window.event_bus.color_chooser_popdown.connect(() => { + color_popover.popdown(); + }); + color_chooser_widget = new Gtk.ColorChooserWidget (); color_chooser_widget.hexpand = true; color_chooser_widget.show_editor = true; diff --git a/src/Widgets/DirectionLine.vala b/src/Widgets/DirectionLine.vala index 6c0b41249..1a8ebb9fa 100644 --- a/src/Widgets/DirectionLine.vala +++ b/src/Widgets/DirectionLine.vala @@ -111,6 +111,9 @@ public class Akira.Widgets.DirectionLine { canvas.motion_notify_event.connect (on_motion_event); return true; + } else { + // if neighter of the buttons nobs were pressed, the user has clicked elsewhere + window.event_bus.color_chooser_popdown(); } return false; } From 241fbceb8c41485cce240c672feac1bbf5896244 Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Sun, 18 Jul 2021 13:57:27 +0530 Subject: [PATCH 33/35] Hide Gradient Editor based on color modes --- src/Widgets/ColorMode.vala | 12 ++++++++++++ src/Widgets/DirectionLine.vala | 11 +++++++++-- src/Widgets/GradientEditor.vala | 10 ++++++---- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/Widgets/ColorMode.vala b/src/Widgets/ColorMode.vala index 0a2adcf61..f350fba20 100644 --- a/src/Widgets/ColorMode.vala +++ b/src/Widgets/ColorMode.vala @@ -72,6 +72,13 @@ gradient_editor = new GradientEditor (window, model, model.pattern); + mode_button_pressed(color_mode_type); + + delete_step_button.size_allocate.connect(() => { + if(color_mode_type == "solid") { + delete_step_button.visible = false; + } + }); // since color modes on border havent been implmented yet, disable these buttons if (model.type == Akira.Models.ColorModel.Type.BORDER) { solid_color_button.sensitive = false; @@ -94,6 +101,11 @@ } private void mode_button_pressed (string _color_mode_type) { + if(_color_mode_type == "solid") { + delete_step_button.visible = false; + } else { + delete_step_button.visible = true; + } color_mode_type = _color_mode_type; model.color_mode = color_mode_type; window.event_bus.color_mode_changed (color_mode_type); diff --git a/src/Widgets/DirectionLine.vala b/src/Widgets/DirectionLine.vala index 1a8ebb9fa..7f6e6cb83 100644 --- a/src/Widgets/DirectionLine.vala +++ b/src/Widgets/DirectionLine.vala @@ -81,9 +81,8 @@ public class Akira.Widgets.DirectionLine { private void set_nob_initial_position(double[] coords) { double x = 0, y = 0; + print("%f %f %f %f\n", coords[0], coords[1], coords[2], coords[3] ); - // if this is the first time we are applying gradients to the item, - // set the nobs outside the canvas. if(coords[0] != -10 || coords[1] != -10) { x = selected_item.coordinates.x; y = selected_item.coordinates.y; @@ -140,6 +139,9 @@ public class Akira.Widgets.DirectionLine { } if (start_nob.center_x == -10 || start_nob.center_y == -10) { + print("setting initial position\n"); + selected_item = canvas.selected_bound_manager.selected_items.nth_data (0); + // if this is the first time the direction line is being displayed, // set its default position along diagonal double pos_x = selected_item.coordinates.x; @@ -148,6 +150,11 @@ public class Akira.Widgets.DirectionLine { double height = selected_item.size.height; double offset = Akira.Lib.Selection.Nob.NOB_SIZE; + // if height and width allocation was not completed, then put off setting the initial positions + if(width == 1 || height == 1) { + return; + } + start_nob.update_state (identity_mat, pos_x + offset, pos_y + offset, true); end_nob.update_state (identity_mat, pos_x + width - offset, pos_y + height - offset, true); } diff --git a/src/Widgets/GradientEditor.vala b/src/Widgets/GradientEditor.vala index f9436b1b0..c7f47f9dd 100644 --- a/src/Widgets/GradientEditor.vala +++ b/src/Widgets/GradientEditor.vala @@ -46,8 +46,6 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { direction_line = new DirectionLine (_window, this, _model, coords); set_hexpand (true); - height_request = 35; - set_events (Gdk.EventMask.BUTTON_PRESS_MASK); set_above_child (false); @@ -113,8 +111,6 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { selected_color.alpha = selected_stop_color.alpha; window.event_bus.change_editor_color(selected_color); - print("selected color %s\n", selected_stop_color.color); - // trigger redraw for the Editor. This renders the stop color queue_draw_area (widget_x, widget_y, widget_width, widget_height); } @@ -299,6 +295,12 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { } private void on_color_mode_changed (string color_mode) { + if(color_mode == "solid") { + height_request = 1; + } else { + height_request = 44; + } + update_style (); } From cd678bce0b3189b876e9f500d73f60f52a018035 Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Sun, 18 Jul 2021 14:27:12 +0530 Subject: [PATCH 34/35] Show gradient patterns on ColorButton --- src/Models/ColorModel.vala | 4 ++++ src/Widgets/ColorRow.vala | 25 +++++++++++++++++++------ src/Widgets/DirectionLine.vala | 2 -- src/Widgets/GradientEditor.vala | 11 ++++++----- 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/Models/ColorModel.vala b/src/Models/ColorModel.vala index 5b1606453..f1419e164 100644 --- a/src/Models/ColorModel.vala +++ b/src/Models/ColorModel.vala @@ -55,6 +55,8 @@ public class Akira.Models.ColorModel : GLib.Object { } } + public string fill_css { get; set; } + public string color { owned get { return type == Type.FILL ? fill.color.to_string () : border.color.to_string (); @@ -126,5 +128,7 @@ public class Akira.Models.ColorModel : GLib.Object { type = fill != null ? Type.FILL : Type.BORDER; this.fill = fill; this.border = border; + + fill_css = "@bg_color"; } } diff --git a/src/Widgets/ColorRow.vala b/src/Widgets/ColorRow.vala index 675bba8ed..8a0407fef 100644 --- a/src/Widgets/ColorRow.vala +++ b/src/Widgets/ColorRow.vala @@ -83,6 +83,12 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { color_button.clicked.connect (() => { init_color_chooser (); + + window.event_bus.color_chooser_popdown.connect(() => { + var rgba = color_chooser_widget.rgba; + set_button_color(rgba.to_string(), (int)rgba.alpha * 255, model.fill_css); + }); + color_popover.popup (); }); @@ -202,7 +208,7 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { return; } - // makeing color_popover non modal allows recieving events in the window. + // making color_popover non modal allows recieving events in the window. // this will allow user to modify direction line with the color picker open color_popover.modal = false; @@ -310,21 +316,28 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { color_chooser_widget.set_rgba (new_rgba); } - private void set_button_color (string color, int alpha) { + private void set_button_color (string color, int alpha, string gradient_css = "") { try { var provider = new Gtk.CssProvider (); var context = color_button.get_style_context (); + string background, border_color; + var new_rgba = Gdk.RGBA (); new_rgba.parse (color); new_rgba.alpha = (double) alpha / 255; - var new_color = new_rgba.to_string (); - // TODO: when in gradient mode, add css_style from gradient editor here + background = new_rgba.to_string (); + border_color = background; + + if(gradient_css != null && gradient_css.contains("gradient")) { + background = gradient_css; + } + var css = """.selected-color { - background-color: %s; + background: %s; border-color: shade (%s, 0.75); - }""".printf (new_color, new_color); + }""".printf (background, border_color); provider.load_from_data (css, css.length); diff --git a/src/Widgets/DirectionLine.vala b/src/Widgets/DirectionLine.vala index 7f6e6cb83..f1bb4d64d 100644 --- a/src/Widgets/DirectionLine.vala +++ b/src/Widgets/DirectionLine.vala @@ -81,7 +81,6 @@ public class Akira.Widgets.DirectionLine { private void set_nob_initial_position(double[] coords) { double x = 0, y = 0; - print("%f %f %f %f\n", coords[0], coords[1], coords[2], coords[3] ); if(coords[0] != -10 || coords[1] != -10) { x = selected_item.coordinates.x; @@ -139,7 +138,6 @@ public class Akira.Widgets.DirectionLine { } if (start_nob.center_x == -10 || start_nob.center_y == -10) { - print("setting initial position\n"); selected_item = canvas.selected_bound_manager.selected_items.nth_data (0); // if this is the first time the direction line is being displayed, diff --git a/src/Widgets/GradientEditor.vala b/src/Widgets/GradientEditor.vala index c7f47f9dd..b19ca6d3f 100644 --- a/src/Widgets/GradientEditor.vala +++ b/src/Widgets/GradientEditor.vala @@ -256,13 +256,13 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { return; } - string css_style = ""; + string fill_css = ""; string stop_color_string = stop_colors_as_string (); if (model.color_mode == "solid") { - css_style = "@bg_color"; + fill_css = "@bg_color"; } else { - css_style = """linear-gradient(to right %s)""".printf (stop_color_string); + fill_css = """linear-gradient(to right %s)""".printf (stop_color_string); } try { @@ -271,16 +271,17 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { var editor_css_style = """*{ background: %s - }""".printf (css_style); + }""".printf (fill_css); provider.load_from_data (editor_css_style, editor_css_style.length); context.add_provider (provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); } catch (Error e) { warning ("Style error: %s", e.message); - debug ("%s %s\n", name, css_style); + debug ("%s %s\n", name, fill_css); } + model.fill_css = fill_css; create_gradient_pattern (); } From 1835cb34b437ad3ed650454102c6b1887ea0a549 Mon Sep 17 00:00:00 2001 From: Ashish Shevale Date: Sun, 18 Jul 2021 15:07:13 +0530 Subject: [PATCH 35/35] Linting fixes --- src/Lib/Components/Fills.vala | 5 +++-- src/Models/ColorModel.vala | 6 +++--- src/Services/EventBus.vala | 4 ++-- src/Widgets/ColorMode.vala | 8 ++++---- src/Widgets/ColorRow.vala | 16 ++++++++-------- src/Widgets/DirectionLine.vala | 17 ++++++++++------- src/Widgets/GradientEditor.vala | 34 ++++++++++++++++----------------- 7 files changed, 47 insertions(+), 43 deletions(-) diff --git a/src/Lib/Components/Fills.vala b/src/Lib/Components/Fills.vala index 7f73c7b88..96d412ad4 100644 --- a/src/Lib/Components/Fills.vala +++ b/src/Lib/Components/Fills.vala @@ -97,8 +97,9 @@ public class Akira.Lib.Components.Fills : Component { if (item is Items.CanvasArtboard) { ((Items.CanvasArtboard) item).background.set ("fill-pattern", fill.gradient_pattern); } else { - item.set ("fill-pattern", fill.gradient_pattern); double x0, y0, x1, y1; - fill.gradient_pattern.get_linear_points(out x0, out y0, out x1, out y1); + item.set ("fill-pattern", fill.gradient_pattern); + double x0, y0, x1, y1; + fill.gradient_pattern.get_linear_points (out x0, out y0, out x1, out y1); } // since we dont have the functionality of blending gradients, diff --git a/src/Models/ColorModel.vala b/src/Models/ColorModel.vala index f1419e164..9b97209ea 100644 --- a/src/Models/ColorModel.vala +++ b/src/Models/ColorModel.vala @@ -38,7 +38,7 @@ public class Akira.Models.ColorModel : GLib.Object { return type == Type.FILL ? fill.color_mode : "solid"; } set { - if(type == Type.FILL) { + if (type == Type.FILL) { fill.color_mode = value; } } @@ -46,11 +46,11 @@ public class Akira.Models.ColorModel : GLib.Object { public Cairo.Pattern pattern { owned get { - return type == Type.FILL ? fill.gradient_pattern : new Cairo.Pattern.linear(0,0,0,0); + return type == Type.FILL ? fill.gradient_pattern : new Cairo.Pattern.linear (0,0,0,0); } set { if (type == Type.FILL) { - fill.set("gradient-pattern", value); + fill.set ("gradient-pattern", value); } } } diff --git a/src/Services/EventBus.vala b/src/Services/EventBus.vala index 774f23025..fbea3f29e 100644 --- a/src/Services/EventBus.vala +++ b/src/Services/EventBus.vala @@ -55,8 +55,8 @@ public class Akira.Services.EventBus : Object { public signal void color_changed (string color, double alpha); public signal void color_mode_changed (string color_mode); // this signal is used to change color in ColorChooserWidget when new stop color selected - public signal void change_editor_color(Gdk.RGBA color); - public signal void color_chooser_popdown(); + public signal void change_editor_color (Gdk.RGBA color); + public signal void color_chooser_popdown (); // Options panel signals. public signal void align_items (string align_action); diff --git a/src/Widgets/ColorMode.vala b/src/Widgets/ColorMode.vala index f350fba20..9f6bb0cba 100644 --- a/src/Widgets/ColorMode.vala +++ b/src/Widgets/ColorMode.vala @@ -72,10 +72,10 @@ gradient_editor = new GradientEditor (window, model, model.pattern); - mode_button_pressed(color_mode_type); + mode_button_pressed (color_mode_type); - delete_step_button.size_allocate.connect(() => { - if(color_mode_type == "solid") { + delete_step_button.size_allocate.connect ( () => { + if (color_mode_type == "solid") { delete_step_button.visible = false; } }); @@ -101,7 +101,7 @@ } private void mode_button_pressed (string _color_mode_type) { - if(_color_mode_type == "solid") { + if (_color_mode_type == "solid") { delete_step_button.visible = false; } else { delete_step_button.visible = true; diff --git a/src/Widgets/ColorRow.vala b/src/Widgets/ColorRow.vala index 8a0407fef..711217614 100644 --- a/src/Widgets/ColorRow.vala +++ b/src/Widgets/ColorRow.vala @@ -84,9 +84,9 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { color_button.clicked.connect (() => { init_color_chooser (); - window.event_bus.color_chooser_popdown.connect(() => { + window.event_bus.color_chooser_popdown.connect ( () => { var rgba = color_chooser_widget.rgba; - set_button_color(rgba.to_string(), (int)rgba.alpha * 255, model.fill_css); + set_button_color (rgba.to_string (), (int) rgba.alpha * 255, model.fill_css); }); color_popover.popup (); @@ -212,8 +212,8 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { // this will allow user to modify direction line with the color picker open color_popover.modal = false; - window.event_bus.color_chooser_popdown.connect(() => { - color_popover.popdown(); + window.event_bus.color_chooser_popdown.connect ( () => { + color_popover.popdown (); }); color_chooser_widget = new Gtk.ColorChooserWidget (); @@ -259,10 +259,10 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { // Set the chooser color before connecting the signal. set_chooser_color (model.color, model.alpha); - window.event_bus.color_mode_changed(model.color_mode); + window.event_bus.color_mode_changed (model.color_mode); color_chooser_widget.notify["rgba"].connect (() => { - if(color_set_manually) { + if (color_set_manually) { color_set_manually = false; return; } @@ -274,7 +274,7 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { window.event_bus.color_changed (new_color, alpha); }); - window.event_bus.change_editor_color.connect((color) => { + window.event_bus.change_editor_color.connect ( (color) => { color_set_manually = true; color_chooser_widget.rgba = color; }); @@ -330,7 +330,7 @@ public class Akira.Widgets.ColorRow : Gtk.Grid { background = new_rgba.to_string (); border_color = background; - if(gradient_css != null && gradient_css.contains("gradient")) { + if (gradient_css != null && gradient_css.contains ("gradient")) { background = gradient_css; } diff --git a/src/Widgets/DirectionLine.vala b/src/Widgets/DirectionLine.vala index f1bb4d64d..c69f88a0b 100644 --- a/src/Widgets/DirectionLine.vala +++ b/src/Widgets/DirectionLine.vala @@ -32,7 +32,10 @@ public class Akira.Widgets.DirectionLine { // dummy identity matrix private Cairo.Matrix identity_mat = Cairo.Matrix.identity (); - public DirectionLine (Window _window, GradientEditor _gradient_editor, Akira.Models.ColorModel model, double[] coords) { + public DirectionLine (Window _window, + GradientEditor _gradient_editor, + Akira.Models.ColorModel model, + double[] coords) { type = model.type; // since gradients on borders are not yet supported, dont draw direction line @@ -53,7 +56,7 @@ public class Akira.Widgets.DirectionLine { end_nob.set_rectangle (); update_visibility (model.color_mode); - set_nob_initial_position(coords); + set_nob_initial_position (coords); window.event_bus.color_mode_changed.connect (update_visibility); canvas.button_press_event.connect (on_buton_press_event); @@ -79,10 +82,10 @@ public class Akira.Widgets.DirectionLine { y1 = end_nob.center_y - selected_item.coordinates.y; } - private void set_nob_initial_position(double[] coords) { + private void set_nob_initial_position (double[] coords) { double x = 0, y = 0; - if(coords[0] != -10 || coords[1] != -10) { + if (coords[0] != -10 || coords[1] != -10) { x = selected_item.coordinates.x; y = selected_item.coordinates.y; } @@ -111,7 +114,7 @@ public class Akira.Widgets.DirectionLine { return true; } else { // if neighter of the buttons nobs were pressed, the user has clicked elsewhere - window.event_bus.color_chooser_popdown(); + window.event_bus.color_chooser_popdown (); } return false; } @@ -139,7 +142,7 @@ public class Akira.Widgets.DirectionLine { if (start_nob.center_x == -10 || start_nob.center_y == -10) { selected_item = canvas.selected_bound_manager.selected_items.nth_data (0); - + // if this is the first time the direction line is being displayed, // set its default position along diagonal double pos_x = selected_item.coordinates.x; @@ -149,7 +152,7 @@ public class Akira.Widgets.DirectionLine { double offset = Akira.Lib.Selection.Nob.NOB_SIZE; // if height and width allocation was not completed, then put off setting the initial positions - if(width == 1 || height == 1) { + if (width == 1 || height == 1) { return; } diff --git a/src/Widgets/GradientEditor.vala b/src/Widgets/GradientEditor.vala index b19ca6d3f..8e46ad6e6 100644 --- a/src/Widgets/GradientEditor.vala +++ b/src/Widgets/GradientEditor.vala @@ -41,7 +41,7 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { model = _model; gradient_pattern = pattern; - double[] coords = parse_stop_colors_from_pattern(); + double[] coords = parse_stop_colors_from_pattern (); direction_line = new DirectionLine (_window, this, _model, coords); @@ -106,10 +106,10 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { var position = (event.x / widget_width) * 100; get_stop_color_at (position); - Gdk.RGBA selected_color = Gdk.RGBA(); - selected_color.parse(selected_stop_color.color); + Gdk.RGBA selected_color = Gdk.RGBA (); + selected_color.parse (selected_stop_color.color); selected_color.alpha = selected_stop_color.alpha; - window.event_bus.change_editor_color(selected_color); + window.event_bus.change_editor_color (selected_color); // trigger redraw for the Editor. This renders the stop color queue_draw_area (widget_x, widget_y, widget_width, widget_height); @@ -151,7 +151,7 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { stop_colors[index].color = color; selected_stop_color.color = color; - + stop_colors[index].alpha = alpha; selected_stop_color.alpha = alpha; @@ -164,14 +164,14 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { // this method retrieves the stop colors from gradient_pattern from model. // returns a list of points [x0, y0, x1, y1] representing the coordinates of start and end nob - private double[] parse_stop_colors_from_pattern() { + private double[] parse_stop_colors_from_pattern () { stop_colors = new Gee.ArrayList (); double[] coords = new double[4]; int stop_color_count; - gradient_pattern.get_color_stop_count(out stop_color_count); + gradient_pattern.get_color_stop_count (out stop_color_count); - if(stop_color_count == 0) { + if (stop_color_count == 0) { // default value when no gradient has been added stop_colors.insert (0, new StopColor ("#000", 1, 0)); stop_colors.insert (1, new StopColor ("#fff", 1, 100)); @@ -180,24 +180,24 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { return coords; } - for(int i = 0; i < stop_color_count; ++i) { + for (int i = 0; i < stop_color_count; ++i) { double offset, red, green, blue, alpha; - gradient_pattern.get_color_stop_rgba(i, out offset, out red, out green, out blue, out alpha); + gradient_pattern.get_color_stop_rgba (i, out offset, out red, out green, out blue, out alpha); - Gdk.RGBA color = Gdk.RGBA(); + Gdk.RGBA color = Gdk.RGBA (); color.red = red; color.green = green; color.blue = blue; - StopColor stop_color = new StopColor(color.to_string(), alpha, offset * 100); + StopColor stop_color = new StopColor (color.to_string (), alpha, offset * 100); - stop_colors.insert(i, stop_color); + stop_colors.insert (i, stop_color); } // TODO: there's a bug here. Cant retrieve coordinates if gradient is radial - // will fix when I update to libcairo 1.4 - if(gradient_pattern.get_type() == Cairo.PatternType.LINEAR) { - gradient_pattern.get_linear_points(out coords[0], out coords[1], out coords[2], out coords[3]); + // To fix, need to upgrade libcairo to >=1.4 + if (gradient_pattern.get_type () == Cairo.PatternType.LINEAR) { + gradient_pattern.get_linear_points (out coords[0], out coords[1], out coords[2], out coords[3]); } else { coords[0] = coords[1] = coords[2] = coords[3] = -10; } @@ -296,7 +296,7 @@ public class Akira.Widgets.GradientEditor : Gtk.EventBox { } private void on_color_mode_changed (string color_mode) { - if(color_mode == "solid") { + if (color_mode == "solid") { height_request = 1; } else { height_request = 44;