xref: /haiku/src/tests/servers/app/bitmap_drawing/main.cpp (revision 8359877941f34059cc2cbad37bb1002601c22403)
1 // main.cpp
2 
3 #include <stdio.h>
4 #include <string.h>
5 
6 #include "Application.h"
7 #include "Bitmap.h"
8 #include "Button.h"
9 #include "Message.h"
10 #include "View.h"
11 #include "Window.h"
12 
13 #include "bitmap.h"
14 
15 enum {
16 	MSG_RESET	= 'rset',
17 };
18 
19 class TestView : public BView {
20 
21  public:
22 					TestView(BRect frame, const char* name,
23 							  uint32 resizeFlags, uint32 flags)
24 						: BView(frame, name, resizeFlags, flags),
25 //						  fBitmap(new BBitmap(BRect(0, 0, kBitmapWidth - 1, kBitmapHeight -1),
26 //						  					  0, kBitmapFormat)),
27 						  fBitmap(new BBitmap(BRect(0, 0, 32 - 1, 8 - 1),
28 						  					  0, B_CMAP8)),
29 //						  fBitmap(new BBitmap(BRect(0, 0, 32 - 1, 8 - 1),
30 //						  					  0, B_GRAY8)),
31 						  fBitmapRect(),
32 						  fTracking(TRACKING_NONE),
33 						  fLastMousePos(-1.0, -1.0)
34 					{
35 						SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
36 						SetLowColor(ViewColor());
37 //						uint32 size = min_c((uint32)fBitmap->BitsLength(), sizeof(kBitmapBits));
38 //						memcpy(fBitmap->Bits(), kBitmapBits, size);
39 						uint8* bits = (uint8*)fBitmap->Bits();
40 						uint32 width = fBitmap->Bounds().IntegerWidth() + 1;
41 						uint32 height = fBitmap->Bounds().IntegerHeight() + 1;
42 						uint32 bpr = fBitmap->BytesPerRow();
43 printf("width: %ld, height: %ld, bpr: %ld\n", width, height, bpr);
44 						int32 index = 0;
45 						for (uint32 y = 0; y < height; y++) {
46 							uint8* h = bits;
47 							for (uint32 x = 0; x < width; x++) {
48 								*h = index++;
49 								h++;
50 							}
51 							bits += bpr;
52 						}
53 BRect a(0.0, 10.0, 20.0, 10.0);
54 BRect b(0.0, 10.0, 10.0, 30.0);
55 printf("Intersects: %d\n", a.Intersects(b));
56 						_ResetRect();
57 					}
58 
59 	virtual	void	MessageReceived(BMessage* message);
60 
61 	virtual	void	Draw(BRect updateRect);
62 
63 	virtual	void	MouseDown(BPoint where);
64 	virtual	void	MouseUp(BPoint where);
65 	virtual	void	MouseMoved(BPoint where, uint32 transit,
66 							   const BMessage* dragMessage);
67 
68  private:
69 			void	_ResetRect();
70 			void	_InvalidateBitmapRect(BRect r);
71 			void	_DrawCross(BPoint where, rgb_color c);
72 
73 	BBitmap*		fBitmap;
74 	BRect			fBitmapRect;
75 
76 	enum {
77 		TRACKING_NONE = 0,
78 
79 		TRACKING_LEFT,
80 		TRACKING_RIGHT,
81 		TRACKING_TOP,
82 		TRACKING_BOTTOM,
83 
84 		TRACKING_LEFT_TOP,
85 		TRACKING_RIGHT_TOP,
86 		TRACKING_LEFT_BOTTOM,
87 		TRACKING_RIGHT_BOTTOM,
88 
89 		TRACKING_ALL
90 	};
91 
92 	uint32			fTracking;
93 	BPoint			fLastMousePos;
94 };
95 
96 // MessageReceived
97 void
98 TestView::MessageReceived(BMessage* message)
99 {
100 	if (message->what == MSG_RESET) {
101 		BRect old = fBitmapRect;
102 		_ResetRect();
103 		_InvalidateBitmapRect(old | fBitmapRect);
104 	} else
105 		BView::MessageReceived(message);
106 }
107 
108 // Draw
109 void
110 TestView::Draw(BRect updateRect)
111 {
112 	SetDrawingMode(B_OP_COPY);
113 	DrawBitmap(fBitmap, fBitmap->Bounds(), fBitmapRect);
114 
115 	// indicate the frame to see any errors in the drawing code
116 	rgb_color red = (rgb_color){ 255, 0, 0, 255 };
117 	_DrawCross(fBitmapRect.LeftTop() + BPoint(-1.0, -1.0), red);
118 	_DrawCross(fBitmapRect.RightTop() + BPoint(1.0, -1.0), red);
119 	_DrawCross(fBitmapRect.LeftBottom() + BPoint(-1.0, 1.0), red);
120 	_DrawCross(fBitmapRect.RightBottom() + BPoint(1.0, 1.0), red);
121 
122 	// text
123 	SetDrawingMode(B_OP_ALPHA);
124 	const char* message = "Click and drag to move and resize the bitmap!";
125 	BPoint textPos(20.0, 30.0);
126 	SetHighColor(255, 255, 255, 180);
127 	DrawString(message, textPos);
128 	SetHighColor(0, 0, 0, 180);
129 	DrawString(message, textPos + BPoint(-1.0, -1.0));
130 }
131 
132 bool
133 hit_test(BPoint where, BPoint p)
134 {
135 	BRect r(p, p);
136 	r.InsetBy(-5.0, -5.0);
137 	return r.Contains(where);
138 }
139 
140 bool
141 hit_test(BPoint where, BPoint a, BPoint b)
142 {
143 	BRect r(a, b);
144 	if (a.x == b.x)
145 		r.InsetBy(-3.0, 0.0);
146 	else
147 		r.InsetBy(0.0, -3.0);
148 	return r.Contains(where);
149 }
150 
151 // MouseDown
152 void
153 TestView::MouseDown(BPoint where)
154 {
155 	fTracking = TRACKING_NONE;
156 
157 	// check if we hit a corner
158 	if (hit_test(where, fBitmapRect.LeftTop()))
159 		fTracking = TRACKING_LEFT_TOP;
160 	else if (hit_test(where, fBitmapRect.RightTop()))
161 		fTracking = TRACKING_RIGHT_TOP;
162 	else if (hit_test(where, fBitmapRect.LeftBottom()))
163 		fTracking = TRACKING_LEFT_BOTTOM;
164 	else if (hit_test(where, fBitmapRect.RightBottom()))
165 		fTracking = TRACKING_RIGHT_BOTTOM;
166 	// check if we hit a side
167 	else if (hit_test(where, fBitmapRect.LeftTop(), fBitmapRect.RightTop()))
168 		fTracking = TRACKING_TOP;
169 	else if (hit_test(where, fBitmapRect.LeftTop(), fBitmapRect.LeftBottom()))
170 		fTracking = TRACKING_LEFT;
171 	else if (hit_test(where, fBitmapRect.RightTop(), fBitmapRect.RightBottom()))
172 		fTracking = TRACKING_RIGHT;
173 	else if (hit_test(where, fBitmapRect.LeftBottom(), fBitmapRect.RightBottom()))
174 		fTracking = TRACKING_BOTTOM;
175 	// check if we hit inside the rect
176 	else if (fBitmapRect.Contains(where))
177 		fTracking = TRACKING_ALL;
178 
179 	fLastMousePos = where;
180 }
181 
182 // MouseUp
183 void
184 TestView::MouseUp(BPoint where)
185 {
186 	fTracking = TRACKING_NONE;
187 }
188 
189 // MouseMoved
190 void
191 TestView::MouseMoved(BPoint where, uint32 transit,
192 					 const BMessage* dragMessage)
193 {
194 	if (fTracking > TRACKING_NONE) {
195 		BRect old = fBitmapRect;
196 		BPoint offset = where - fLastMousePos;
197 		switch (fTracking) {
198 			case TRACKING_LEFT_TOP:
199 				fBitmapRect.Set(fBitmapRect.left + offset.x,
200 								fBitmapRect.top + offset.y,
201 								fBitmapRect.right,
202 								fBitmapRect.bottom);
203 				break;
204 			case TRACKING_RIGHT_BOTTOM:
205 				fBitmapRect.Set(fBitmapRect.left,
206 								fBitmapRect.top,
207 								fBitmapRect.right + offset.x,
208 								fBitmapRect.bottom + offset.y);
209 				break;
210 			case TRACKING_LEFT_BOTTOM:
211 				fBitmapRect.Set(fBitmapRect.left + offset.x,
212 								fBitmapRect.top,
213 								fBitmapRect.right,
214 								fBitmapRect.bottom + offset.y);
215 				break;
216 			case TRACKING_RIGHT_TOP:
217 				fBitmapRect.Set(fBitmapRect.left,
218 								fBitmapRect.top + offset.y,
219 								fBitmapRect.right + offset.x,
220 								fBitmapRect.bottom);
221 				break;
222 			case TRACKING_LEFT:
223 				fBitmapRect.Set(fBitmapRect.left + offset.x,
224 								fBitmapRect.top,
225 								fBitmapRect.right,
226 								fBitmapRect.bottom);
227 				break;
228 			case TRACKING_TOP:
229 				fBitmapRect.Set(fBitmapRect.left,
230 								fBitmapRect.top + offset.y,
231 								fBitmapRect.right,
232 								fBitmapRect.bottom);
233 				break;
234 			case TRACKING_RIGHT:
235 				fBitmapRect.Set(fBitmapRect.left,
236 								fBitmapRect.top,
237 								fBitmapRect.right + offset.x,
238 								fBitmapRect.bottom);
239 				break;
240 			case TRACKING_BOTTOM:
241 				fBitmapRect.Set(fBitmapRect.left,
242 								fBitmapRect.top,
243 								fBitmapRect.right,
244 								fBitmapRect.bottom + offset.y);
245 				break;
246 			case TRACKING_ALL:
247 			default:
248 				fBitmapRect.OffsetBy(offset);
249 				break;
250 		}
251 		fLastMousePos = where;
252 		if (old != fBitmapRect)
253 			_InvalidateBitmapRect(old | fBitmapRect);
254 	}
255 }
256 
257 // _ResetRect
258 void
259 TestView::_ResetRect()
260 {
261 	fBitmapRect = fBitmap->Bounds();
262 	fBitmapRect.OffsetBy(floorf((Bounds().Width() - fBitmapRect.Width()) / 2.0 + 0.5),
263 						 floorf((Bounds().Height() - fBitmapRect.Height()) / 2.0 + 0.5));
264 }
265 
266 // _InvalidateBitmapRect
267 void
268 TestView::_InvalidateBitmapRect(BRect r)
269 {
270 	r.InsetBy(-4.0, -4.0);
271 	Invalidate(r);
272 }
273 
274 // _DrawCross
275 void
276 TestView::_DrawCross(BPoint where, rgb_color c)
277 {
278 	BeginLineArray(4);
279 		AddLine(BPoint(where.x, where.y - 3),
280 				BPoint(where.x, where.y - 1), c);
281 		AddLine(BPoint(where.x, where.y + 1),
282 				BPoint(where.x, where.y + 3), c);
283 		AddLine(BPoint(where.x - 3, where.y),
284 				BPoint(where.x - 1, where.y), c);
285 		AddLine(BPoint(where.x + 1, where.y),
286 				BPoint(where.x + 3, where.y), c);
287 	EndLineArray();
288 }
289 
290 // show_window
291 void
292 show_window(BRect frame, const char* name)
293 {
294 	BWindow* window = new BWindow(frame, name,
295 								  B_TITLED_WINDOW,
296 								  B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE);
297 
298 	BView* view = new TestView(window->Bounds(), "test", B_FOLLOW_ALL,
299 							   B_WILL_DRAW/* | B_FULL_UPDATE_ON_RESIZE*/);
300 
301 	window->AddChild(view);
302 	BRect b(0.0, 0.0, 60.0, 15.0);
303 	b.OffsetTo(5.0, view->Bounds().bottom - (b.Height() + 15.0));
304 	BButton* control = new BButton(b, "button", "Reset", new BMessage(MSG_RESET),
305 								   B_FOLLOW_LEFT | B_FOLLOW_BOTTOM);
306 	view->AddChild(control);
307 	control->SetTarget(view);
308 
309 	window->Show();
310 }
311 
312 // main
313 int
314 main(int argc, char** argv)
315 {
316 	BApplication* app = new BApplication("application/x.vnd-Haiku.BitmapDrawing");
317 
318 	BRect frame(50.0, 50.0, 400.0, 250.0);
319 	show_window(frame, "Bitmap Drawing");
320 
321 	app->Run();
322 
323 	delete app;
324 	return 0;
325 }
326