]> git.tdb.fi Git - libs/gui.git/blob - source/input/bindings.cpp
291c8f152584b552acbf7228053fcb1ed765ee6b
[libs/gui.git] / source / input / bindings.cpp
1 #include "bindings.h"
2 #include <algorithm>
3 #include <msp/strings/format.h>
4 #include "controlscheme.h"
5
6 using namespace std;
7
8 namespace Msp {
9 namespace Input {
10
11 vector<Device *> Bindings::resolve_devices(Device &dev) const
12 {
13         vector<Device *> resolved_devs;
14         resolved_devs.reserve(devices.size());
15         for(const DeviceRef &d: devices)
16         {
17                 if(d.type!=UNSPECIFIED)
18                         resolved_devs.push_back(dev.find_subdevice(d.type));
19                 else if(!d.name.empty())
20                         resolved_devs.push_back(dev.find_subdevice(d.name));
21                 else
22                         resolved_devs.push_back(nullptr);
23         }
24         return resolved_devs;
25 }
26
27 bool Bindings::is_compatible(Device &dev) const
28 {
29         vector<Device *> resolved_devs = resolve_devices(dev);
30         return all_of(resolved_devs.begin(), resolved_devs.end(), [](Device *d) -> bool { return d; });
31 }
32
33 bool Bindings::apply_to(ControlScheme &control_scheme, Device &dev)
34 {
35         vector<Device *> resolved_devs = resolve_devices(dev);
36         bool applied = false;
37         for(const Binding &b: bindings)
38         {
39                 Control *ctrl = control_scheme.find(b.control);
40                 Device *bdev = (b.device<resolved_devs.size() ? resolved_devs[b.device] : nullptr);
41                 if(ctrl && bdev)
42                 {
43                         ctrl->set_source(*bdev, b.type, b.index);
44                         applied = true;
45                 }
46         }
47
48         return applied;
49 }
50
51
52 DataFile::Loader::ActionMap Bindings::Loader::shared_actions;
53
54 Bindings::Loader::Loader(Bindings &b):
55         ObjectLoader<Bindings>(b)
56 {
57         set_actions(shared_actions);
58 }
59
60 void Bindings::Loader::init_actions()
61 {
62         add("binding", &Loader::binding);
63         add("device", &Loader::device_type);
64         add("device", &Loader::device_name);
65 }
66
67 void Bindings::Loader::binding(const string &c)
68 {
69         Binding bind;
70         bind.control = c;
71         load_sub(bind);
72         obj.bindings.push_back(bind);
73 }
74
75 void Bindings::Loader::device_type(DeviceType t)
76 {
77         DeviceRef dev;
78         dev.type = t;
79         obj.devices.push_back(dev);
80 }
81
82 void Bindings::Loader::device_name(const string &n)
83 {
84         DeviceRef dev;
85         dev.name = n;
86         obj.devices.push_back(dev);
87 }
88
89
90 DataFile::Loader::ActionMap Bindings::Binding::Loader::shared_actions;
91
92 Bindings::Binding::Loader::Loader(Binding &b):
93         ObjectLoader<Binding>(b)
94 {
95         set_actions(shared_actions);
96 }
97
98 void Bindings::Binding::Loader::init_actions()
99 {
100         add("axis", &Loader::axis);
101         add("button", &Loader::button);
102         add("device", &Binding::device);
103         add("key", &Loader::key);
104         add("mouse_axis", &Loader::mouse_axis);
105         add("mouse_button", &Loader::mouse_button);
106 }
107
108 void Bindings::Binding::Loader::axis(unsigned a, AxisSide s)
109 {
110         obj.type = (s==NEGATIVE ? AXIS_NEG : AXIS_POS);
111         obj.index = a;
112 }
113
114 void Bindings::Binding::Loader::button(unsigned b)
115 {
116         obj.type = BUTTON;
117         obj.index = b;
118 }
119
120
121 void operator>>(const LexicalConverter &conv, Bindings::AxisSide &side)
122 {
123         if(conv.get()=="POSITIVE")
124                 side = Bindings::POSITIVE;
125         else if(conv.get()=="NEGATIVE")
126                 side = Bindings::NEGATIVE;
127         else
128                 throw lexical_error(format("conversion of '%s' to AxisSide", conv.get()));
129 }
130
131 void operator<<(LexicalConverter &conv, Bindings::AxisSide side)
132 {
133         switch(side)
134         {
135         case Bindings::POSITIVE: conv.result("POSITIVE"); break;
136         case Bindings::NEGATIVE: conv.result("NEGATIVE"); break;
137         default: conv.result(format("AxisSide(%#x)", static_cast<int>(side)));
138         }
139 }
140
141 } // namespace Input
142 } // namespace Msp;