1use event::{Event, AbstractEvent};
2
3use std::any::Any;
4
5use std::sync::mpsc::Sender;
6
7use std::mem;
8
9use minidom::Element;
10
11#[derive(Clone)]
12pub struct PluginProxyBinding {
13 sender: Sender<Element>,
14 dispatcher: Sender<AbstractEvent>,
15}
16
17impl PluginProxyBinding {
18 pub fn new(sender: Sender<Element>, dispatcher: Sender<AbstractEvent>) -> PluginProxyBinding {
19 PluginProxyBinding {
20 sender: sender,
21 dispatcher: dispatcher,
22 }
23 }
24}
25
26pub enum PluginProxy {
27 Unbound,
28 BoundTo(PluginProxyBinding),
29}
30
31impl PluginProxy {
32 pub fn new() -> PluginProxy {
33 PluginProxy::Unbound
34 }
35
36 pub fn bind(&mut self, inner: PluginProxyBinding) {
37 if let PluginProxy::BoundTo(_) = *self {
38 panic!("trying to bind an already bound plugin proxy!");
39 }
40 mem::replace(self, PluginProxy::BoundTo(inner));
41 }
42
43 fn with_binding<R, F: FnOnce(&PluginProxyBinding) -> R>(&self, f: F) -> R {
44 match *self {
45 PluginProxy::Unbound => {
46 panic!("trying to use an unbound plugin proxy!");
47 },
48 PluginProxy::BoundTo(ref binding) => {
49 f(binding)
50 },
51 }
52 }
53
54 pub fn dispatch<E: Event>(&self, event: E) {
55 self.with_binding(move |binding| {
56 binding.dispatcher.send(AbstractEvent::new(event))
57 .unwrap(); // TODO: may want to return the error
58 });
59 }
60
61 pub fn send(&self, elem: Element) {
62 self.with_binding(move |binding| {
63 binding.sender.send(elem).unwrap(); // TODO: as above, may want to return the error
64 });
65 }
66}
67
68#[derive(Copy, Clone, Debug, PartialEq, Eq)]
69pub enum PluginReturn {
70 Continue,
71 Unload,
72}
73
74pub trait Plugin: Any + PluginAny {
75 fn get_proxy(&mut self) -> &mut PluginProxy;
76 fn handle(&mut self, _elem: &Element) -> PluginReturn { PluginReturn::Continue }
77
78 fn bind(&mut self, inner: PluginProxyBinding) {
79 self.get_proxy().bind(inner);
80 }
81}
82
83pub trait PluginAny {
84 fn as_any(&self) -> &Any;
85}
86
87impl<T: Any + Sized> PluginAny for T {
88 fn as_any(&self) -> &Any { self }
89}