[gnome-calculator] WIP: Use GtkPopovers for memory and function buttons. Bug 748742.
- From: Robert Roth <robertroth src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-calculator] WIP: Use GtkPopovers for memory and function buttons. Bug 748742.
- Date: Fri, 28 Oct 2016 07:00:36 +0000 (UTC)
commit ad6270b713da26c6b34a30934b4315c390bb007f
Author: Niels De Graef <nielsdegraef gmail com>
Date: Mon Oct 24 13:28:00 2016 +0200
WIP: Use GtkPopovers for memory and function buttons. Bug 748742.
Signed-off-by: Niels De Graef <nielsdegraef gmail com>
data/Makefile.am | 2 +
data/buttons-advanced.ui | 4 +-
data/buttons-financial.ui | 2 +-
data/buttons-programming.ui | 2 +-
data/calculator.css | 6 +
data/gnome-calculator.gresource.xml | 2 +
data/math-function-popover.ui | 76 ++++++++++++
data/math-variable-popover.ui | 67 ++++++++++
lib/function-manager.vala | 17 ++-
lib/math-variables.vala | 14 ++-
po/POTFILES.in | 5 +-
src/Makefile.am | 4 +-
src/math-buttons.vala | 40 +-----
src/math-function-popover.vala | 197 ++++++++++++++++++++++++++++++
src/math-function-popup.vala | 227 -----------------------------------
src/math-variable-popover.vala | 157 ++++++++++++++++++++++++
src/math-variable-popup.vala | 184 ----------------------------
17 files changed, 550 insertions(+), 456 deletions(-)
---
diff --git a/data/Makefile.am b/data/Makefile.am
index a8ba11d..d44122e 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -21,6 +21,8 @@ EXTRA_DIST = \
history-entry.ui \
history-view.ui \
math-converter.ui \
+ math-function-popover.ui \
+ math-variable-popover.ui \
math-window.ui \
math-shortcuts.ui \
menu.ui \
diff --git a/data/buttons-advanced.ui b/data/buttons-advanced.ui
index 835c5b4..28ed249 100644
--- a/data/buttons-advanced.ui
+++ b/data/buttons-advanced.ui
@@ -567,7 +567,7 @@
</packing>
</child>
<child>
- <object class="GtkButton" id="calc_memory_button">
+ <object class="GtkMenuButton" id="calc_memory_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
@@ -943,7 +943,7 @@
</packing>
</child>
<child>
- <object class="GtkButton" id="calc_function_button">
+ <object class="GtkMenuButton" id="calc_function_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
diff --git a/data/buttons-financial.ui b/data/buttons-financial.ui
index e562ed5..17ff485 100644
--- a/data/buttons-financial.ui
+++ b/data/buttons-financial.ui
@@ -1846,7 +1846,7 @@
<property name="column-homogeneous">True</property>
<property name="column_spacing">4</property>
<child>
- <object class="GtkButton" id="calc_memory_button">
+ <object class="GtkMenuButton" id="calc_memory_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
diff --git a/data/buttons-programming.ui b/data/buttons-programming.ui
index 6379c27..24066b1 100644
--- a/data/buttons-programming.ui
+++ b/data/buttons-programming.ui
@@ -1849,7 +1849,7 @@
</packing>
</child>
<child>
- <object class="GtkButton" id="calc_memory_button">
+ <object class="GtkMenuButton" id="calc_memory_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
diff --git a/data/calculator.css b/data/calculator.css
index ab84348..97e241e 100644
--- a/data/calculator.css
+++ b/data/calculator.css
@@ -63,3 +63,9 @@ window > grid {
.history-entry .answer-label {
}
+
+/* Used for MathVariablePopover */
+row.popover-row {
+ border-bottom: 1px groove @borders;
+ min-height: 35px;
+}
diff --git a/data/gnome-calculator.gresource.xml b/data/gnome-calculator.gresource.xml
index bec25ea..403c045 100644
--- a/data/gnome-calculator.gresource.xml
+++ b/data/gnome-calculator.gresource.xml
@@ -8,6 +8,8 @@
<file preprocess="xml-stripblanks">history-view.ui</file>
<file preprocess="xml-stripblanks">history-entry.ui</file>
<file preprocess="xml-stripblanks">math-converter.ui</file>
+ <file preprocess="xml-stripblanks">math-function-popover.ui</file>
+ <file preprocess="xml-stripblanks">math-variable-popover.ui</file>
<file preprocess="xml-stripblanks">math-window.ui</file>
<file preprocess="xml-stripblanks">math-shortcuts.ui</file>
<file preprocess="xml-stripblanks">menu.ui</file>
diff --git a/data/math-function-popover.ui b/data/math-function-popover.ui
new file mode 100644
index 0000000..766ec55
--- /dev/null
+++ b/data/math-function-popover.ui
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.16"/>
+ <template class="MathFunctionPopover" parent="GtkPopover">
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox" id="vbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkScrolledWindow" id="function_list_scrolled">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="height_request">200</property>
+ <property name="shadow_type">in</property>
+ <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+ <child>
+ <object class="GtkListBox" id="function_list">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="selection_mode">none</property>
+ <signal name="row_activated" handler="insert_function_cb" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkEntry" id="function_name_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="placeholder_text" translatable="yes">New function</property>
+ <signal name="button_press_event" handler="function_name_mouse_click_cb" swapped="no"/>
+ <signal name="key_press_event" handler="function_name_key_press_cb" swapped="no"/>
+ <signal name="changed" handler="function_name_changed_cb" swapped="no"/>
+ <signal name="activate" handler="add_function_cb" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="add_function_box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
+ <property name="spacing">6</property>
+ <property name="tooltip_text">Select no. of arguments</property>
+ <child>
+ <object class="GtkSpinButton" id="add_arguments_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="add_function_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="sensitive">False</property>
+ <signal name="clicked" handler="add_function_cb" swapped="no"/>
+ <child>
+ <object class="GtkImage" id="add_function_button_image">
+ <property name="visible">True</property>
+ <property name="icon_name">list-add-symbolic</property>
+ <property name="pixel_size">16</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="pack_type">end</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/data/math-variable-popover.ui b/data/math-variable-popover.ui
new file mode 100644
index 0000000..62ab198
--- /dev/null
+++ b/data/math-variable-popover.ui
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.16"/>
+ <template class="MathVariablePopover" parent="GtkPopover">
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox" id="content">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="margin">3</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkScrolledWindow" id="variable_list_scrolled">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="height_request">150</property>
+ <property name="shadow_type">in</property>
+ <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+ <child>
+ <object class="GtkListBox" id="variable_list">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="selection_mode">none</property>
+ <signal name="row_activated" handler="insert_variable_cb" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="add_variable_box">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
+ <child>
+ <object class="GtkEntry" id="variable_name_entry">
+ <property name="placeholder_text" translatable="yes">Variable name</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <signal name="key_press_event" handler="variable_name_key_press_cb" swapped="no"/>
+ <signal name="changed" handler="variable_name_changed_cb" swapped="no"/>
+ <signal name="activate" handler="store_variable_cb" swapped="no"/>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="store_variable_button">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="sensitive">False</property>
+ <property name="tooltip_text" translatable="yes">Store value into existing or new
variable</property>
+ <signal name="clicked" handler="store_variable_cb" swapped="no"/>
+ <child>
+ <object class="GtkImage" id="store_variable_button_image">
+ <property name="visible">True</property>
+ <property name="icon_name">document-save-symbolic</property>
+ <property name="pixel_size">16</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/lib/function-manager.vala b/lib/function-manager.vala
index d07c87a..61dd4ea 100644
--- a/lib/function-manager.vala
+++ b/lib/function-manager.vala
@@ -16,6 +16,10 @@ public class FunctionManager : Object
private HashTable<string, MathFunction> functions;
private Serializer serializer;
+ public signal void function_added (MathFunction function);
+ public signal void function_edited (MathFunction new_function);
+ public signal void function_deleted (MathFunction function);
+
public FunctionManager ()
{
functions = new HashTable <string, MathFunction> (str_hash, str_equal);
@@ -159,7 +163,7 @@ public class FunctionManager : Object
if (expression == null)
return null;
- i = left.index_of_char('(');
+ i = left.index_of_char ('(');
if (i < 0)
return null;
var name = left.substring (0, i).strip ();
@@ -243,6 +247,11 @@ public class FunctionManager : Object
return array_sort_string (names);
}
+ /**
+ * Adds a function to the manager, unless the given name is already taken
+ * by a predefined function.
+ * @return If the function was successfully added.
+ */
private bool add (MathFunction new_function)
{
MathFunction? existing_function = get (new_function.name);
@@ -250,10 +259,11 @@ public class FunctionManager : Object
if (existing_function != null && !existing_function.is_custom_function ())
return false;
+ functions[new_function.name] = new_function;
if (existing_function != null)
- functions.replace (new_function.name, new_function);
+ function_edited (new_function);
else
- functions.insert (new_function.name, new_function);
+ function_added (new_function);
return true;
}
@@ -291,6 +301,7 @@ public class FunctionManager : Object
{
functions.remove (name);
save ();
+ function_deleted (function);
}
}
diff --git a/lib/math-variables.vala b/lib/math-variables.vala
index 63b7191..9685b2c 100644
--- a/lib/math-variables.vala
+++ b/lib/math-variables.vala
@@ -14,6 +14,10 @@ public class MathVariables : Object
private HashTable<string, Number?> registers;
private Serializer serializer;
+ public signal void variable_added (string name, Number value);
+ public signal void variable_edited (string name, Number new_value);
+ public signal void variable_deleted (string name);
+
public MathVariables ()
{
registers = new HashTable <string, Number?> (str_hash, str_equal);
@@ -138,18 +142,24 @@ public class MathVariables : Object
public new void set (string name, Number value)
{
- registers.insert (name, value);
+ bool editing = registers.contains (name);
+ registers[name] = value;
save ();
+ if (editing)
+ variable_edited (name, value);
+ else
+ variable_added (name, value);
}
public new Number? get (string name)
{
- return registers.lookup (name);
+ return registers[name];
}
public void delete (string name)
{
registers.remove (name);
save ();
+ variable_deleted (name);
}
}
diff --git a/po/POTFILES.in b/po/POTFILES.in
index c393e8a..b58dc51 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -8,6 +8,8 @@
data/gnome-calculator.appdata.xml.in
data/gnome-calculator.desktop.in
[type: gettext/glade]data/math-converter.ui
+[type: gettext/glade]data/math-function-popover.ui
+[type: gettext/glade]data/math-variable-popover.ui
[type: gettext/glade]data/math-window.ui
[type: gettext/glade]data/math-shortcuts.ui
[type: gettext/glade]data/menu.ui
@@ -30,7 +32,8 @@ src/math-buttons.vala
src/math-converter.vala
src/math-display.vala
src/math-preferences.vala
-src/math-variable-popup.vala
+src/math-function-popover.vala
+src/math-variable-popover.vala
src/math-window.vala
tests/test-equation.vala
tests/test-number.vala
diff --git a/src/Makefile.am b/src/Makefile.am
index 6ad5a70..dbe0871 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -22,9 +22,9 @@ gnome_calculator_SOURCES = \
math-converter.vala \
math-display.vala \
math-preferences.vala \
- math-variable-popup.vala \
+ math-function-popover.vala \
+ math-variable-popover.vala \
math-window.vala \
- math-function-popup.vala \
math-history.vala \
$(BUILT_SOURCES)
diff --git a/src/math-buttons.vala b/src/math-buttons.vala
index 38d0f02..2e7f546 100644
--- a/src/math-buttons.vala
+++ b/src/math-buttons.vala
@@ -341,13 +341,7 @@ public class MathButtons : Gtk.Box
}
/* Configure buttons */
- var button = builder.get_object ("calc_memory_button") as Gtk.Button;
- if (button != null)
- button.clicked.connect (on_memory);
- button = builder.get_object ("calc_function_button") as Gtk.Button;
- if (button != null)
- button.clicked.connect (on_insert_function);
- button = builder.get_object ("calc_numeric_point_button") as Gtk.Button;
+ var button = builder.get_object ("calc_numeric_point_button") as Gtk.Button;
if (button != null)
button.set_label (equation.serializer.get_radix ().to_string ());
@@ -357,6 +351,12 @@ public class MathButtons : Gtk.Box
menu_button = builder.get_object ("calc_shift_right_button") as Gtk.MenuButton;
if (menu_button != null)
menu_button.menu_model = create_shift_menu (false);
+ menu_button = builder.get_object ("calc_memory_button") as Gtk.MenuButton;
+ if (menu_button != null)
+ menu_button.popover = new MathVariablePopover (equation);
+ menu_button = builder.get_object ("calc_function_button") as Gtk.MenuButton;
+ if (menu_button != null)
+ menu_button.popover = new MathFunctionPopover (equation);
if (mode == ButtonMode.PROGRAMMING)
{
@@ -455,19 +455,6 @@ public class MathButtons : Gtk.Box
}
}
- private void on_memory (Gtk.Widget widget)
- {
- var popup = new MathVariablePopup (equation);
- popup.set_transient_for (widget.get_toplevel () as Gtk.Window);
-
- Gtk.Allocation allocation;
- widget.get_allocation (out allocation);
- int x, y;
- widget.get_window ().get_root_coords (allocation.x, allocation.y, out x, out y);
- popup.move (x, y);
- popup.show ();
- }
-
private Menu create_shift_menu (bool shift_left)
{
var shift_menu = new Menu ();
@@ -485,19 +472,6 @@ public class MathButtons : Gtk.Box
return shift_menu;
}
- private void on_insert_function (Gtk.Widget widget)
- {
- var popup = new MathFunctionPopup (equation);
- popup.set_transient_for (widget.get_toplevel () as Gtk.Window);
-
- Gtk.Allocation allocation;
- widget.get_allocation (out allocation);
- int x, y;
- widget.get_window ().get_root_coords (allocation.x, allocation.y, out x, out y);
- popup.move (x, y);
- popup.show ();
- }
-
private void on_launch_finc_dialog (SimpleAction action, Variant? param)
{
var name = param.get_string ();
diff --git a/src/math-function-popover.vala b/src/math-function-popover.vala
new file mode 100644
index 0000000..e44c184
--- /dev/null
+++ b/src/math-function-popover.vala
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2013 Garima Joshi
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
+ * license.
+ */
+
+[GtkTemplate (ui = "/org/gnome/calculator/math-function-popover.ui")]
+public class MathFunctionPopover : Gtk.Popover
+{
+ // Used to pretty print function arguments, e.g. f(x, y, z)
+ private static string[] FUNCTION_ARGS = {"x","y","z","u","v","w","a","b","c","d"};
+
+ private MathEquation equation;
+
+ [GtkChild]
+ private Gtk.ListBox function_list;
+
+ [GtkChild]
+ private Gtk.Entry function_name_entry;
+ private bool function_name_entry_placeholder_reseted = false;
+
+ [GtkChild]
+ private Gtk.Button add_function_button;
+ [GtkChild]
+ private Gtk.SpinButton add_arguments_button;
+
+ public MathFunctionPopover (MathEquation equation)
+ {
+ this.equation = equation;
+
+ FunctionManager function_manager = FunctionManager.get_default_function_manager ();
+ var names = function_manager.get_names ();
+
+ for (var i = 0; names[i] != null; i++)
+ {
+ var function = function_manager[names[i]];
+ function_list.add (make_function_row (function));
+ }
+
+ // Sort list
+ function_list.set_sort_func (function_list_sort);
+
+ function_manager.function_added.connect ((function) => {
+ function_list.add (make_function_row (function));
+ });
+ function_manager.function_edited.connect ((function) => {
+ function_list.remove (find_row_for_function (function));
+ function_list.add (make_function_row (function));
+ });
+ function_manager.function_deleted.connect ((function) => {
+ function_list.remove (find_row_for_function (function));
+ });
+
+ add_arguments_button.set_range (1, 10);
+ add_arguments_button.set_increments (1, 1);
+ }
+
+ private Gtk.ListBoxRow? find_row_for_function (MathFunction function)
+ {
+ weak Gtk.ListBoxRow? row = null;
+ function_list.foreach ((child) => {
+ if (function.name == child.get_data<MathFunction> ("function").name)
+ row = child as Gtk.ListBoxRow;
+ });
+ return row;
+ }
+
+ [GtkCallback]
+ private void insert_function_cb (Gtk.ListBoxRow row)
+ {
+ var function = row.get_data<MathFunction> ("function");
+ equation.insert (function.name + "()");
+
+ // Place the cursor between the parentheses after inserting the function
+ Gtk.TextIter end;
+ equation.get_iter_at_mark (out end, equation.get_insert ());
+ end.backward_chars (1);
+ equation.place_cursor (end);
+ }
+
+ [GtkCallback]
+ private bool function_name_mouse_click_cb (Gtk.Widget widget, Gdk.EventButton event)
+ {
+ if (!this.function_name_entry_placeholder_reseted)
+ {
+ this.function_name_entry_placeholder_reseted = true;
+ this.function_name_entry.text = "";
+ }
+
+ return false;
+ }
+
+ [GtkCallback]
+ private bool function_name_key_press_cb (Gtk.Widget widget, Gdk.EventKey event)
+ {
+ this.function_name_entry_placeholder_reseted = true;
+
+ /* Can't have whitespace in names, so replace with underscores */
+ if (event.keyval == Gdk.Key.space || event.keyval == Gdk.Key.KP_Space)
+ event.keyval = Gdk.Key.underscore;
+
+ return false;
+ }
+
+ [GtkCallback]
+ private void function_name_changed_cb ()
+ {
+ add_function_button.sensitive = function_name_entry.get_text () != "";
+ }
+
+ [GtkCallback]
+ private void add_function_cb (Gtk.Widget widget)
+ {
+ var name = function_name_entry.text;
+ if (name == "")
+ return;
+
+ var arguments = add_arguments_button.get_value_as_int ();
+ string formatted_args = "";
+ if (arguments > 0)
+ formatted_args = string.joinv ("; ", FUNCTION_ARGS[0:arguments]);
+
+ name += "(%s)=".printf(formatted_args);
+ equation.clear ();
+ equation.insert (name);
+ }
+
+ private void save_function_cb (Gtk.Widget widget)
+ {
+ var function = widget.get_data<MathFunction> ("function");
+ var function_to_edit = "%s(%s)=%s@%s".printf (function.name,
+ string.joinv (";", function.arguments),
+ function.expression,
+ function.description);
+ equation.clear ();
+ equation.insert (function_to_edit);
+ }
+
+ private void delete_function_cb (Gtk.Widget widget)
+ {
+ var function = widget.get_data<MathFunction> ("function");
+
+ var function_manager = FunctionManager.get_default_function_manager ();
+ function_manager.delete (function.name);
+ }
+
+ private Gtk.ListBoxRow make_function_row (MathFunction function)
+ {
+ var row = new Gtk.ListBoxRow ();
+ row.get_style_context ().add_class ("popover-row");
+ row.set_data<MathFunction> ("function", function);
+ row.set_tooltip_text ("%s".printf (function.description));
+
+ var hbox = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 6);
+
+ var expression = "(x)";
+ if (function.is_custom_function ())
+ expression = "(%s)".printf (string.joinv (";", function.arguments));
+
+ var label = new Gtk.Label ("<b>%s</b>%s".printf (function.name, expression));
+ label.set_use_markup (true);
+ label.halign = Gtk.Align.START;
+ hbox.pack_start (label, true, true, 0);
+
+ if (function.is_custom_function ())
+ {
+ var button = new Gtk.Button.from_icon_name ("edit-symbolic");
+ button.get_style_context ().add_class ("flat");
+ button.set_data<MathFunction> ("function", function);
+ button.clicked.connect (save_function_cb);
+ hbox.pack_start (button, false, true, 0);
+
+ button = new Gtk.Button.from_icon_name ("list-remove-symbolic");
+ button.get_style_context ().add_class ("flat");
+ button.set_data<MathFunction> ("function", function);
+ button.clicked.connect (delete_function_cb);
+ hbox.pack_start (button, false, true, 0);
+ }
+
+ row.add (hbox);
+ row.show_all ();
+
+ return row;
+ }
+
+ private int function_list_sort (Gtk.ListBoxRow row1, Gtk.ListBoxRow row2)
+ {
+ var function1 = row1.get_data<MathFunction> ("function");
+ var function2 = row2.get_data<MathFunction> ("function");
+
+ return strcmp (function1.name, function2.name);
+ }
+}
diff --git a/src/math-variable-popover.vala b/src/math-variable-popover.vala
new file mode 100644
index 0000000..b5c7c31
--- /dev/null
+++ b/src/math-variable-popover.vala
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2008-2012 Robert Ancell
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
+ * license.
+ */
+
+[GtkTemplate (ui = "/org/gnome/calculator/math-variable-popover.ui")]
+public class MathVariablePopover : Gtk.Popover
+{
+ private static string[] RESERVED_VARIABLE_NAMES = {"ans", "rand"};
+
+ private MathEquation equation;
+
+ [GtkChild]
+ private Gtk.ListBox variable_list;
+ [GtkChild]
+ private Gtk.Entry variable_name_entry;
+ [GtkChild]
+ private Gtk.Button store_variable_button;
+
+ public MathVariablePopover (MathEquation equation)
+ {
+ this.equation = equation;
+
+ // Fill variable list
+ var names = equation.variables.get_names ();
+ for (var i = 0; names[i] != null; i++)
+ {
+ var value = equation.variables[names[i]];
+ variable_list.add (make_variable_row (names[i], value));
+ }
+
+ variable_list.add (make_variable_row ("rand", null));
+ variable_list.add (make_variable_row ("ans", equation.answer));
+
+ // Sort list
+ variable_list.set_sort_func (variable_list_sort);
+
+ // Listen for variable changes
+ equation.variables.variable_added.connect ((name, value) => {
+ variable_list.add (make_variable_row (name, value));
+ });
+ equation.variables.variable_edited.connect ((name, value) => {
+ variable_list.remove (find_row_for_variable (name));
+ variable_list.add (make_variable_row (name, value));
+ });
+ equation.variables.variable_deleted.connect ((name) => {
+ variable_list.remove (find_row_for_variable (name));
+ });
+ }
+
+ private Gtk.ListBoxRow? find_row_for_variable (string name)
+ {
+ weak Gtk.ListBoxRow? row = null;
+ variable_list.foreach ((child) => {
+ if (name == child.get_data<string> ("variable_name"))
+ row = child as Gtk.ListBoxRow;
+ });
+ return row;
+ }
+
+ [GtkCallback]
+ private void insert_variable_cb (Gtk.ListBoxRow row)
+ {
+ var name = row.get_data<string> ("variable_name");
+ equation.insert (name);
+ }
+
+ [GtkCallback]
+ private bool variable_name_key_press_cb (Gtk.Widget widget, Gdk.EventKey event)
+ {
+ /* Can't have whitespace in names, so replace with underscores */
+ if (event.keyval == Gdk.Key.space || event.keyval == Gdk.Key.KP_Space)
+ event.keyval = Gdk.Key.underscore;
+
+ return false;
+ }
+
+ [GtkCallback]
+ private void variable_name_changed_cb ()
+ {
+ store_variable_button.sensitive = (variable_name_entry.get_text () != "");
+ }
+
+ [GtkCallback]
+ private void store_variable_cb (Gtk.Widget widget)
+ {
+ var name = variable_name_entry.get_text ();
+ if (name == "" || name in RESERVED_VARIABLE_NAMES)
+ return;
+
+ var z = equation.number;
+ if (z != null)
+ equation.variables[name] = z;
+ else if (equation.is_result)
+ equation.variables[name] = equation.answer;
+ else
+ warning ("Can't add variable %s, the display is not a number", name);
+
+ variable_name_entry.set_text ("");
+ }
+
+ private void delete_variable_cb (Gtk.Widget widget)
+ {
+ var name = widget.get_data<string> ("variable_name");
+ equation.variables.delete (name);
+ }
+
+ private Gtk.ListBoxRow make_variable_row (string name, Number? value)
+ {
+ var row = new Gtk.ListBoxRow ();
+ row.get_style_context ().add_class ("popover-row");
+ row.set_data<string> ("variable_name", name);
+
+ var hbox = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 6);
+
+ string text;
+ if (value != null)
+ {
+ var value_text = equation.serializer.to_string (value);
+ text = "<b>%s</b> = %s".printf (name, value_text);
+ }
+ else
+ text = "<b>%s</b>".printf (name);
+
+ var label = new Gtk.Label (text);
+ label.set_use_markup (true);
+ label.halign = Gtk.Align.START;
+ hbox.pack_start (label, true, true, 0);
+
+ if (!(name in RESERVED_VARIABLE_NAMES))
+ {
+ var button = new Gtk.Button.from_icon_name ("list-remove-symbolic");
+ button.get_style_context ().add_class ("flat");
+ button.set_data<string> ("variable_name", name);
+ button.clicked.connect (delete_variable_cb);
+ hbox.pack_start (button, false, true, 0);
+ }
+
+ row.add (hbox);
+ row.show_all ();
+
+ return row;
+ }
+
+ private int variable_list_sort (Gtk.ListBoxRow row1, Gtk.ListBoxRow row2)
+ {
+ string name1 = row1.get_data<string> ("variable_name");
+ string name2 = row2.get_data<string> ("variable_name");
+
+ return strcmp (name1, name2);
+ }
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]