summaryrefslogtreecommitdiffstats
path: root/src/ui/widget/unit-tracker.cpp
diff options
context:
space:
mode:
authorMatthew Petroff <matthew@mpetroff.net>2013-07-17 00:10:36 +0000
committerMatthew Petroff <matthew@mpetroff.net>2013-07-17 00:10:36 +0000
commit3174f1abec451e06ff36bf8f4d9a1e5992ee0382 (patch)
tree518efbf22d68fcac4efb760b5b6d66ac19167d07 /src/ui/widget/unit-tracker.cpp
parentPorted sp-namedview.cpp (todo: fix a bunch of things). (diff)
downloadinkscape-3174f1abec451e06ff36bf8f4d9a1e5992ee0382.tar.gz
inkscape-3174f1abec451e06ff36bf8f4d9a1e5992ee0382.zip
Added new UnitTracker class.
(bzr r12380.1.9)
Diffstat (limited to 'src/ui/widget/unit-tracker.cpp')
-rw-r--r--src/ui/widget/unit-tracker.cpp255
1 files changed, 255 insertions, 0 deletions
diff --git a/src/ui/widget/unit-tracker.cpp b/src/ui/widget/unit-tracker.cpp
new file mode 100644
index 000000000..b701c785e
--- /dev/null
+++ b/src/ui/widget/unit-tracker.cpp
@@ -0,0 +1,255 @@
+/*
+ * Inkscape::UI::Widget::UnitTracker
+ * Simple mediator to synchronize changes to unit menus
+ *
+ * Authors:
+ * Jon A. Cruz <jon@joncruz.org>
+ * Matthew Petroff <matthew@mpetroff.net>
+ *
+ * Copyright (C) 2007 Jon A. Cruz
+ * Copyright (C) 2013 Matthew Petroff
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "unit-tracker.h"
+#include "ege-select-one-action.h"
+
+#define COLUMN_STRING 0
+
+namespace Inkscape {
+namespace UI {
+namespace Widget {
+
+UnitTracker::UnitTracker(UnitType unit_type) :
+ _active(0),
+ _isUpdating(false),
+ _activeUnitInitialized(false),
+ _store(0),
+ _unitList(0),
+ _actionList(0),
+ _adjList(0),
+ _priorValues()
+{
+ _store = gtk_list_store_new(1, G_TYPE_STRING);
+ static Inkscape::Util::UnitTable unit_table;
+
+ GtkTreeIter iter;
+ UnitTable::UnitMap m = _unit_table.units(unit_type);
+ UnitTable::UnitMap::iterator m_iter = m.begin();
+ while(m_iter != m.end()) {
+ Glib::ustring text = (*m_iter).first;
+ m_iter++;
+ gtk_list_store_append(_store, &iter);
+ gtk_list_store_set(_store, &iter, COLUMN_STRING, text.c_str(), -1);
+ }
+ gint count = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(_store), 0);
+ if ((count > 0) && (_active > count)) {
+ _setActive(--count);
+ } else {
+ _setActive(_active);
+ }
+}
+
+UnitTracker::~UnitTracker()
+{
+ // Unhook weak references to GtkActions
+ while (_actionList) {
+ g_signal_handlers_disconnect_by_func(G_OBJECT(_actionList->data), (gpointer) _unitChangedCB, this);
+ g_object_weak_unref(G_OBJECT(_actionList->data), _actionFinalizedCB, this);
+ _actionList = g_slist_delete_link(_actionList, _actionList);
+ }
+
+ // Unhook weak references to GtkAdjustments
+ while (_adjList) {
+ g_object_weak_unref(G_OBJECT(_adjList->data), _adjustmentFinalizedCB, this);
+ _adjList = g_slist_delete_link(_adjList, _adjList);
+ }
+}
+
+bool UnitTracker::isUpdating() const
+{
+ return _isUpdating;
+}
+
+Inkscape::Util::Unit UnitTracker::getActiveUnit() const
+{
+ return _activeUnit;
+}
+
+void UnitTracker::setActiveUnit(Inkscape::Util::Unit const *unit)
+{
+ if (unit) {
+ GtkTreeIter iter;
+ int index = 0;
+ gboolean found = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(_store), &iter);
+ while (found) {
+ gchar *storedUnit = 0;
+ gtk_tree_model_get(GTK_TREE_MODEL(_store), &iter, COLUMN_STRING, &storedUnit, -1);
+ if (storedUnit && (!unit->abbr.compare(storedUnit))) {
+ _setActive(index);
+ break;
+ }
+
+ found = gtk_tree_model_iter_next(GTK_TREE_MODEL(_store), &iter);
+ index++;
+ }
+ }
+}
+
+void UnitTracker::setActiveUnitByAbbr(gchar const *abbr)
+{
+ Inkscape::Util::Unit u = _unit_table.getUnit(abbr);
+ setActiveUnit(&u);
+}
+
+void UnitTracker::addAdjustment(GtkAdjustment *adj)
+{
+ if (!g_slist_find(_adjList, adj)) {
+ g_object_weak_ref(G_OBJECT(adj), _adjustmentFinalizedCB, this);
+ _adjList = g_slist_append(_adjList, adj);
+ }
+}
+
+void UnitTracker::setFullVal(GtkAdjustment *adj, gdouble val)
+{
+ _priorValues[adj] = val;
+}
+
+GtkAction *UnitTracker::createAction(gchar const *name, gchar const *label, gchar const *tooltip)
+{
+ EgeSelectOneAction *act1 = ege_select_one_action_new(name, label, tooltip, NULL, GTK_TREE_MODEL(_store));
+ ege_select_one_action_set_label_column(act1, COLUMN_STRING);
+ if (_active) {
+ ege_select_one_action_set_active(act1, _active);
+ }
+
+ ege_select_one_action_set_appearance(act1, "minimal");
+ g_object_weak_ref(G_OBJECT(act1), _actionFinalizedCB, this);
+ g_signal_connect(G_OBJECT(act1), "changed", G_CALLBACK(_unitChangedCB), this);
+ _actionList = g_slist_append(_actionList, act1);
+
+ return GTK_ACTION(act1);
+}
+
+void UnitTracker::_unitChangedCB(GtkAction *action, gpointer data)
+{
+ if (action && data) {
+ EgeSelectOneAction *act = EGE_SELECT_ONE_ACTION(action);
+ gint active = ege_select_one_action_get_active(act);
+ UnitTracker *self = reinterpret_cast<UnitTracker *>(data);
+ self->_setActive(active);
+ }
+}
+
+void UnitTracker::_actionFinalizedCB(gpointer data, GObject *where_the_object_was)
+{
+ if (data && where_the_object_was) {
+ UnitTracker *self = reinterpret_cast<UnitTracker *>(data);
+ self->_actionFinalized(where_the_object_was);
+ }
+}
+
+void UnitTracker::_adjustmentFinalizedCB(gpointer data, GObject *where_the_object_was)
+{
+ if (data && where_the_object_was) {
+ UnitTracker *self = reinterpret_cast<UnitTracker *>(data);
+ self->_adjustmentFinalized(where_the_object_was);
+ }
+}
+
+void UnitTracker::_actionFinalized(GObject *where_the_object_was)
+{
+ GSList *target = g_slist_find(_actionList, where_the_object_was);
+ if (target) {
+ _actionList = g_slist_remove(_actionList, where_the_object_was);
+ } else {
+ g_warning("Received a finalization callback for unknown object %p", where_the_object_was);
+ }
+}
+
+void UnitTracker::_adjustmentFinalized(GObject *where_the_object_was)
+{
+ GSList *target = g_slist_find(_adjList, where_the_object_was);
+ if (target) {
+ _adjList = g_slist_remove(_adjList, where_the_object_was);
+ } else {
+ g_warning("Received a finalization callback for unknown object %p", where_the_object_was);
+ }
+}
+
+void UnitTracker::_setActive(gint active)
+{
+ if ( active != _active || !_activeUnitInitialized ) {
+ gint oldActive = _active;
+
+ GtkTreeIter iter;
+ gboolean found = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(_store), &iter, NULL, oldActive);
+ if (found) {
+ gchar *abbr;
+ gtk_tree_model_get(GTK_TREE_MODEL(_store), &iter, COLUMN_STRING, &abbr, -1);
+ Inkscape::Util::Unit unit = _unit_table.getUnit(abbr);
+
+ found = gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(_store), &iter, NULL, active);
+ if (found) {
+ gchar *newAbbr;
+ gtk_tree_model_get(GTK_TREE_MODEL(_store), &iter, COLUMN_STRING, &newAbbr, -1);
+ Inkscape::Util::Unit newUnit = _unit_table.getUnit(newAbbr);
+ _activeUnit = newUnit;
+
+ if (_adjList) {
+ _fixupAdjustments(unit, newUnit);
+ }
+
+ } else {
+ g_warning("Did not find new unit");
+ }
+ } else {
+ g_warning("Did not find old unit");
+ }
+
+ _active = active;
+
+ for ( GSList *cur = _actionList ; cur ; cur = g_slist_next(cur) ) {
+ if (IS_EGE_SELECT_ONE_ACTION(cur->data)) {
+ EgeSelectOneAction *act = EGE_SELECT_ONE_ACTION(cur->data);
+ ege_select_one_action_set_active(act, active);
+ }
+ }
+
+ _activeUnitInitialized = true;
+ }
+}
+
+void UnitTracker::_fixupAdjustments(Inkscape::Util::Unit const oldUnit, Inkscape::Util::Unit const newUnit)
+{
+ _isUpdating = true;
+ Inkscape::Util::Unit px = _unit_table.getUnit("px");
+ for ( GSList *cur = _adjList ; cur ; cur = g_slist_next(cur) ) {
+ GtkAdjustment *adj = GTK_ADJUSTMENT(cur->data);
+ gdouble oldVal = gtk_adjustment_get_value(adj);
+ gdouble val = oldVal;
+
+ if ( (oldUnit.type != Inkscape::Util::UNIT_TYPE_DIMENSIONLESS)
+ && (newUnit.type == Inkscape::Util::UNIT_TYPE_DIMENSIONLESS) )
+ {
+ val = 1.0 / newUnit.factor;
+ _priorValues[adj] = Inkscape::Util::Quantity::convert(oldVal, &oldUnit, &px);
+ } else if ( (oldUnit.type == Inkscape::Util::UNIT_TYPE_DIMENSIONLESS)
+ && (newUnit.type != Inkscape::Util::UNIT_TYPE_DIMENSIONLESS) )
+ {
+ if (_priorValues.find(adj) != _priorValues.end()) {
+ val = Inkscape::Util::Quantity::convert(_priorValues[adj], &newUnit, &px);
+ }
+ } else {
+ val = Inkscape::Util::Quantity::convert(oldVal, &oldUnit, &newUnit);
+ }
+
+ gtk_adjustment_set_value(adj, val);
+ }
+ _isUpdating = false;
+}
+
+} // namespace Widget
+} // namespace UI
+} // namespace Inkscape