1/*
2 * Copyright 2014 Stephan Aßmus <superstippi@gmx.de>
3 * All rights reserved. Distributed under the terms of the MIT license.
4 */
5
6
7#include <stdio.h>
8#include <string.h>
9
10#include <Application.h>
11#include <Message.h>
12#include <Picture.h>
13#include <LayoutBuilder.h>
14#include <List.h>
15#include <PopUpMenu.h>
16#include <ScrollView.h>
17#include <String.h>
18#include <StringView.h>
19#include <View.h>
20#include <Window.h>
21
22
23static const char* kAppSignature = "application/x.vnd-Haiku.ClipToPicture";
24
25
26class TestRenderer {
27public:
28	virtual	void				Draw(BView* view, BRect updateRect) = 0;
29};
30
31
32class Test {
33public:
34								Test(const char* name,
35									TestRenderer* clippingTest,
36									TestRenderer* validateTest);
37								~Test();
38
39			const char*			Name() const
40									{ return fName.String(); }
41
42			TestRenderer*		ClippingTest() const
43									{ return fClippingTest; }
44			TestRenderer*		ValidateTest() const
45									{ return fValidateTest; }
46
47private:
48			BString				fName;
49			TestRenderer*		fClippingTest;
50			TestRenderer*		fValidateTest;
51};
52
53
54Test::Test(const char* name, TestRenderer* clippingTest,
55		TestRenderer* validateTest)
56	:
57	fName(name),
58	fClippingTest(clippingTest),
59	fValidateTest(validateTest)
60{
61}
62
63
64Test::~Test()
65{
66	delete fClippingTest;
67	delete fValidateTest;
68}
69
70
71// #pragma mark - TestView
72
73
74class TestView : public BView {
75public:
76								TestView();
77	virtual						~TestView();
78
79	virtual	void				Draw(BRect updateRect);
80
81			void				SetTestRenderer(TestRenderer* renderer);
82
83private:
84			TestRenderer*		fTestRenderer;
85};
86
87
88TestView::TestView()
89	:
90	BView(NULL, B_WILL_DRAW),
91	fTestRenderer(NULL)
92{
93}
94
95
96TestView::~TestView()
97{
98}
99
100
101void
102TestView::Draw(BRect updateRect)
103{
104	if (fTestRenderer != NULL)
105		fTestRenderer->Draw(this, updateRect);
106}
107
108
109void
110TestView::SetTestRenderer(TestRenderer* renderer)
111{
112	fTestRenderer = renderer;
113	Invalidate();
114}
115
116
117// #pragma mark - TestWindow
118
119
120enum {
121	MSG_SELECT_TEST	= 'stst'
122};
123
124
125class TestWindow : public BWindow {
126public:
127								TestWindow();
128	virtual						~TestWindow();
129
130	virtual	void				MessageReceived(BMessage* message);
131
132			void				AddTest(Test* test);
133			void				SetToTest(int32 index);
134
135private:
136			TestView*			fClippingTestView;
137			TestView*			fValidateTestView;
138
139			BMenuField*			fTestSelectionField;
140
141			BList				fTests;
142};
143
144
145TestWindow::TestWindow()
146	:
147	BWindow(BRect(50.0, 50.0, 450.0, 250.0), "ClipToPicture Test",
148		B_DOCUMENT_WINDOW, B_ASYNCHRONOUS_CONTROLS | B_QUIT_ON_WINDOW_CLOSE
149			| B_AUTO_UPDATE_SIZE_LIMITS)
150{
151	fClippingTestView = new TestView();
152	fValidateTestView = new TestView();
153
154	BGroupView* group = new BGroupView(B_HORIZONTAL);
155	BLayoutBuilder::Group<>(group, B_HORIZONTAL, 0.0f)
156		.Add(fClippingTestView)
157		.Add(fValidateTestView)
158	;
159
160	BScrollView* scrollView = new BScrollView("scroll", group, 0, true, true);
161
162	BStringView* leftLabel = new BStringView("left label",
163		"ClipToPicture:");
164	leftLabel->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
165
166	BStringView* rightLabel = new BStringView("right label",
167		"Validation:");
168	rightLabel->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
169
170	fTestSelectionField = new BMenuField("test selection",
171		"Select test:", new BPopUpMenu("select"));
172
173	BLayoutBuilder::Group<>(this, B_VERTICAL, 0.0f)
174		.AddGroup(B_HORIZONTAL)
175			.Add(fTestSelectionField)
176			.AddGlue()
177			.SetInsets(B_USE_DEFAULT_SPACING)
178		.End()
179		.AddGroup(B_HORIZONTAL)
180			.Add(leftLabel)
181			.Add(rightLabel)
182			.SetInsets(B_USE_DEFAULT_SPACING)
183		.End()
184		.Add(scrollView)
185	;
186}
187
188
189TestWindow::~TestWindow()
190{
191	for (int32 i = fTests.CountItems() - 1; i >= 0; i++)
192		delete (Test*)fTests.ItemAt(i);
193}
194
195
196void
197TestWindow::MessageReceived(BMessage* message)
198{
199	switch (message->what) {
200		case MSG_SELECT_TEST:
201		{
202			int32 index;
203			if (message->FindInt32("index", &index) == B_OK)
204				SetToTest(index);
205			break;
206		}
207
208		default:
209			BWindow::MessageReceived(message);
210	}
211}
212
213
214void
215TestWindow::AddTest(Test* test)
216{
217	if (test == NULL || fTests.HasItem(test))
218		return;
219
220	if (!fTests.AddItem(test)) {
221		delete test;
222		return;
223	}
224
225	BMessage* message = new BMessage(MSG_SELECT_TEST);
226	message->AddInt32("index", fTests.CountItems() - 1);
227
228	BMenuItem* item = new BMenuItem(test->Name(), message);
229	if (!fTestSelectionField->Menu()->AddItem(item)) {
230		fTests.RemoveItem(fTests.CountItems() - 1);
231		delete test;
232		delete item;
233		return;
234	}
235
236	if (fTests.CountItems() == 1)
237		SetToTest(0);
238}
239
240
241void
242TestWindow::SetToTest(int32 index)
243{
244	Test* test = (Test*)fTests.ItemAt(index);
245	if (test == NULL)
246		return;
247
248	fTestSelectionField->Menu()->ItemAt(index)->SetMarked(true);
249
250	fClippingTestView->SetTestRenderer(test->ClippingTest());
251	fValidateTestView->SetTestRenderer(test->ValidateTest());
252}
253
254
255// #pragma mark - Test1
256
257
258class Test1Clipping : public TestRenderer {
259	virtual void Draw(BView* view, BRect updateRect)
260	{
261		BPicture picture;
262		view->BeginPicture(&picture);
263		view->SetDrawingMode(B_OP_ALPHA);
264		view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE);
265		view->DrawString("Clipping to text.", BPoint(20, 30));
266		view->EndPicture();
267
268		view->ClipToPicture(&picture);
269
270		view->FillRect(view->Bounds());
271	}
272};
273
274
275class Test1Validate : public TestRenderer {
276	virtual void Draw(BView* view, BRect updateRect)
277	{
278		view->DrawString("Clipping to text.", BPoint(20, 30));
279	}
280};
281
282
283// #pragma mark - Test2
284
285
286class Test2Clipping : public TestRenderer {
287	virtual void Draw(BView* view, BRect updateRect)
288	{
289		view->PushState();
290
291		BPicture picture;
292		view->BeginPicture(&picture);
293		view->SetDrawingMode(B_OP_ALPHA);
294		view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE);
295		view->SetScale(2.0);
296		view->DrawString("Scaled clipping", BPoint(10, 15));
297		view->DrawString("to text.", BPoint(10, 25));
298		view->EndPicture();
299
300		view->PopState();
301
302		view->ClipToPicture(&picture);
303
304		view->FillRect(view->Bounds());
305	}
306};
307
308
309class Test2Validate : public TestRenderer {
310	virtual void Draw(BView* view, BRect updateRect)
311	{
312		view->SetScale(2.0);
313		view->DrawString("Scaled clipping", BPoint(10, 15));
314		view->DrawString("to text.", BPoint(10, 25));
315	}
316};
317
318
319// #pragma mark - Test2
320
321
322class Test3Clipping : public TestRenderer {
323	virtual void Draw(BView* view, BRect updateRect)
324	{
325		BPicture picture;
326		view->BeginPicture(&picture);
327		view->SetDrawingMode(B_OP_ALPHA);
328		view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE);
329		view->DrawString("Scaled picture", BPoint(10, 15));
330		view->EndPicture();
331
332		view->SetScale(2.0);
333		view->ClipToPicture(&picture);
334
335		view->SetScale(1.0);
336		view->FillRect(view->Bounds());
337	}
338};
339
340
341class Test3Validate : public TestRenderer {
342	virtual void Draw(BView* view, BRect updateRect)
343	{
344		view->SetScale(2.0);
345		view->DrawString("Scaled picture", BPoint(10, 15));
346	}
347};
348
349
350// #pragma mark - Test2
351
352
353class Test4Clipping : public TestRenderer {
354	virtual void Draw(BView* view, BRect updateRect)
355	{
356		view->SetDrawingMode(B_OP_ALPHA);
357		view->SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_COMPOSITE);
358
359		BPicture rect;
360		view->BeginPicture(&rect);
361		view->FillRect(BRect(20, 20, 50, 50));
362		view->EndPicture();
363
364		view->ClipToPicture(&rect);
365
366		view->PushState();
367		BPicture circle;
368		view->BeginPicture(&circle);
369		view->FillEllipse(BRect(20, 20, 50, 50));
370		view->EndPicture();
371
372		view->ClipToInversePicture(&circle);
373
374		view->FillRect(view->Bounds());
375
376		view->PopState();
377	}
378};
379
380
381class Test4Validate : public TestRenderer {
382	virtual void Draw(BView* view, BRect updateRect)
383	{
384		view->FillRect(BRect(20, 20, 50, 50));
385		view->FillEllipse(BRect(20, 20, 50, 50), B_SOLID_LOW);
386	}
387};
388
389
390// #pragma mark -
391
392
393int
394main(int argc, char** argv)
395{
396	BApplication app(kAppSignature);
397
398	TestWindow* window = new TestWindow();
399
400	window->AddTest(new Test("Simple clipping",
401		new Test1Clipping(), new Test1Validate()));
402
403	window->AddTest(new Test("Scaled clipping 1",
404		new Test2Clipping(), new Test2Validate()));
405
406	window->AddTest(new Test("Scaled clipping 2",
407		new Test3Clipping(), new Test3Validate()));
408
409	window->AddTest(new Test("Nested states",
410		new Test4Clipping(), new Test4Validate()));
411
412	window->SetToTest(3);
413	window->Show();
414
415	app.Run();
416	return 0;
417}
418