Code

Adding signals and linking
authorjoncruz <joncruz@users.sourceforge.net>
Thu, 20 Mar 2008 08:44:00 +0000 (08:44 +0000)
committerjoncruz <joncruz@users.sourceforge.net>
Thu, 20 Mar 2008 08:44:00 +0000 (08:44 +0000)
src/device-manager.cpp
src/device-manager.h
src/ui/dialog/input.cpp

index bd34af2979d32d575a681e7475fe37fd175cdf23..9cf4583c698f1bfc379f2350536e9e4ea12d63d0 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <glib.h>
+#include <map>
 
 #include "device-manager.h"
 
@@ -19,17 +20,39 @@ static GList* fakeList = 0;
 
 namespace Inkscape {
 
-InputDevice::InputDevice() {}
+using std::pair;
+
+static pair<gint, gint> vals[] = {
+    pair<gint, gint>(0, 1), pair<gint, gint>(1, 1 << 1), pair<gint, gint>(2, 1 << 2), pair<gint, gint>(3, 1 << 3),
+    pair<gint, gint>(4, 1 << 4), pair<gint, gint>(5, 1 << 5), pair<gint, gint>(6, 1 << 6), pair<gint, gint>(7, 1 << 7),
+    pair<gint, gint>(8, 1 << 8), pair<gint, gint>(9, 1 << 9), pair<gint, gint>(10, 1 << 10), pair<gint, gint>(11, 1 << 11),
+    pair<gint, gint>(12, 1 << 12), pair<gint, gint>(13, 1 << 13), pair<gint, gint>(14, 1 << 14), pair<gint, gint>(15, 1 << 15),
+    pair<gint, gint>(16, 1 << 16), pair<gint, gint>(17, 1 << 17), pair<gint, gint>(18, 1 << 18), pair<gint, gint>(19, 1 << 19),
+    pair<gint, gint>(20, 1 << 20), pair<gint, gint>(21, 1 << 21), pair<gint, gint>(22, 1 << 22), pair<gint, gint>(23, 1 << 23)
+};
+static std::map<gint, gint> bitVals(vals, &vals[G_N_ELEMENTS(vals)]);
+
+
+InputDevice::InputDevice()
+    : Glib::Object()
+{}
+
 InputDevice::~InputDevice() {}
 
 class InputDeviceImpl : public InputDevice {
 public:
-    virtual Glib::ustring getName() const {return Glib::ustring(device->name);}
-    virtual Gdk::InputSource getSource() const {return static_cast<Gdk::InputSource>(device->source);}
+    virtual Glib::ustring getId() const {return id;}
+    virtual Glib::ustring getName() const {return name;}
+    virtual Gdk::InputSource getSource() const {return source;}
     virtual Gdk::InputMode getMode() const {return static_cast<Gdk::InputMode>(device->mode);}
     virtual bool hasCursor() const {return device->has_cursor;}
     virtual gint getNumAxes() const {return device->num_axes;}
     virtual gint getNumKeys() const {return device->num_keys;}
+    virtual Glib::ustring getLink() const {return link;}
+    virtual void setLink( Glib::ustring const& link ) {this->link = link;}
+    virtual gint getLiveButtons() const {return liveButtons;}
+    virtual void setLiveButtons(gint buttons) {liveButtons = buttons;}
+
 
     InputDeviceImpl(GdkDevice* device);
     virtual ~InputDeviceImpl() {}
@@ -39,12 +62,57 @@ private:
     void operator=(InputDeviceImpl const &); // no assign
 
     GdkDevice* device;
+    Glib::ustring id;
+    Glib::ustring name;
+    Gdk::InputSource source;
+    Glib::ustring link;
+    guint liveButtons;
+};
+
+class IdMatcher : public std::unary_function<InputDeviceImpl*, bool> {
+public:
+    IdMatcher(Glib::ustring const& target):target(target) {}
+    bool operator ()(InputDeviceImpl* dev) {return dev && (target == dev->getId());}
+
+private:
+    Glib::ustring const& target;
+};
+
+class LinkMatcher : public std::unary_function<InputDeviceImpl*, bool> {
+public:
+    LinkMatcher(Glib::ustring const& target):target(target) {}
+    bool operator ()(InputDeviceImpl* dev) {return dev && (target == dev->getLink());}
+
+private:
+    Glib::ustring const& target;
 };
 
 InputDeviceImpl::InputDeviceImpl(GdkDevice* device)
     : InputDevice(),
-      device(device)
+      device(device),
+      id(),
+      name(device->name ? device->name : ""),
+      source(static_cast<Gdk::InputSource>(device->source)),
+      link(),
+      liveButtons(0)
 {
+    switch ( source ) {
+        case Gdk::SOURCE_MOUSE:
+            id = "M:";
+            break;
+        case Gdk::SOURCE_CURSOR:
+            id = "C:";
+            break;
+        case Gdk::SOURCE_PEN:
+            id = "P:";
+            break;
+        case Gdk::SOURCE_ERASER:
+            id = "E:";
+            break;
+        default:
+            id = "?:";
+    }
+    id += name;
 }
 
 
@@ -58,11 +126,21 @@ class DeviceManagerImpl : public DeviceManager {
 public:
     DeviceManagerImpl();
     virtual std::list<InputDevice const *> getDevices();
+    virtual sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalDeviceChanged();
+    virtual sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalButtonsChanged();
+    virtual sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalLinkChanged();
+
+    virtual void addButton(Glib::ustring const & id, gint button);
+    virtual void setLinkedTo(Glib::ustring const & id, Glib::ustring const& link);
 
 protected:
     std::list<InputDeviceImpl*> devices;
+    sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalDeviceChangedPriv;
+    sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalButtonsChangedPriv;
+    sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalLinkChangedPriv;
 };
 
+
 DeviceManagerImpl::DeviceManagerImpl() :
     DeviceManager(),
     devices()
@@ -96,9 +174,87 @@ std::list<InputDevice const *> DeviceManagerImpl::getDevices()
 }
 
 
