1#include <Application.h>
2#include <GridView.h>
3#include <LayoutBuilder.h>
4#include <Picture.h>
5#include <ScrollView.h>
6#include <Shape.h>
7#include <View.h>
8#include <Window.h>
9
10
11typedef void (*clipper)(BView*, BRect, bool);
12typedef void (*test)(BView*, clipper);
13
14static const BRect bigRect(-1000,-1000, 1000,1000);
15static const BRect baseRect(-25,-10, 25,10);
16static const BRect corner(-25,-10, -15,0);
17static const BRect crossRect(-5,-35, 5,40);
18
19
20static void
21rectClipper(BView* view, BRect rect, bool inverse)
22{
23	if (inverse)
24		view->ClipToInverseRect(rect);
25	else
26		view->ClipToRect(rect);
27}
28
29static void
30pictureClipper(BView* view, BRect rect, bool inverse)
31{
32	BPicture p;
33	view->BeginPicture(&p);
34	view->FillEllipse(rect);
35	view->SetHighColor(0, 0, 0, 0);
36	view->FillEllipse(rect.InsetByCopy(rect.Width()/4, rect.Height()/4));
37	view->EndPicture();
38
39	if (inverse)
40		view->ClipToInversePicture(&p);
41	else
42		view->ClipToPicture(&p);
43}
44
45static void
46shapeClipper(BView* view, BRect rect, bool inverse)
47{
48	BShape s;
49	s.MoveTo(rect.LeftTop());
50	s.LineTo(rect.RightBottom());
51	s.ArcTo(rect.Width()/4, rect.Height()/4, 0, false, true, rect.RightTop());
52	s.LineTo(rect.LeftBottom());
53	s.Close();
54
55	if (inverse)
56		view->ClipToInverseShape(&s);
57	else
58		view->ClipToShape(&s);
59}
60
61
62static void
63testBase(BView* view, clipper clip, bool inverse)
64{
65	clip(view, baseRect, inverse);
66	view->SetHighColor(255,0,0);
67	view->FillRect(bigRect);
68}
69
70static void
71testBaseDirect(BView* view, clipper clip)
72{
73	testBase(view, clip, false);
74}
75
76static void
77testBaseInverse(BView* view, clipper clip)
78{
79	testBase(view, clip, true);
80}
81
82static void
83testCross(BView* view, clipper clip, bool inverse)
84{
85	clip(view, crossRect, inverse);
86	view->SetHighColor(0,0,255);
87	view->FillRect(bigRect);
88}
89
90static void
91testCorner(BView* view, clipper clip, bool inverse)
92{
93	clip(view, corner, inverse);
94	view->SetHighColor(0,255,0);
95	view->FillRect(bigRect);
96}
97
98static void
99testCross00(BView* view, clipper clip)
100{
101	testBase(view, clip, false);
102	testCross(view, clip, false);
103}
104
105static void
106testCross01(BView* view, clipper clip)
107{
108	testBase(view, clip, false);
109	testCross(view, clip, true);
110}
111
112static void
113testCross10(BView* view, clipper clip)
114{
115	testBase(view, clip, true);
116	testCross(view, clip, false);
117}
118
119static void
120testCross11(BView* view, clipper clip)
121{
122	testBase(view, clip, true);
123	testCross(view, clip, true);
124}
125
126static void
127test3000(BView* view, clipper clip)
128{
129	testBase(view, clip, false);
130	testCorner(view, clip, false);
131	testCross(view, clip, false);
132}
133
134static void
135test3001(BView* view, clipper clip)
136{
137	testBase(view, clip, false);
138	testCorner(view, clip, false);
139	testCross(view, clip, true);
140}
141
142static void
143test3010(BView* view, clipper clip)
144{
145	testBase(view, clip, false);
146	testCorner(view, clip, true);
147	testCross(view, clip, false);
148}
149
150static void
151test3011(BView* view, clipper clip)
152{
153	testBase(view, clip, false);
154	testCorner(view, clip, true);
155	testCross(view, clip, true);
156}
157
158static void
159test3100(BView* view, clipper clip)
160{
161	testBase(view, clip, true);
162	testCorner(view, clip, false);
163	testCross(view, clip, false);
164}
165
166static void
167test3101(BView* view, clipper clip)
168{
169	testBase(view, clip, true);
170	testCorner(view, clip, false);
171	testCross(view, clip, true);
172}
173
174static void
175test3110(BView* view, clipper clip)
176{
177	testBase(view, clip, true);
178	testCorner(view, clip, true);
179	testCross(view, clip, false);
180}
181
182static void
183test3111(BView* view, clipper clip)
184{
185	testBase(view, clip, true);
186	testCorner(view, clip, true);
187	testCross(view, clip, true);
188}
189
190static const test tests[] = {
191	testBaseDirect, testBaseInverse,
192	testCross00, testCross01, testCross10, testCross11,
193	test3000, test3001, test3010, test3011,
194	test3100, test3101, test3110, test3111
195};
196
197
198class View : public BView {
199public:
200								View(const char* name, test, clipper);
201			void				Draw(BRect);
202			void				AttachedToWindow();
203
204private:
205			test				fTest;
206			clipper				fClipper;
207};
208
209View::View(const char* name, test fTest, clipper fClipper)
210	:
211	BView(BRect(0,0, 100,100), name, 0, B_WILL_DRAW),
212	fTest(fTest),
213	fClipper(fClipper)
214{
215}
216
217void
218View::AttachedToWindow()
219{
220	BView::AttachedToWindow();
221	TranslateBy(50, 50);
222}
223
224void
225View::Draw(BRect)
226{
227	fTest(this, fClipper);
228}
229
230
231class App : public BApplication {
232public:
233								App();
234};
235
236App::App()
237	:
238	BApplication("application/x-vnd.Haiku-Test_inverse_clip")
239{
240	BWindow* window = new BWindow(BRect(100,100, 800,400), "clip test",
241		B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE);
242
243	BGridView* grid = new BGridView();
244	grid->SetResizingMode(B_FOLLOW_ALL_SIDES);
245
246	BLayoutBuilder::Grid<> layout(grid);
247	layout.SetInsets(B_USE_DEFAULT_SPACING);
248
249	int testsCount = B_COUNT_OF(tests);
250	for (int i = 0; i < testsCount; i++) {
251		layout.Add(new View("region", tests[i], rectClipper), 0, i);
252		layout.Add(new View("rotate", tests[i], rectClipper), 1, i);
253			// This one changes from Region to Shape clipping
254		layout.Add(new View("picture", tests[i], pictureClipper), 2, i);
255		layout.Add(new View("rotate", tests[i], pictureClipper), 3, i);
256		layout.Add(new View("shape", tests[i], shapeClipper), 4, i);
257		layout.Add(new View("rotate", tests[i], shapeClipper), 5, i);
258	}
259
260	BScrollView* scroll = new BScrollView("scroll", grid, B_FOLLOW_ALL_SIDES,
261		0, true, true, B_NO_BORDER);
262	window->AddChild(scroll);
263	BRect bounds(window->Bounds());
264	scroll->ResizeTo(bounds.Width(), bounds.Height());
265
266	BView* rotate;
267	while ((rotate = window->FindView("rotate")) != NULL) {
268		rotate->RotateBy(0.78);
269		rotate->SetName("rotated");
270	}
271
272	window->Show();
273}
274
275
276int
277main()
278{
279	App app;
280	app.Run();
281	return 0;
282}
283