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}