+sigc::signal<void, const Glib::RefPtr<InputDevice>& > DeviceManagerImpl::signalDeviceChanged()
+{
+    return signalDeviceChangedPriv;
+}
+
+sigc::signal<void, const Glib::RefPtr<InputDevice>& > DeviceManagerImpl::signalButtonsChanged()
+{
+    return signalButtonsChangedPriv;
+}
+
+sigc::signal<void, const Glib::RefPtr<InputDevice>& > DeviceManagerImpl::signalLinkChanged()
+{
+    return signalLinkChangedPriv;
+}
+
+void DeviceManagerImpl::addButton(Glib::ustring const & id, gint button)
+{
+    if ( button >= 0 && button < static_cast<gint>(bitVals.size()) ) {
+        std::list<InputDeviceImpl*>::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id));
+        if ( it != devices.end() ) {
+            gint mask = bitVals[button];
+            if ( (mask & (*it)->getLiveButtons()) == 0 ) {
+                (*it)->setLiveButtons((*it)->getLiveButtons() | mask);
+
+                // Only signal if a new button was added
+                (*it)->reference();
+                signalButtonsChangedPriv.emit(Glib::RefPtr<InputDevice>(*it));
+            }
+        }
+    }
+}
+
+
+void DeviceManagerImpl::setLinkedTo(Glib::ustring const & id, Glib::ustring const& link)
+{
+    std::list<InputDeviceImpl*>::iterator it = std::find_if(devices.begin(), devices.end(), IdMatcher(id));
+    if ( it != devices.end() ) {
+        InputDeviceImpl* dev = *it;
+        // Need to be sure the target of the link exists
+        it = std::find_if(devices.begin(), devices.end(), IdMatcher(link));
+        if ( it != devices.end() ) {
+            InputDeviceImpl* targetDev = *it;
+            if ( (dev->getLink() != link) || (targetDev->getLink() != id) ) {
+                // only muck about if they aren't already linked
+                std::list<InputDeviceImpl*> changedItems;
+
+                // Is something else already using that link?
+                it = std::find_if(devices.begin(), devices.end(), LinkMatcher(link));
+                if ( it != devices.end() ) {
+                    (*it)->setLink("");
+                    changedItems.push_back(*it);
+                }
+                it = std::find_if(devices.begin(), devices.end(), LinkMatcher(id));
+                if ( it != devices.end() ) {
+                    (*it)->setLink("");
+                    changedItems.push_back(*it);
+                }
+                dev->setLink(link);
+                targetDev->setLink(id);
+                changedItems.push_back(targetDev);
+                changedItems.push_back(dev);
+
+                for ( std::list<InputDeviceImpl*>::const_iterator iter = changedItems.begin(); iter != changedItems.end(); ++iter ) {
+                    (*iter)->reference();
+                    signalLinkChangedPriv.emit(Glib::RefPtr<InputDevice>(*iter));
+                }
+            }
+        }
+    }
+}
+
+
+
+
+
+
 static DeviceManagerImpl* theInstance = 0;
 
