diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c09fa18e..6f4a8aad 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v6 - name: Lint run: io.elementary.vala-lint -d . @@ -24,7 +24,7 @@ jobs: matrix: python-version: ["3.12"] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v3 with: diff --git a/data/com.github.subhadeepjasu.pebbles.gschema.xml.in b/data/com.github.subhadeepjasu.pebbles.gschema.xml.in index 0921e260..01422ca7 100644 --- a/data/com.github.subhadeepjasu.pebbles.gschema.xml.in +++ b/data/com.github.subhadeepjasu.pebbles.gschema.xml.in @@ -51,6 +51,11 @@ Result Flow Whether result action would replace input with result + + false + All Clear using Delete + Whether to clear all values when delete is pressed + "euler" Choose Constant 1 diff --git a/data/meson.build b/data/meson.build index 7e4e1e0d..f1c84341 100644 --- a/data/meson.build +++ b/data/meson.build @@ -45,8 +45,6 @@ foreach b : blueprint_files bfs += meson.current_source_dir () / b endforeach -run_command ('blueprint-compiler', 'batch-compile', meson.project_build_root () / 'data/ui', meson.current_source_dir () / 'ui', bfs, check: true) - blueprints = custom_target ('blueprints', input: files (blueprint_files), output: '.', diff --git a/data/style.scss b/data/style.scss index 96428717..9e3c1812 100644 --- a/data/style.scss +++ b/data/style.scss @@ -63,7 +63,7 @@ $LCD_FG_COLOR: #272863bb; 0 0 0 1px #0006, inset 0 1px 0 #fff4, inset 0 -1px 0 #fff2, - 0 12px 24px #545e5473; + 0 12px 24px #aec3ae73; color: $LCD_FG_COLOR; padding-top: 8px; diff --git a/data/ui/calculus_view.blp b/data/ui/calculus_view.blp index 6690db2c..62afa491 100644 --- a/data/ui/calculus_view.blp +++ b/data/ui/calculus_view.blp @@ -52,9 +52,9 @@ template $PebblesCalculusView: $PebblesView { $PebblesButton all_clear_button { label_text: _("AC"); tooltip_desc: _("All Clear"); - accel_markup: "BackSpace"; + accel_markup: bind template.all_clear_key; focus-on-click: false; - key: "BackSpace"; + key: bind template.all_clear_key; styles [ "destructive-action", diff --git a/data/ui/converter_view.blp b/data/ui/converter_view.blp index da07fdc4..5a302e40 100644 --- a/data/ui/converter_view.blp +++ b/data/ui/converter_view.blp @@ -109,9 +109,9 @@ template $PebblesConverterView: $PebblesView { $PebblesButton all_clear_button { label_text: _("AC"); tooltip_desc: _("All Clear"); - accel_markup: "BackSpace"; + accel_markup: bind template.all_clear_key; focus-on-click: false; - key: "BackSpace"; + key: bind template.all_clear_key; styles [ "destructive-action", diff --git a/data/ui/graphing_view.blp b/data/ui/graphing_view.blp index a59d50bc..2ce0d95f 100644 --- a/data/ui/graphing_view.blp +++ b/data/ui/graphing_view.blp @@ -49,9 +49,9 @@ template $PebblesGraphingView: $PebblesView { $PebblesButton all_clear_button { label_text: _("AC"); tooltip_desc: _("All Clear"); - accel_markup: "Delete"; + accel_markup: bind template.all_clear_key; focus-on-click: false; - key: "delete"; + key: bind template.all_clear_key; styles [ "destructive-action", diff --git a/data/ui/preferences_dialog.blp b/data/ui/preferences_dialog.blp index f0160552..6cc3ea45 100644 --- a/data/ui/preferences_dialog.blp +++ b/data/ui/preferences_dialog.blp @@ -18,6 +18,15 @@ template $PebblesPreferencesDialog: Adw.PreferencesDialog { notify::active => $load_session_notify_active_cb(); } + Adw.SwitchRow { + title: _("All Clear On [Delete] Key"); + subtitle: _("Clear all values when delete is pressed"); + focus-on-click: false; + focusable: false; + active: bind template.settings as <$PebblesSettings>.delete_all_clear; + notify::active => $delete_all_clear_notify_active_cb(); + } + Adw.ActionRow decimal_places { title: _("Decimal Places"); subtitle: _("Number of decimal places after radix symbol"); diff --git a/data/ui/programmer_view.blp b/data/ui/programmer_view.blp index 157194b6..2db31b5b 100644 --- a/data/ui/programmer_view.blp +++ b/data/ui/programmer_view.blp @@ -57,9 +57,9 @@ template $PebblesProgrammerView: $PebblesView { $PebblesButton all_clear_button { label_text: _("AC"); tooltip_desc: _("All Clear"); - accel_markup: "BackSpace"; + accel_markup: bind template.all_clear_key; focus-on-click: false; - key: "BackSpace"; + key: bind template.all_clear_key; styles [ "destructive-action", diff --git a/data/ui/scientific_view.blp b/data/ui/scientific_view.blp index bc5c1ad1..3ccca6a6 100644 --- a/data/ui/scientific_view.blp +++ b/data/ui/scientific_view.blp @@ -52,9 +52,9 @@ template $PebblesScientificView: $PebblesView { $PebblesButton all_clear_button { label_text: _("AC"); tooltip_desc: _("All Clear"); - accel_markup: "BackSpace"; + accel_markup: bind template.all_clear_key; focus-on-click: false; - key: "BackSpace"; + key: bind template.all_clear_key; styles [ "destructive-action", diff --git a/data/ui/statistics_view.blp b/data/ui/statistics_view.blp index b7e63141..9b1c18fe 100644 --- a/data/ui/statistics_view.blp +++ b/data/ui/statistics_view.blp @@ -52,9 +52,9 @@ template $PebblesStatisticsView: $PebblesView { $PebblesButton all_clear_button { label_text: _("AC"); tooltip_desc: _("All Clear"); - accel_markup: "BackSpace"; + accel_markup: bind template.all_clear_key; focus-on-click: false; - key: "BackSpace"; + key: bind template.all_clear_key; styles [ "destructive-action", diff --git a/src/Settings.vala b/src/Settings.vala index 40ab34c6..536131d7 100644 --- a/src/Settings.vala +++ b/src/Settings.vala @@ -17,6 +17,7 @@ namespace Pebbles { public const string KEY_VERSION = "version"; public const string KEY_LOAD_LAST_SESSION = "load-last-session"; public const string KEY_RESULT_FLOW = "result-flow"; + public const string KEY_DELETE_ALL_CLEAR = "delete-all-clear"; public const string KEY_THEME = "theme"; public const string KEY_CONSTANT_KEY_VALUE1 = "constant-key-value1"; public const string KEY_CONSTANT_KEY_VALUE2 = "constant-key-value2"; @@ -125,6 +126,11 @@ namespace Pebbles { set { set_boolean (KEY_RESULT_FLOW, value); } } + public bool delete_all_clear { + get { return get_boolean (KEY_DELETE_ALL_CLEAR); } + set { set_boolean (KEY_DELETE_ALL_CLEAR, value); } + } + public string theme { owned get { return get_string (KEY_THEME); } set { set_string (KEY_THEME, value); } diff --git a/src/core/graphing_calculator.py b/src/core/graphing_calculator.py index 9054ff43..299575b3 100644 --- a/src/core/graphing_calculator.py +++ b/src/core/graphing_calculator.py @@ -68,7 +68,8 @@ def set_plot_params_and_plot(self, payload): 'yMax': payload.get_y_max(), 'xScaling': payload.get_x_scaling(), 'yScaling': payload.get_y_scaling(), - 'darkMode': payload.get_dark_mode() + 'darkMode': payload.get_dark_mode(), + 'fidelity': payload.get_fidelity_mode() } self.start_plotting() @@ -99,64 +100,74 @@ def start_plotting(self): def _plot(self, path=''): try: with self.plot_lock: - steps = [6, 5, 4, 3, 1] + fidelity_mode = self.plot_params['fidelity'] + step_size = 1 if fidelity_mode or path != '' else 6 palette = Pebbles.get_palette(self.plot_params['darkMode']) dpi = self.plot_params['dpi'] width = self.plot_params['width'] height = self.plot_params['height'] plt.tight_layout(pad=4 / dpi) - for step_size in steps: - if self.cancel_event.is_set(): - return - - fig, ax = self._setup_plot(width, height, dpi, step_size) - x_values = self._generate_plot_x_values( - self.plot_params['xScaling'], - width, - step_size - ) - - if self.plot_params['yScaling'] == 1: - x_values = x_values[x_values != 0] - - t_values = np.linspace( - 0, 2*np.pi, width // (step_size ** 2) - ) - for pro in self.calculators: - pro['calc'].set_substitute_value('A', - self.plot_params['a'], zero_limit=True) - pro['calc'].set_substitute_value('B', - self.plot_params['b'], zero_limit=True) - pro['calc'].set_substitute_value('C', - self.plot_params['c'], zero_limit=True) - pro['calc'].set_substitute_value('M', - self.plot_params['m'], zero_limit=True) - if pro['eq'].get_radial_coord_mode(): - self._plot_radial(ax, pro, palette, (t_values, step_size)) - else: - self._plot_cartesian( - ax, pro, palette, - ( - x_values, - step_size, - self.plot_params['xScaling'], - self.plot_params['yScaling'] - ) + if self.cancel_event.is_set(): + return + + fig, ax = self._setup_plot(width, height, dpi, step_size) + x_values = self._generate_plot_x_values( + self.plot_params['xScaling'], + width, + step_size + ) + + if self.plot_params['yScaling'] == 1: + x_values = x_values[x_values != 0] + + t_values = np.linspace( + 0, 2 * np.pi, width // (step_size ** 2) + ) + for pro in self.calculators: + pro['calc'].set_substitute_value('A', + self.plot_params['a'], zero_limit=True) + pro['calc'].set_substitute_value('B', + self.plot_params['b'], zero_limit=True) + pro['calc'].set_substitute_value('C', + self.plot_params['c'], zero_limit=True) + pro['calc'].set_substitute_value('M', + self.plot_params['m'], zero_limit=True) + if pro['eq'].get_radial_coord_mode(): + self._plot_radial(ax, pro, palette, (t_values, step_size)) + else: + self._plot_cartesian( + ax, pro, palette, + ( + x_values, + step_size, + self.plot_params['xScaling'], + self.plot_params['yScaling'] ) + ) - if step_size == 1: + if path == '': + if fidelity_mode: self._draw_legend(ax) self._configure_labels(ax) - - if path != '': - Utils.fig_save_path = path - Utils.plot_to_image(plt, fig, (width, height), dpi, step_size) + pixbuf_f = Utils.plot_to_pixbuf(plt, fig, (width, height), dpi, step_size) + ax.set_xticklabels([]) + ax.set_yticklabels([]) + ax.get_legend().remove() + pixbuf_i = Utils.plot_to_pixbuf(plt, fig, (width, height), dpi, step_size) + if self.on_plot_ready: + self.on_plot_ready(pixbuf_i, pixbuf_f, True) else: - pixbuf = Utils.plot_to_pixbuf(plt, fig, (width, height), dpi, step_size) - + ax.set_xticklabels([]) + ax.set_yticklabels([]) + pixbuf_f = Utils.plot_to_pixbuf(plt, fig, (width, height), dpi, step_size) if self.on_plot_ready: - self.on_plot_ready(pixbuf, True) + self.on_plot_ready(None, pixbuf_f, True) + else: + self._draw_legend(ax) + self._configure_labels(ax) + Utils.fig_save_path = path + Utils.plot_to_image(plt, fig, (width, height), dpi, step_size) except RuntimeError: pass diff --git a/src/models/GraphPayload.Model.vala b/src/models/GraphPayload.Model.vala index 04e7eb11..1e66face 100644 --- a/src/models/GraphPayload.Model.vala +++ b/src/models/GraphPayload.Model.vala @@ -19,9 +19,10 @@ namespace Pebbles { public int height { get; set; } public double dpi { get; set; } public bool dark_mode { get; set; } + public bool fidelity_mode { get; set; } public bool contains_equations () { - return equations != null; + return equations != null && equations.length > 0; } } } diff --git a/src/shell/MainWindow.vala b/src/shell/MainWindow.vala index 3de1a258..24fbd28d 100644 --- a/src/shell/MainWindow.vala +++ b/src/shell/MainWindow.vala @@ -601,7 +601,9 @@ namespace Pebbles { set_shift_on (!lock_on); } - if (keyval == Gdk.Key.BackSpace && (modifier & Gdk.ModifierType.SHIFT_MASK) != 0) { + if (settings.delete_all_clear && keyval == Gdk.Key.Delete) { + on_all_clear (view_stack.visible_child_name); + } else if (keyval == Gdk.Key.BackSpace && (modifier & Gdk.ModifierType.SHIFT_MASK) != 0) { on_all_clear (view_stack.visible_child_name); } @@ -717,13 +719,6 @@ namespace Pebbles { } private void load_settings () { - // Check if the version is new - if (settings.version != Config.VERSION) { - settings.version = Config.VERSION; - - // Show some kind of What's New dialog? - } - if (settings.load_last_session) { switch (settings.global_angle_unit) { case DEG: @@ -902,8 +897,8 @@ namespace Pebbles { statistics_view.plot (figure, valid); } - protected void on_render_ready (Gdk.Pixbuf? figure, bool valid) { - graphing_view.render_graph (figure, valid); + protected void on_render_ready (Gdk.Pixbuf? figure_i, Gdk.Pixbuf? figure_f, bool valid) { + graphing_view.render_graph (figure_i, figure_f, valid); } protected void on_memory_change (string context, bool present) { diff --git a/src/shell/dialogs/PreferencesDialog.vala b/src/shell/dialogs/PreferencesDialog.vala index 3d647f80..48e48d76 100644 --- a/src/shell/dialogs/PreferencesDialog.vala +++ b/src/shell/dialogs/PreferencesDialog.vala @@ -57,6 +57,11 @@ namespace Pebbles { settings.load_last_session = (obj as Adw.SwitchRow)?.active; } + [GtkCallback] + protected void delete_all_clear_notify_active_cb (Object obj, ParamSpec params) { + settings.delete_all_clear = (obj as Adw.SwitchRow)?.active; + } + [GtkCallback] protected void result_flow_notify_active_cb (Object obj, ParamSpec params) { settings.result_flow = (obj as Adw.SwitchRow)?.active; diff --git a/src/shell/dialogs/ShortcutsDialog.vala b/src/shell/dialogs/ShortcutsDialog.vala index f56de8b6..19be06b2 100644 --- a/src/shell/dialogs/ShortcutsDialog.vala +++ b/src/shell/dialogs/ShortcutsDialog.vala @@ -22,43 +22,43 @@ namespace Pebbles { uint8 i = 0; for (; i < control_scheme.common.length[0]; i++) { common_box.append (new Granite.AccelLabel ( - control_scheme.common[i, 0], - control_scheme.common[i, 1] + control_scheme.common[i, 1], + control_scheme.common[i, 2] )); } for (i = 0; i < control_scheme.scientific.length[0]; i++) { scientific_box.append (new Granite.AccelLabel ( - control_scheme.scientific[i, 0], - control_scheme.scientific[i, 1] + control_scheme.scientific[i, 1], + control_scheme.scientific[i, 2] )); } for (i = 0; i < control_scheme.statistics.length[0]; i++) { statistics_box.append (new Granite.AccelLabel ( - control_scheme.statistics[i, 0], - control_scheme.statistics[i, 1] + control_scheme.statistics[i, 1], + control_scheme.statistics[i, 2] )); } for (i = 0; i < control_scheme.calculus.length[0]; i++) { calculus_box.append (new Granite.AccelLabel ( - control_scheme.calculus[i, 0], - control_scheme.calculus[i, 1] + control_scheme.calculus[i, 1], + control_scheme.calculus[i, 2] )); } for (i = 0; i < control_scheme.programmer.length[0]; i++) { programmer_box.append (new Granite.AccelLabel ( - control_scheme.programmer[i, 0], - control_scheme.programmer[i, 1] + control_scheme.programmer[i, 1], + control_scheme.programmer[i, 2] )); } for (i = 0; i < control_scheme.converter.length[0]; i++) { converter_box.append (new Granite.AccelLabel ( - control_scheme.converter[i, 0], - control_scheme.converter[i, 1] + control_scheme.converter[i, 1], + control_scheme.converter[i, 2] )); } } diff --git a/src/shell/main_window.py b/src/shell/main_window.py index 0d3aa89a..081c3009 100644 --- a/src/shell/main_window.py +++ b/src/shell/main_window.py @@ -236,8 +236,8 @@ def _on_graph_export(self, _, path): self.graph_calc.export(path) - def _graph_ready_cb(self, pixbuf, valid): - self.on_render_ready(pixbuf, valid) + def _graph_ready_cb(self, pixbuf_i, pixbuf_f, valid): + self.on_render_ready(pixbuf_i, pixbuf_f, valid) def _memory_recall(self, _, context: str): diff --git a/src/shell/views/CalculusView.vala b/src/shell/views/CalculusView.vala index 0b32adea..8449e3b9 100644 --- a/src/shell/views/CalculusView.vala +++ b/src/shell/views/CalculusView.vala @@ -68,6 +68,7 @@ namespace Pebbles { protected string constant_label { get; private set; default = "C"; } protected string constant_desc { get; private set; default = ""; } + protected string all_clear_key { get; private set; default = "BackSpace" ; } private Settings settings; @@ -92,14 +93,14 @@ namespace Pebbles { ); }); + load_buttons (); if (settings.load_last_session) { integral_mode = settings.calculus_mode; } - load_constant_button (); Settings.get_default ().changed.connect ((key) => { - if (key == "constant-key-value1" || key == "constant-key-value2") { - load_constant_button (); + if (key == "constant-key-value1" || key == "constant-key-value2" || key == "delete-all-clear") { + load_buttons (); } }); } @@ -220,7 +221,7 @@ namespace Pebbles { sinh_button.tooltip_desc = shift_button.active ? _("Inverse Hyperbolic Sine") : _("Hyperbolic Sine"); cosh_button.label_text = shift_button.active ? "cosh-1" : "cosh"; cosh_button.tooltip_desc = shift_button.active ? _("Inverse Hyperbolic Cosine") : _("Hyperbolic Cosine"); - tanh_button.label_text = shift_button.active ? "tanh-1" : "tan"; + tanh_button.label_text = shift_button.active ? "tanh-1" : "tanh"; tanh_button.tooltip_desc = shift_button.active ? _("Inverse Hyperbolic Tangent") : _("Hyperbolic Tangent"); log_mod_button.label_text = shift_button.active ? "logxy" : "mod"; log_mod_button.tooltip_desc = shift_button.active ? _("Log Base x") : _("Modulus"); @@ -248,10 +249,10 @@ namespace Pebbles { last_answer_button_p.tooltip_desc = shift_button.active ? _("Insert shared last answer") : _("Insert last answer"); - load_constant_button (); + load_buttons (); } - private void load_constant_button () { + private void load_buttons () { var key = shift_button.active ? settings.constant_key_value2 : settings.constant_key_value1; switch (key) { case ARCHIMEDES: @@ -295,6 +296,8 @@ namespace Pebbles { constant_desc = _("Euler's constant (exponential)"); break; } + + all_clear_key = settings.delete_all_clear ? "Delete" : "BackSpace"; } public void send_shift_modifier (bool shifted) { diff --git a/src/shell/views/GraphingView.vala b/src/shell/views/GraphingView.vala index 56d60da7..82140f03 100644 --- a/src/shell/views/GraphingView.vala +++ b/src/shell/views/GraphingView.vala @@ -57,6 +57,8 @@ namespace Pebbles { protected string constant_label { get; private set; default = "C"; } protected string constant_desc { get; private set; default = ""; } + protected string all_clear_key { get; private set; default= "BackSpace" ; } + protected Gtk.Adjustment var_a_adjustment { get; set; } protected Gtk.Adjustment var_b_adjustment { get; set; } protected Gtk.Adjustment var_c_adjustment { get; set; } @@ -69,10 +71,10 @@ namespace Pebbles { public signal string on_memory_recall (); construct { - load_constant_button (); + load_buttons (); Settings.get_default ().changed.connect ((key) => { - if (key == "constant-key-value1" || key == "constant-key-value2") { - load_constant_button (); + if (key == "constant-key-value1" || key == "constant-key-value2" || key == "delete-all-clear") { + load_buttons (); } }); @@ -82,8 +84,8 @@ namespace Pebbles { var_m_adjustment = new Gtk.Adjustment (0, -double.MAX, double.MAX, 0.01, 0.1, 0); } - public void render_graph (Gdk.Pixbuf? pixbuf, bool valid) { - viewport.show_graph (pixbuf, valid); + public void render_graph (Gdk.Pixbuf? pixbuf_i, Gdk.Pixbuf? pixbuf_f, bool valid) { + viewport.show_graph (pixbuf_i, pixbuf_f, valid); } public void send_shift_modifier (bool shifted) { @@ -193,7 +195,7 @@ namespace Pebbles { sinh_button.tooltip_desc = shift_button.active ? _("Inverse Hyperbolic Sine") : _("Hyperbolic Sine"); cosh_button.label_text = shift_button.active ? "cosh-1" : "cosh"; cosh_button.tooltip_desc = shift_button.active ? _("Inverse Hyperbolic Cosine") : _("Hyperbolic Cosine"); - tanh_button.label_text = shift_button.active ? "tanh-1" : "tan"; + tanh_button.label_text = shift_button.active ? "tanh-1" : "tanh"; tanh_button.tooltip_desc = shift_button.active ? _("Inverse Hyperbolic Tangent") : _("Hyperbolic Tangent"); log_mod_button.label_text = shift_button.active ? "logxy" : "mod"; log_mod_button.tooltip_desc = shift_button.active ? _("Log Base x") : _("Modulus"); @@ -204,7 +206,7 @@ namespace Pebbles { var_m_button.label_text = shift_button.active ? "c" : "m"; var_m_button.tooltip_desc = shift_button.active ? _("Variable c") : _("Variable m"); - load_constant_button (); + load_buttons (); } private void save_equations () { @@ -218,7 +220,7 @@ namespace Pebbles { settings.last_input_graphing = eq_strings; } - private void load_constant_button () { + private void load_buttons () { var settings = Pebbles.Settings.get_default (); var key = shift_button.active ? settings.constant_key_value2 : settings.constant_key_value1; @@ -264,6 +266,8 @@ namespace Pebbles { constant_desc = _("Euler's constant (exponential)"); break; } + + all_clear_key = settings.delete_all_clear ? "Delete" : "BackSpace"; } public void set_global_memory_present (bool present) { diff --git a/src/shell/views/ProgrammerView.vala b/src/shell/views/ProgrammerView.vala index 2be54251..a7882f40 100644 --- a/src/shell/views/ProgrammerView.vala +++ b/src/shell/views/ProgrammerView.vala @@ -96,6 +96,8 @@ namespace Pebbles { [GtkChild] private unowned Button last_answer_button; + protected string all_clear_key { get; private set; default = "BackSpace" ; } + private Pebbles.Settings settings; public signal void on_evaluate ( @@ -116,6 +118,11 @@ namespace Pebbles { set_number_system (settings.number_system); }); + settings.changed["delete-all-clear"].connect ((key) => { + all_clear_key = settings.delete_all_clear ? "Delete" : "BackSpace"; + }); + all_clear_key = settings.delete_all_clear ? "Delete" : "BackSpace"; + display.on_input.connect ((text) => { on_evaluate ( text, @@ -124,6 +131,14 @@ namespace Pebbles { 0 ); }); + + settings.changed.connect ((key) => { + if (key == "delete-all-clear") { + all_clear_key = settings.get_boolean ("delete-all-clear") ? "Delete" : "BackSpace"; + } + }); + + all_clear_key = settings.get_boolean ("delete-all-clear") ? "Delete" : "BackSpace"; } public void show_result (string result) { diff --git a/src/shell/views/ScientificView.vala b/src/shell/views/ScientificView.vala index a34b6525..711fc124 100644 --- a/src/shell/views/ScientificView.vala +++ b/src/shell/views/ScientificView.vala @@ -58,6 +58,7 @@ namespace Pebbles { protected string constant_label { get; private set; default = "C"; } protected string constant_desc { get; private set; default = ""; } + protected string all_clear_key { get; private set; default = "BackSpace" ; } [GtkChild] private unowned Adw.NavigationSplitView sci_nav_split_view; @@ -68,10 +69,10 @@ namespace Pebbles { construct { display.on_input.connect (evaluate); - load_constant_button (); + load_buttons (); Settings.get_default ().changed.connect ((key) => { - if (key == "constant-key-value1" || key == "constant-key-value2") { - load_constant_button (); + if (key == "constant-key-value1" || key == "constant-key-value2" || key == "delete-all-clear") { + load_buttons (); } }); } @@ -104,7 +105,7 @@ namespace Pebbles { sinh_button.tooltip_desc = shift_button.active ? _("Inverse Hyperbolic Sine") : _("Hyperbolic Sine"); cosh_button.label_text = shift_button.active ? "cosh-1" : "cosh"; cosh_button.tooltip_desc = shift_button.active ? _("Inverse Hyperbolic Cosine") : _("Hyperbolic Cosine"); - tanh_button.label_text = shift_button.active ? "tanh-1" : "tan"; + tanh_button.label_text = shift_button.active ? "tanh-1" : "tanh"; tanh_button.tooltip_desc = shift_button.active ? _("Inverse Hyperbolic Tangent") : _("Hyperbolic Tangent"); log_mod_button.label_text = shift_button.active ? "logxy" : "mod"; log_mod_button.tooltip_desc = shift_button.active ? _("Log Base x") : _("Modulus"); @@ -132,7 +133,7 @@ namespace Pebbles { last_answer_button_p.tooltip_desc = shift_button.active ? _("Insert shared last answer") : _("Insert last answer"); - load_constant_button (); + load_buttons (); } public void evaluate (string text) { @@ -164,7 +165,7 @@ namespace Pebbles { display.show_history (history); } - private void load_constant_button () { + private void load_buttons () { var settings = Pebbles.Settings.get_default (); var key = shift_button.active ? settings.constant_key_value2 : settings.constant_key_value1; @@ -210,6 +211,8 @@ namespace Pebbles { constant_desc = _("Euler's constant (exponential)"); break; } + + all_clear_key = settings.delete_all_clear ? "Delete" : "BackSpace"; } [GtkCallback] diff --git a/src/shell/views/StatisticsView.vala b/src/shell/views/StatisticsView.vala index 71fff42c..de1bbfc0 100644 --- a/src/shell/views/StatisticsView.vala +++ b/src/shell/views/StatisticsView.vala @@ -31,6 +31,8 @@ namespace Pebbles { protected List> table; + protected string all_clear_key { get; private set; default = "BackSpace" ; } + public signal void on_evaluate (StatOp op, Json.Object options); public signal string on_memory_recall (bool global); public signal void on_memory_clear (bool global); @@ -46,6 +48,16 @@ namespace Pebbles { } }); }); + + Settings.get_default ().changed.connect ((key) => { + if (key == "delete-all-clear") { + all_clear_key = Settings.get_default ().get_boolean ("delete-all-clear") + ? "Delete" + : "BackSpace"; + } + }); + + all_clear_key = Settings.get_default ().get_boolean ("delete-all-clear") ? "Delete" : "BackSpace"; } public void show_result (string res) { diff --git a/src/shell/views/converters/ConverterView.vala b/src/shell/views/converters/ConverterView.vala index 71a7a444..21d933da 100644 --- a/src/shell/views/converters/ConverterView.vala +++ b/src/shell/views/converters/ConverterView.vala @@ -38,6 +38,8 @@ namespace Pebbles { [GtkChild] protected unowned Gtk.Label additional_label; + protected string all_clear_key { get; private set; default = "BackSpace" ; } + private Gtk.EventControllerFocus from_entry_focus_controller; private Gtk.EventControllerFocus to_entry_focus_controller; private Gtk.EventControllerKey key_controller; @@ -121,6 +123,14 @@ namespace Pebbles { entry_formatter_from = new EntryFormatter (from_entry, NONE); entry_formatter_to = new EntryFormatter (to_entry, NONE); + + settings.changed.connect ((key) => { + if (key == "delete-all-clear") { + all_clear_key = settings.get_boolean ("delete-all-clear") ? "Delete" : "BackSpace"; + } + }); + + all_clear_key = settings.get_boolean ("delete-all-clear") ? "Delete" : "BackSpace"; } [GtkCallback] diff --git a/src/shell/widgets/GraphViewport.vala b/src/shell/widgets/GraphViewport.vala index d0b35285..9ae217b0 100644 --- a/src/shell/widgets/GraphViewport.vala +++ b/src/shell/widgets/GraphViewport.vala @@ -101,7 +101,28 @@ namespace Pebbles { } } + private bool _dragging = false; + private bool dragging { + get { + return _dragging; + } + + set { + _dragging = value; + queue_render = true; + } + } + + private bool scrolling = false; + private Gdk.Pixbuf? figure; + private Gdk.Pixbuf? intermediate_figure; + private double last_pixbuf_zoom_x = 100.0; + private double last_pixbuf_zoom_y = 100.0; + private double last_pixbuf_pan_x = 0.0; + private double last_pixbuf_pan_y = 0.0; + private int last_pixbuf_width = 0; + private int last_pixbuf_height = 0; private bool valid_figure = true; private GlobalAngleUnit angle_unit; private bool queue_render = false; @@ -164,6 +185,11 @@ namespace Pebbles { propagation_phase = Gtk.PropagationPhase.CAPTURE, name = "drag-rotation-capture" }; + + pan_gesture.begin.connect (() => { + dragging = true; + }); + pan_gesture.drag_update.connect ((off_x, off_y) => { var vel_x = off_x - previous_x; previous_x = off_x; @@ -173,9 +199,11 @@ namespace Pebbles { previous_y = off_y; pan_y += vel_y / zoom_y; }); + pan_gesture.drag_end.connect (() => { previous_x = 0; previous_y = 0; + dragging = false; }); add_controller (pan_gesture); @@ -186,10 +214,15 @@ namespace Pebbles { zoom_gesture.begin.connect (() => { previous_sx = zoom_x; previous_sy = zoom_y; + dragging = true; }); zoom_gesture.scale_changed.connect ((off_s) => { zoom_x = previous_sx * off_s; zoom_y = previous_sy * off_s; + dragging = true; + }); + zoom_gesture.end.connect (() => { + dragging = false; }); add_controller (zoom_gesture); @@ -197,6 +230,8 @@ namespace Pebbles { propagation_phase = Gtk.PropagationPhase.CAPTURE }; main_scroll_gesture.scroll.connect ((dx, dy) => { + dragging = true; + scrolling = true; var modifier = main_scroll_gesture.get_current_event_state (); if ((modifier & Gdk.ModifierType.CONTROL_MASK) != 0) { var new_zoom_x = zoom_x - dy; @@ -211,6 +246,10 @@ namespace Pebbles { pan_y -= dy / dpi; } }); + main_scroll_gesture.scroll_end.connect (() => { + dragging = false; + scrolling = false; + }); add_controller (main_scroll_gesture); x_scroll_gesture = new Gtk.EventControllerScroll (Gtk.EventControllerScrollFlags.BOTH_AXES); @@ -222,8 +261,6 @@ namespace Pebbles { if (new_zoom_x > 0) { zoom_x = new_zoom_x; } - - }); y_scroll_gesture.scroll.connect ((dx, dy) => { @@ -270,14 +307,24 @@ namespace Pebbles { width = renderer.get_width (), height = renderer.get_height (), dpi = dpi, - dark_mode = gtk_settings.gtk_application_prefer_dark_theme + dark_mode = gtk_settings.gtk_application_prefer_dark_theme, + fidelity_mode = !dragging }; window.on_render_graph (payload); } - public void show_graph (Gdk.Pixbuf? figure, bool valid) { - this.figure = figure; + public void show_graph (Gdk.Pixbuf? figure_i, Gdk.Pixbuf? figure_f, bool valid) { + this.figure = figure_f; + if (figure_i != null) { + this.intermediate_figure = figure_i; + this.last_pixbuf_pan_x = pan_x; + this.last_pixbuf_pan_y = pan_y; + this.last_pixbuf_zoom_x = zoom_x; + this.last_pixbuf_zoom_y = zoom_y; + this.last_pixbuf_width = figure_i.get_width (); + this.last_pixbuf_height = figure_i.get_height (); + } valid_figure = valid; Idle.add_once (() => { renderer.queue_draw (); @@ -287,7 +334,108 @@ namespace Pebbles { } private void draw_figure (Gtk.DrawingArea area, Cairo.Context cr, int width, int height) { - if (figure != null) { + if ((dragging || scrolling) && intermediate_figure != null && figure != null) { // Intermediate Image + double degrees = Math.PI / 180.0; + double radius = 3.0; + cr.new_sub_path (); + cr.arc (width - radius, radius, radius, -90 * degrees, 0); + cr.arc (width - radius, height - radius, radius, 0, 90 * degrees); + cr.arc (radius, height - radius, radius, 90 * degrees, 180 * degrees); + cr.arc (radius, radius, radius, 180 * degrees, 270 * degrees); + cr.close_path (); + + cr.clip (); + + + int width_f = figure?.get_width (); + int height_f = figure?.get_height (); + int width_i = intermediate_figure?.get_width (); + int height_i = intermediate_figure?.get_height (); + if (width_f > 0 && height_f > 0) { + double scale_x = (double) width / width_f; + double scale_y = (double) height / height_f; + + cr.save (); + cr.set_operator (Cairo.Operator.SOURCE); + cr.scale (scale_x, scale_y); + Gdk.cairo_set_source_pixbuf ( + cr, + figure, + 0, + 0 + ); + cr.paint (); + cr.restore (); + + if (width_i > 0) { + if (last_pixbuf_zoom_x > 0 && last_pixbuf_zoom_y > 0 && + last_pixbuf_width > 0 && last_pixbuf_height > 0) { + double s_x = zoom_x / last_pixbuf_zoom_x; + double s_y = zoom_y / last_pixbuf_zoom_y; + + double img_w = (double) last_pixbuf_width * s_x; + double img_h = (double) last_pixbuf_height * s_y; + + double tx = (double) width / 2.0 + zoom_x * (last_pixbuf_pan_x - pan_x) - img_w / 2.0; + double ty = (double) height / 2.0 - zoom_y * (last_pixbuf_pan_y - pan_y) - img_h / 2.0; + + cr.save (); + if (gtk_settings.gtk_application_prefer_dark_theme) { + cr.set_source_rgb (0.227, 0.227, 0.227); + } else { + cr.set_source_rgb (1.0, 1.0, 1.0); + } + cr.rectangle (tx, ty, img_w, img_h); + cr.fill (); + cr.restore (); + + cr.save (); + cr.rectangle (tx, ty, img_w, img_h); + cr.clip (); + cr.translate (tx, ty); + cr.scale (s_x, s_y); + Gdk.cairo_set_source_pixbuf ( + cr, + intermediate_figure, + 0, + 0 + ); + cr.paint (); + cr.restore (); + } else { + double scale_xi = (double) width / width_i; + double scale_yi = (double) height / height_i; + + double img_w = width; + double img_h = height; + double tx = 0.0; + double ty = 0.0; + + cr.save (); + if (gtk_settings.gtk_application_prefer_dark_theme) { + cr.set_source_rgb (0.227, 0.227, 0.227); + } else { + cr.set_source_rgb (1.0, 1.0, 1.0); + } + cr.rectangle (tx, ty, img_w, img_h); + cr.fill (); + cr.restore (); + + cr.save (); + cr.set_operator (Cairo.Operator.OVER); + cr.scale (scale_xi, scale_yi); + Gdk.cairo_set_source_pixbuf ( + cr, + intermediate_figure, + 0, + 0 + ); + cr.paint (); + cr.restore (); + } + } + } + } else if (figure != null) { double degrees = Math.PI / 180.0; double radius = 3.0; cr.new_sub_path (); @@ -301,11 +449,14 @@ namespace Pebbles { int iwidth = figure?.get_width (); - if (iwidth > 0) { + int iheight = figure?.get_height (); + if (iwidth > 0 && iheight > 0) { double scale_x = (double) width / iwidth; + double scale_y = (double) height / iheight; + cr.save (); cr.set_operator (Cairo.Operator.SOURCE); - cr.scale (scale_x, scale_x); + cr.scale (scale_x, scale_y); Gdk.cairo_set_source_pixbuf ( cr, figure, @@ -313,6 +464,7 @@ namespace Pebbles { 0 ); cr.paint (); + cr.restore (); } } else if (!valid_figure) { // Draw a "No Symbol" (🛇) @@ -331,6 +483,12 @@ namespace Pebbles { cr.line_to (cx + radius * 0.7, cy + radius * 0.7); cr.stroke (); } + + if (scrolling) { + dragging = false; + scrolling = false; + renderer.queue_draw (); + } } private void draw_x_scale (Gtk.DrawingArea area, Cairo.Context cr, int width, int height) { @@ -444,8 +602,10 @@ namespace Pebbles { double y_center = (height - extents.width) / 2 - extents.x_bearing; double x_offset = width - extents.height - major_tick - 4; - cr.move_to (x_offset, y_center); + cr.save (); + cr.translate (x_offset, y_center); cr.rotate (Math.PI_2); + cr.move_to (0, 0); cr.show_text (label); cr.restore (); } diff --git a/src/shell/widgets/displays/ScientificDisplay.vala b/src/shell/widgets/displays/ScientificDisplay.vala index 8325c0e6..9ba0cf24 100644 --- a/src/shell/widgets/displays/ScientificDisplay.vala +++ b/src/shell/widgets/displays/ScientificDisplay.vala @@ -39,22 +39,33 @@ namespace Pebbles { construct { Idle.add (()=> { - Timeout.add (60, ()=> { - if (animation_frame < animation_frames.length) { - main_label.label = animation_frames[animation_frame]; - animation_frame++; - return true; - } + if (settings.version != Config.VERSION) { + settings.version = Config.VERSION; + + Timeout.add (60, ()=> { + if (animation_frame < animation_frames.length) { + main_label.label = animation_frames[animation_frame]; + animation_frame++; + return true; + } + + main_label.label = settings.last_output_scientific; + main_entry.text = settings.last_input_scientific; + main_entry.grab_focus_without_selecting (); + main_entry.set_position (-1); + history_display.visible = true; + history_display.add_css_class ("animate-in"); + return false; + }); + } else { main_label.label = settings.last_output_scientific; main_entry.text = settings.last_input_scientific; main_entry.grab_focus_without_selecting (); main_entry.set_position (-1); history_display.visible = true; history_display.add_css_class ("animate-in"); - - return false; - }); + } return false; }, Priority.LOW);