1// main.cpp
2
3#include <stdio.h>
4
5#include "Application.h"
6#include "Message.h"
7#include "Button.h"
8#include "View.h"
9#include "Window.h"
10
11#define MSG_COPY_BITS 'cbts'
12
13class TestView : public BView {
14
15	enum {
16		TRACKING_NONE,
17		TRACKING_SOURCE,
18		TRACKING_DEST
19	};
20
21 public:
22					TestView(BRect frame, const char* name,
23							  uint32 resizeFlags, uint32 flags)
24						: BView(frame, name, resizeFlags, flags),
25						  fTracking(TRACKING_NONE),
26						  fCopyBitsJustCalled(false)
27					{
28						fSourceRect.Set(frame.left, frame.top,
29									    (frame.left + frame.right) / 2,
30									    frame.bottom);
31						fDestRect.Set((frame.left + frame.right) / 2,
32									  frame.top,
33									  frame.right, frame.bottom);
34						fSourceRect.InsetBy(10.0, 10.0);
35						fDestRect.InsetBy(10.0, 10.0);
36
37						SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
38						SetLowUIColor(ViewUIColor());
39					}
40
41	virtual	void	MessageReceived(BMessage* message);
42
43	virtual	void	Draw(BRect updateRect);
44
45	virtual	void	MouseDown(BPoint where);
46	virtual	void	MouseUp(BPoint where);
47	virtual	void	MouseMoved(BPoint where, uint32 transit,
48							   const BMessage* dragMessage);
49
50 private:
51			void	_TrackMouse(BPoint where);
52
53			BRect	fSourceRect;
54			BRect	fDestRect;
55
56			uint32	fTracking;
57
58			bool	fCopyBitsJustCalled;
59};
60
61// MessageReceived
62void
63TestView::MessageReceived(BMessage* message)
64{
65	if (message->what == MSG_COPY_BITS) {
66		printf("MSG_COPY_BITS\n");
67		fSourceRect.PrintToStream();
68		fDestRect.PrintToStream();
69		CopyBits(fSourceRect, fDestRect);
70		fCopyBitsJustCalled = true;
71	} else
72		BView::MessageReceived(message);
73}
74
75// Draw
76void
77TestView::Draw(BRect updateRect)
78{
79	if (fCopyBitsJustCalled) {
80		printf("TestView::Draw(%.1f, %.1f, %.1f, %.1f) after CopyBits()\n",
81			   updateRect.left, updateRect.top, updateRect.right, updateRect.bottom);
82		fCopyBitsJustCalled = false;
83	}
84
85	// background
86//	SetHighColor(ui_color(B_PANEL_BACKGROUND_COLOR));
87//	FillRect(updateRect);
88
89	BRect r(Bounds());
90
91	// draw some pattern with lines
92	float width = r.Width();
93	float height = r.Height();
94	int32 lineCount = 20;
95	SetPenSize(2.0);
96	for (int32 i = 0; i < lineCount; i++) {
97		SetHighColor(255, (255 / lineCount) * i, 255 - (255 / lineCount) * i);
98		StrokeLine(BPoint(r.left + (width / lineCount) * i, r.top),
99				   BPoint(r.left, r.top + (height / lineCount) * i));
100		StrokeLine(BPoint(r.right - (width / lineCount) * i, r.bottom),
101				   BPoint(r.right, r.bottom - (height / lineCount) * i));
102	}
103	StrokeLine(BPoint(r.left, r.bottom), BPoint(r.right, r.top));
104
105	// source and dest rect
106	SetPenSize(1.0);
107
108	SetHighColor(0, 255, 0, 255);
109	StrokeRect(fSourceRect);
110
111	SetHighColor(0, 0, 255, 255);
112	StrokeRect(fDestRect);
113
114	// text
115	SetHighColor(128, 0, 50, 255);
116
117	const char* message = "Left-Click and drag";
118	width = StringWidth(message);
119	BPoint p(r.left + r.Width() / 2.0 - width / 2.0,
120			 r.top + r.Height() / 2.0 - 50.0);
121
122	DrawString(message, p);
123
124	message = "to set source rect!";
125	width = StringWidth(message);
126	p.x = r.left + r.Width() / 2.0 - width / 2.0;
127	p.y += 20;
128
129	DrawString(message, p);
130
131	message = "Right-Click and drag";
132	width = StringWidth(message);
133	p.x = r.left + r.Width() / 2.0 - width / 2.0;
134	p.y += 30.0;
135
136	DrawString(message, p);
137
138	message = "to set destination rect!";
139	width = StringWidth(message);
140	p.x = r.left + r.Width() / 2.0 - width / 2.0;
141	p.y += 20;
142
143	DrawString(message, p);
144}
145
146// MouseDown
147void
148TestView::MouseDown(BPoint where)
149{
150	BMessage* message = Window()->CurrentMessage();
151	uint32 buttons;
152	if (message && message->FindInt32("buttons", (int32*)&buttons) >= B_OK) {
153		if (buttons & B_PRIMARY_MOUSE_BUTTON) {
154			fTracking = TRACKING_SOURCE;
155			fSourceRect.left = where.x;
156			fSourceRect.top = where.y;
157		}
158		if (buttons & B_SECONDARY_MOUSE_BUTTON) {
159			fTracking = TRACKING_DEST;
160			fDestRect.left = where.x;
161			fDestRect.top = where.y;
162		}
163		Invalidate();
164		_TrackMouse(where);
165	}
166}
167
168// MouseUp
169void
170TestView::MouseUp(BPoint where)
171{
172	fTracking = TRACKING_NONE;
173}
174
175// MouseMoved
176void
177TestView::MouseMoved(BPoint where, uint32 transit,
178					 const BMessage* dragMessage)
179{
180	if (fTracking > TRACKING_NONE) {
181		_TrackMouse(where);
182	}
183}
184
185float
186min4(float a, float b, float c, float d)
187{
188	return min_c(a, min_c(b, min_c(c, d)));
189}
190
191float
192max4(float a, float b, float c, float d)
193{
194	return max_c(a, max_c(b, max_c(c, d)));
195}
196
197// _TrackMouse
198void
199TestView::_TrackMouse(BPoint where)
200{
201	BRect before;
202	BRect after;
203	bool invalidate = false;
204	switch (fTracking) {
205		case TRACKING_SOURCE:
206			before = fSourceRect;
207			fSourceRect.right = where.x;
208			fSourceRect.bottom = where.y;
209			after = fSourceRect;
210			invalidate = true;
211			break;
212		case TRACKING_DEST:
213			before = fDestRect;
214			fDestRect.right = where.x;
215			fDestRect.bottom = where.y;
216			after = fDestRect;
217			invalidate = true;
218			break;
219	}
220	if (invalidate) {
221		BRect dirty(min4(before.left, before.right, after.left, after.right),
222					min4(before.top, before.bottom, after.top, after.bottom),
223					max4(before.left, before.right, after.left, after.right),
224					max4(before.top, before.bottom, after.top, after.bottom));
225		Invalidate(dirty);
226	}
227}
228
229
230// show_window
231void
232show_window(BRect frame, const char* name)
233{
234	BWindow* window = new BWindow(frame, name,
235								  B_TITLED_WINDOW,
236								  B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE);
237
238	BView* view = new TestView(window->Bounds(), "test", B_FOLLOW_ALL,
239							   B_WILL_DRAW/* | B_FULL_UPDATE_ON_RESIZE*/);
240
241	window->AddChild(view);
242	BRect b(0.0, 0.0, 50.0, 15.0);
243	b.OffsetTo(5.0, view->Bounds().bottom - (b.Height() + 15.0));
244	BButton* control = new BButton(b, "button", "Copy", new BMessage(MSG_COPY_BITS));
245	view->AddChild(control);
246	control->SetTarget(view);
247
248	// test CopyBits() on top of children
249	b = BRect(80, 130, 130, 160);
250	BView* child = new BView(b, "some child", B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM, 0);
251	child->SetViewColor(255, 0, 0);
252	view->AddChild(child);
253
254	b = BRect(136, 127, 158, 140);
255	child = new BView(b, "some other child", B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM, 0);
256	child->SetViewColor(255, 255, 0);
257	view->AddChild(child);
258
259	window->Show();
260}
261
262// main
263int
264main(int argc, char** argv)
265{
266	BApplication* app = new BApplication("application/x.vnd-Haiku.CopyBits");
267
268	BRect frame(50.0, 50.0, 300.0, 250.0);
269	show_window(frame, "CopyBits Test");
270
271	app->Run();
272
273	delete app;
274	return 0;
275}
276