D Paste by downs
Description: test27.d; full
Hide line numbers

Create new paste
Post a reply
View replies

Paste:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
module test27;

import tools.base;

struct QdEvent {
  enum Type {
    MouseMoved, MouseClicked, MousePushed, MouseReleased
  }
  Type type;
  pt pos;
  int button; // 0 unless appropriate
}

alias Stuple!() Nothing; // sadly, void is a keyword
Stuple!() nothing;

Nothing[void delegate(QdEvent)] listeners;

template toDelegate(T...) {
  typeof((T t) { C c; return c(t); }) toDelegate(C)(C callable) {
    struct Wrapper {
      C callable;
      typeof(function{ T t; return callable(t); }()) call(T t) {
        return callable(t);
      }
    }
    auto res = new Wrapper;
    res.callable = callable;
    return &res.call;
  }
}

void registerCallback(C)(C callable) {
  listeners[toDelegate!(QdEvent)(callable)] = nothing;
}

private void dispatchEvent(QdEvent q) {
  foreach (key, bogus; listeners) key(q);
}

// void events(void delegate(ushort, bool) key=null, void delegate(int, int, ubyte, int) mouse=null, void delegate() quit=null)
void checkEvents() {
  events((ushort u) { }, (int x, int y, ubyte button, int dir) {
    switch (dir) {
      case 0: dispatchEvent = QdEvent(QdEvent.Type.MouseMoved, pt(x, y), button); break;
      case 1: dispatchEvent = QdEvent(QdEvent.Type.MousePushed, pt(x, y), button); break;
      case -1: dispatchEvent = QdEvent(QdEvent.Type.MouseReleased, pt(x, y), button); break;
    }
  }, { throw new Exception("Quit"); });
}

struct CondSliceFunctorPre(T) {
  T sup;
  CondSliceFunctor!(T, U, V) opSlice(U, V)(U u, V v) {
    CondSliceFunctor!(T, U, V) res;
    res.sup = sup; res.u = u; res.v = v;
    return res;
  }
}

CondSliceFunctorPre!(T) condslice(T)(T t) {
  return CondSliceFunctorPre!(T)(t);
}

template isCallable(T, U) {
  static if (is(typeof({ T foo; U param; foo(param); }))) const bool isCallable = true;
  else const bool isCallable = true;
}

struct CondSliceFunctor(T, U, V) {
  T sup; U u; V v;
  bool inRange;
  void opCall(W)(W w) {
    logln("cond slice with ", w, ", inRange ", inRange, ", and ", u(w));
    static assert(isCallable!(T, W), "Cond-Slice problem: can't call "~T.stringof~" with "~W.stringof~"! ");
    static assert(isCallable!(U, W), "Cond-Slice problem: can't call start cond "~U.stringof~" with "~W.stringof~"! ");
    static assert(isCallable!(V, W), "Cond-Slice problem: can't call end cond "~V.stringof~" with "~W.stringof~"! ");
    if (inRange) {
      sup(w);
      if (v(w)) { inRange = false; }
    } else if (u(w)) { inRange = true; sup(w); }
  }
}

import qd;
void main() {
  screen(640, 480);
  pt pos;
  alias ex!("v -> f -> f.type == v") TypeCheck;
  alias ex!("a, b -> x -> a(x) && b(x)") And;
  alias ex!("a -> b -> b.pos in a()") LazyIn;
  registerCallback(
    condslice((QdEvent qe) {
      if (qe.type == QdEvent.Type.MouseMoved) { pos = qe.pos; }
    })[
      And(TypeCheck(QdEvent.Type.MousePushed), LazyIn({ return Area(pos - pt(10), pt(20)); }))
      .. TypeCheck(QdEvent.Type.MouseReleased)
    ]
  );
  while (true) {
    cls;
    circle(pos.x, pos.y, 10);
    flip; checkEvents;
  }
}

Replies:
Reply by tiZPxADGdaOZoWO
That's the best asnwer of all time! JMHO

    (some replies deleted)