-DeviceManager::DeviceManager() {
+DeviceManager::DeviceManager()
+    : Glib::Object()
+{
 }
 
 DeviceManager::~DeviceManager() {
@@ -197,14 +353,23 @@ static void createFakeList() {
         fakeout[3].num_keys = 7;
         fakeout[3].keys = stylusKeys;
 
-        fakeout[4].name = "Core Pointer";
-        fakeout[4].source = GDK_SOURCE_MOUSE;
-        fakeout[4].mode = GDK_MODE_SCREEN;
-        fakeout[4].has_cursor = TRUE;
-        fakeout[4].num_axes = 2;
-        fakeout[4].axes = coreAxes;
-        fakeout[4].num_keys = 0;
-        fakeout[4].keys = NULL;
+// try to find the first *real* core pointer
+        GList* devList = gdk_devices_list();
+        while ( devList && devList->data && (((GdkDevice*)devList->data)->source != GDK_SOURCE_MOUSE) ) {
+            devList = g_list_next(devList);
+        }
+        if ( devList && devList->data ) {
+            fakeout[4] = *((GdkDevice*)devList->data);
+        } else {
+            fakeout[4].name = "Core Pointer";
+            fakeout[4].source = GDK_SOURCE_MOUSE;
+            fakeout[4].mode = GDK_MODE_SCREEN;
+            fakeout[4].has_cursor = TRUE;
+            fakeout[4].num_axes = 2;
+            fakeout[4].axes = coreAxes;
+            fakeout[4].num_keys = 0;
+            fakeout[4].keys = NULL;
+        }
 
         for ( guint pos = 0; pos < G_N_ELEMENTS(fakeout); pos++) {
             fakeList = g_list_append(fakeList, &(fakeout[pos]));
index 0b532aae28a979dd82b5272d2ff9481976e1f13d..f441180a67c8fd2a4a910dd46a98a3d6190b54bc 100644 (file)
 
 namespace Inkscape {
 
-class InputDevice {
+class InputDevice : public Glib::Object {
 public:
+    virtual Glib::ustring getId() const = 0;
     virtual Glib::ustring getName() const = 0;
     virtual Gdk::InputSource getSource() const = 0;
     virtual Gdk::InputMode getMode() const = 0;
     virtual bool hasCursor() const = 0;
     virtual gint getNumAxes() const = 0;
     virtual gint getNumKeys() const = 0;
+    virtual Glib::ustring getLink() const = 0;
+    virtual gint getLiveButtons() const = 0;
 
 protected:
     InputDevice();
@@ -34,11 +37,17 @@ private:
     void operator=(InputDevice const &); // no assign
 };
 
-class DeviceManager {
+class DeviceManager : public Glib::Object {
 public:
     static DeviceManager& getManager();
 
     virtual std::list<InputDevice const *> getDevices() = 0;
+    virtual sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalDeviceChanged() = 0;
+    virtual sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalButtonsChanged() = 0;
+    virtual sigc::signal<void, const Glib::RefPtr<InputDevice>& > signalLinkChanged() = 0;
+
+    virtual void addButton(Glib::ustring const & id, gint button) = 0;
+    virtual void setLinkedTo(Glib::ustring const & id, Glib::ustring const& link) = 0;
 
 protected:
     DeviceManager();
index 8e132a2f5bc560764f8bd6a38610ae74bca0123c..f5746dbdecb413eece434b7b71a4f5755551d0e5 100644 (file)
@@ -1,5 +1,29 @@
 
 
+/* XPM */
+static char * core_xpm[] = {
+"16 16 4 1",
+"      c None",
+".     c #808080",
+"+     c #000000",
+"@     c #FFFFFF",
+"                ",
+"                ",
+"                ",
+"    .++++++.    ",
+"    +@+@@+@+    ",
+"    +@+@@+@+    ",
+"    +.+..+.+    ",
+"    +@@@@@@+    ",
+"    +@@@@@@+    ",
+"    +@@@@@@+    ",
+"    +@@@@@@+    ",
+"    +@@@@@@+    ",
+"    .++++++.    ",
+"                ",
+"                ",
+"                "};
+
 /* XPM */
 static char *eraser[] = {
 /* columns rows colors chars-per-pixel */
@@ -268,6 +292,7 @@ public:
     virtual ~InputDialogImpl() {}
 
 private:
+    Glib::RefPtr<Gdk::Pixbuf> corePix;
     Glib::RefPtr<Gdk::Pixbuf> penPix;
     Glib::RefPtr<Gdk::Pixbuf> mousePix;
     Glib::RefPtr<Gdk::Pixbuf> tipPix;
@@ -298,7 +323,8 @@ private:
     Gtk::Label devAxesCount;
     Gtk::ComboBoxText axesCombo;
     Gtk::ComboBoxText buttonCombo;
-    Gtk::ComboBoxText modeCombo;
+    Gtk::ComboBoxText linkCombo;
+    sigc::connection linkConnection;
     Gtk::Label keyVal;
     Gtk::Entry keyEntry;
     Gtk::Table devDetails;
@@ -313,7 +339,11 @@ private:
     void updateTestButtons( Glib::ustring const& key, gint hotButton );
     Glib::ustring getKeyFor( GdkDevice* device );
     bool eventSnoop(GdkEvent* event);
-    void foo();
+    void linkComboChanged();
+    void resyncToSelection();
+    void handleDeviceChange(const Glib::RefPtr<InputDevice>& device);
+    void updateDeviceButtons(const Glib::RefPtr<InputDevice>& device);
+    void updateDeviceLinks(const Glib::RefPtr<InputDevice>& device);
 };
 
 
@@ -328,6 +358,7 @@ InputDialog &InputDialog::getInstance()
 InputDialogImpl::InputDialogImpl() :
     InputDialog(),
 
+    corePix(Gdk::Pixbuf::create_from_xpm_data(core_xpm)),
     penPix(Gdk::Pixbuf::create_from_xpm_data(pen)),
     mousePix(Gdk::Pixbuf::create_from_xpm_data(mouse)),
     tipPix(Gdk::Pixbuf::create_from_xpm_data(tip)),
@@ -350,7 +381,7 @@ InputDialogImpl::InputDialogImpl() :
     detailScroller(),
     splitter(),
     split2(),
-    modeCombo(),
+    linkCombo(),
     devDetails(6, 2),
     confSplitter(),
     topHolder(),
@@ -407,18 +438,17 @@ InputDialogImpl::InputDialogImpl() :
 
     rowNum++;
 
-    lbl = Gtk::manage(new Gtk::Label("Mode:"));
+    lbl = Gtk::manage(new Gtk::Label("Link:"));
     devDetails.attach(*lbl, 0, 1, rowNum, rowNum+ 1,
                       ::Gtk::FILL,
                       ::Gtk::SHRINK);
 
-    modeCombo.append_text("Disabled");
-    modeCombo.append_text("Screen");
-    modeCombo.append_text("Window");
-    modeCombo.set_active_text("Disabled");
-    modeCombo.set_sensitive(false);
+    linkCombo.append_text("None");
+    linkCombo.set_active_text("None");
+    linkCombo.set_sensitive(false);
+    linkConnection = linkCombo.signal_changed().connect(sigc::mem_fun(*this, &InputDialogImpl::linkComboChanged));
 
-    devDetails.attach(modeCombo, 1, 2, rowNum, rowNum + 1,
+    devDetails.attach(linkCombo, 1, 2, rowNum, rowNum + 1,
                       ::Gtk::FILL,
                       ::Gtk::SHRINK);
     rowNum++;
@@ -453,6 +483,7 @@ InputDialogImpl::InputDialogImpl() :
 
     rowNum++;
 
+/*
     lbl = Gtk::manage(new Gtk::Label("Actual button count:"));
     devDetails.attach(*lbl, 0, 1, rowNum, rowNum+ 1,
                       ::Gtk::FILL,
@@ -462,6 +493,7 @@ InputDialogImpl::InputDialogImpl() :
                       ::Gtk::SHRINK);
 
     rowNum++;
+*/
 
     devDetails.attach(keyVal, 0, 2, rowNum, rowNum + 1,
                       ::Gtk::FILL,
@@ -508,14 +540,12 @@ InputDialogImpl::InputDialogImpl() :
 
     tree.set_enable_tree_lines();
     tree.set_headers_visible(false);
-    tree.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &InputDialogImpl::foo));
+    tree.get_selection()->signal_changed().connect(sigc::mem_fun(*this, &InputDialogImpl::resyncToSelection));
 
 
 
     std::list<InputDevice const *> devList = Inkscape::DeviceManager::getManager().getDevices();
     if ( !devList.empty() ) {
-        g_message("Found some");
-
         {
             GdkModifierType  defaultModMask = static_cast<GdkModifierType>(gtk_accelerator_get_default_mod_mask());
             gchar* name = gtk_accelerator_name(GDK_a, defaultModMask);
@@ -538,11 +568,15 @@ InputDialogImpl::InputDialogImpl() :
                 g_message("device: name[%s] source[0x%x] mode[0x%x] cursor[%s] axis count[%d] key count[%d]", dev->getName().c_str(), dev->getSource(), dev->getMode(),
                           dev->hasCursor() ? "Yes":"no", dev->getNumAxes(), dev->getNumKeys());
 
-                if ( dev->getSource() != Gdk::SOURCE_MOUSE ) {
+//                 if ( dev->getSource() != Gdk::SOURCE_MOUSE ) {
+                if ( dev ) {
                     deviceRow = *(store->append(childrow.children()));
                     deviceRow[cols.description] = dev->getName();
                     deviceRow[cols.device] = dev;
                     switch ( dev->getSource() ) {
+                        case GDK_SOURCE_MOUSE:
+                            deviceRow[cols.thumbnail] = corePix;
+                            break;
                         case GDK_SOURCE_PEN:
                             if (deviceRow[cols.description] == "pad") {
                                 deviceRow[cols.thumbnail] = sidebuttonsPix;
@@ -567,13 +601,60 @@ InputDialogImpl::InputDialogImpl() :
     } else {
         g_message("NO DEVICES FOUND");
     }
-
+    Inkscape::DeviceManager::getManager().signalDeviceChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::handleDeviceChange));
+    Inkscape::DeviceManager::getManager().signalButtonsChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::updateDeviceButtons));
+    Inkscape::DeviceManager::getManager().signalLinkChanged().connect(sigc::mem_fun(*this, &InputDialogImpl::updateDeviceLinks));
 
     tree.expand_all();
     show_all_children();
 }
 
-void InputDialogImpl::foo() {
+void InputDialogImpl::handleDeviceChange(const Glib::RefPtr<InputDevice>& /*device*/)
+{
+//     g_message("OUCH!!!! for %p  hits %s", &device, device->getId().c_str());
+}
+
+void InputDialogImpl::updateDeviceButtons(const Glib::RefPtr<InputDevice>& device)
+{
+    gint live = device->getLiveButtons();
+    std::set<guint> existing = buttonMap[device->getId()];
+    gint mask = 0x1;
+    for ( gint num = 0; num < 32; num++, mask <<= 1) {
+        if ( (mask & live) != 0 ) {
+            if ( existing.find(num) == existing.end() ) {
+                buttonMap[device->getId()].insert(num);
+            }
+        }
+    }
+    updateTestButtons(device->getId(), -1);
+}
+
+void InputDialogImpl::updateDeviceLinks(const Glib::RefPtr<InputDevice>& /*device*/)
+{
+//     g_message("Links!!!! for %p  hits %s  with link of %s", &device, device->getId().c_str(), device->getLink().c_str());
+}
+
+void InputDialogImpl::linkComboChanged() {
+    Glib::RefPtr<Gtk::TreeSelection> treeSel = tree.get_selection();
+    Gtk::TreeModel::iterator iter = treeSel->get_selected();
+    if (iter) {
+        Gtk::TreeModel::Row row = *iter;
+        Glib::ustring val = row[cols.description];
+        InputDevice const * dev = row[cols.device];
+        if ( dev ) {
+            Glib::ustring linkName = linkCombo.get_active_text();
+            std::list<InputDevice const *> devList = Inkscape::DeviceManager::getManager().getDevices();
+            for ( std::list<InputDevice const *>::const_iterator it = devList.begin(); it != devList.end(); ++it ) {
+                if ( linkName == (*it)->getName() ) {
+                    DeviceManager::getManager().setLinkedTo(dev->getId(), (*it)->getId());
+                    break;
+                }
+            }
+        }
+    }
+}
+
+void InputDialogImpl::resyncToSelection() {
     bool clear = true;
     Glib::RefPtr<Gtk::TreeSelection> treeSel = tree.get_selection();
     Gtk::TreeModel::iterator iter = treeSel->get_selected();
@@ -583,20 +664,28 @@ void InputDialogImpl::foo() {
         InputDevice const * dev = row[cols.device];
         if ( dev ) {
             devDetails.set_sensitive(true);
-            modeCombo.set_sensitive(true);
-            switch( dev->getMode() ) {
-                case GDK_MODE_DISABLED:
-                    modeCombo.set_active(0);
-                    break;
-                case GDK_MODE_SCREEN:
-                    modeCombo.set_active(1);
-                    break;
-                case GDK_MODE_WINDOW:
-                    modeCombo.set_active(2);
-                    break;
-                default:
-                    ;
+
+            linkConnection.block();
+            linkCombo.clear_items();
+            linkCombo.append_text("None");
+            linkCombo.set_active(0);
+            if ( dev->getSource() != Gdk::SOURCE_MOUSE ) {
+                Glib::ustring linked = dev->getLink();
+                std::list<InputDevice const *> devList = Inkscape::DeviceManager::getManager().getDevices();
+                for ( std::list<InputDevice const *>::const_iterator it = devList.begin(); it != devList.end(); ++it ) {
+                    if ( ((*it)->getSource() != Gdk::SOURCE_MOUSE) && ((*it) != dev) ) {
+                        linkCombo.append_text((*it)->getName().c_str());
+                        if ( (linked.length() > 0) && (linked == (*it)->getId()) ) {
+                            linkCombo.set_active_text((*it)->getName().c_str());
+                        }
+                    }
+                }
+                linkCombo.set_sensitive(true);
+            } else {
+                linkCombo.set_sensitive(false);
             }
+            linkConnection.unblock();
+
             clear = false;
             devName.set_label(row[cols.description]);
             setupValueAndCombo( dev->getNumAxes(), dev->getNumAxes(), devAxesCount, axesCombo);
@@ -703,6 +792,7 @@ bool InputDialogImpl::eventSnoop(GdkEvent* event)
                 if ( buttonMap[key].find(btnEvt->button) == buttonMap[key].end() ) {
                     g_message("New button found for %s = %d", key.c_str(), btnEvt->button);
                     buttonMap[key].insert(btnEvt->button);
+                    DeviceManager::getManager().addButton(key, btnEvt->button);
                 }
                 hotButton = modmod ? btnEvt->button : -1;
                 updateTestButtons(key, hotButton);
@@ -748,11 +838,10 @@ bool InputDialogImpl::eventSnoop(GdkEvent* event)
 
 
     if ( (lastSourceSeen != source) || (lastDevnameSeen != devName) ) {
-        g_message("FLIPPIES  %d => %d", lastSourceSeen, source);
         switch (source) {
             case GDK_SOURCE_MOUSE:
             {
-                testThumb.set(mousePix);
+                testThumb.set(corePix);
             }
             break;
             case GDK_SOURCE_CURSOR: