master chld/haikuprg / src / Drawkun.cpp
  1#include <Application.h>
  2#include <Window.h>
  3#include <View.h>
  4
  5#include <Button.h>
  6#include <Message.h>
  7
  8#include <vector>
  9#include <iostream>
 10#include <random>
 11
 12class Dot:public BView
 13{
 14public: Dot(BRect f):BView(f, "dot", B_FOLLOW_ALL, B_WILL_DRAW | B_PULSE_NEEDED),
 15		     rd(),
 16		     gen(std::random_device{}()),
 17		     distrib(-2,2){}
 18  void Draw(BRect r)
 19  {
 20    for(size_t s=0; s+1<fP.size(); ++s)
 21      {
 22	if (fP[s] == BPoint(-1, -1) || fP[s+1] == BPoint(-1 ,-1)) continue;
 23	int pr=distrib(gen);
 24	
 25	if(!fC[s])
 26	  SetHighColor(0,0,0);
 27	else
 28	  SetHighColor(255,255,255);
 29
 30	StrokeLine(BPoint(fP[s].x+(pr), fP[s].y), BPoint(fP[s+1].x, fP[s+1].y+(pr)));
 31      }
 32  }
 33
 34  void MouseMoved(BPoint w, uint32 c, const BMessage *m)
 35  {
 36    if (draw)
 37      {
 38	fP.push_back(w);
 39	fC.push_back(black);
 40	Invalidate();
 41      }
 42  }
 43
 44  void MouseDown(BPoint w)
 45  {
 46    draw=true;
 47  }
 48
 49  void MouseUp(BPoint w)
 50  {
 51    draw=false;
 52
 53    /* prevent up connecting w down */
 54    fP.push_back(BPoint(-1, -1));
 55    fC.push_back(black);
 56  }
 57
 58  void ClearAll()
 59  {
 60    fP.clear();
 61    fC.clear();
 62    Invalidate();
 63  }
 64
 65  void Pulse()
 66  {
 67    Invalidate();
 68  }
 69
 70  void Undo()
 71  {
 72    if (!fP.empty()){
 73      for (int i=0; i<10; ++i){
 74	fP.pop_back();
 75	fC.pop_back();
 76      }
 77    }
 78    fP.push_back(BPoint(-1, -1));
 79    Invalidate();
 80  }
 81
 82private:
 83  std::vector<BPoint> fP;
 84  std::vector<bool> fC;
 85  bool draw=false;
 86
 87  std::mt19937 gen;
 88  std::random_device rd;
 89  std::uniform_int_distribution<int> distrib;
 90public:
 91  bool black=false;
 92};
 93
 94class Win:public BWindow
 95{
 96public:Win(BRect f):
 97  BWindow(f, "Drawkun", B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE){
 98  dot = new Dot(BRect(0, 30, f.Width(), f.Height()));
 99  AddChild(dot);
100  SetPulseRate(100000);
101  dot->SetHighColor(0,0,0);
102  dot->SetPenSize(z);
103  dot->SetLineMode(B_ROUND_CAP, B_ROUND_JOIN);
104
105  BButton *cButton = new BButton(BRect(10, 10, 100, 20), "clear", "Clear", new BMessage('c'));
106  AddChild(cButton);
107
108  BButton *eButton = new BButton(BRect(110, 10, 200, 20), "toggle", "Toggle", new BMessage('e'));
109  AddChild(eButton);
110
111  BButton *uButton = new BButton(BRect(210, 10, 300, 20), "undo", "Undo", new BMessage('u'));
112  AddChild(uButton);
113
114  BButton *pButton = new BButton(BRect(310, 10, 330, 20), "add", "+", new BMessage('a'));
115  AddChild(pButton);
116
117  BButton *mButton = new BButton(BRect(340, 10, 360, 20), "min", "-", new BMessage('m'));
118  AddChild(mButton);
119}
120  
121  void MessageReceived(BMessage *m)
122  {
123    switch(m->what){
124    case 'c':
125      dot->ClearAll();
126      break;
127    case 'e':
128      dot->black=!dot->black;
129      break;
130    case 'u':
131      dot->Undo();
132      break;
133    case 'a':
134      z+=3;
135      dot->SetPenSize(z);
136      break;
137    case 'm':
138      if(z==0) break;
139      z-=3;
140      dot->SetPenSize(z);
141      break;
142    default:
143      BWindow::MessageReceived(m);
144    }
145  }
146
147private:
148  Dot *dot;
149  bool e=false;
150  int32 z=0;
151};
152
153class App:public BApplication
154{
155public:App():BApplication("application/x-vnd.example.blank")
156  {
157    BRect rect(100,100,640,480);
158    Win *w = new Win(rect);
159    w->Show();
160  }
161};
162
163int main(void)
164{
165  App a;
166  a.Run();
167  return 0;
168}