1
2#include <stdio.h>
3
4#include <Application.h>
5#include <View.h>
6#include <Window.h>
7
8/*-----------------------------------------------------------------------------
9
10OBSERVATION on R5 behaviour:
11
12* The hook function DrawAfterChildren is not called at all if the
13  view flags don't include B_DRAW_ON_CHILDREN.
14
15* If the view flags include B_DRAW_ON_CHILDREN, then any drawing commands
16  executed in Draw() AND DrawAfterChildren() will paint on top of children.
17
18* The background of a view with the B_DRAW_ON_CHILDREN flag set will not
19  be painted by the app_server when child views change position and areas
20  in the parent view are "exposed". If the expose events have other reasons,
21  the background is painted as usual.
22
23* The app_server side background painting of child views does not occur
24  after the Draw() hook of the parent view with B_DRAW_ON_CHILDREN has been
25  called. So while DrawAfterChildren() may be called after the Draw() hooks
26  of all children have been called, the background has been painted earlier.
27
28* It looks like the background painting inside app_server of a view with
29  B_DRAW_ON_CHILDREN paints over the background of any children, though
30  the background of the children is later painted too. Therefor, if a child
31  has B_TRANSPARENT_COLOR background, the background of the parent with
32  B_DRAW_ON_CHILDREN stays visible in the area of that child.
33
34* Both Draw() and DrawAfterChildren() appear to push their own graphics
35  states onto the state stack.
36
37
38CONCLUSION:
39
40It looks like the B_DRAW_ON_CHILDREN flag causes two effects:
41
42* The local view clipping region inside the app_server simply ignores
43  any children, this effects any drawing commands, those from Draw()
44  and those from DrawAfterChildren()
45
46* The DrawAfterChildren() hook is called after the children have drawn,
47  so that the user may move all drawing functions there which he does not
48  wish to have painted over by children.
49
50That areas exposed by moving child views are not repainted could
51be considered a bug of the R5 implementation.
52
53-----------------------------------------------------------------------------*/
54
55
56
57class TestView : public BView {
58public:
59	TestView(BRect frame);
60	~TestView();
61
62	virtual	void Draw(BRect updateRect);
63	virtual void DrawAfterChildren(BRect updateRect);
64};
65
66
67TestView::TestView(BRect frame)
68	: BView(frame, "TestView", B_FOLLOW_ALL,
69		B_WILL_DRAW | B_DRAW_ON_CHILDREN | B_FULL_UPDATE_ON_RESIZE)
70{
71	SetViewColor(200, 220, 255);
72}
73
74
75TestView::~TestView()
76{
77}
78
79
80void
81TestView::Draw(BRect updateRect)
82{
83	printf("Draw(BRect(%.1f, %.1f, %.1f, %.1f))\n",
84		updateRect.left, updateRect.top, updateRect.right, updateRect.bottom);
85
86	printf("pensize: %.2f\n", PenSize());
87
88	SetHighColor(0, 0, 255);
89	StrokeLine(Bounds().LeftBottom(), Bounds().RightTop());
90
91	SetPenSize(5);
92}
93
94void
95TestView::DrawAfterChildren(BRect updateRect)
96{
97	printf("DrawAfterChildren(BRect(%.1f, %.1f, %.1f, %.1f))\n",
98		updateRect.left, updateRect.top, updateRect.right, updateRect.bottom);
99
100	printf("pensize: %.2f\n", PenSize());
101
102	SetHighColor(255, 0, 0);
103	StrokeLine(Bounds().LeftTop(), Bounds().RightBottom());
104	Sync();
105
106	SetPenSize(7);
107}
108
109
110//	#pragma mark -
111
112class ChildView : public BView {
113public:
114	ChildView(BRect frame, const char* name, rgb_color viewColor);
115	~ChildView();
116
117	virtual	void Draw(BRect updateRect);
118};
119
120
121ChildView::ChildView(BRect frame, const char* name, rgb_color viewColor)
122	: BView(frame, name, B_FOLLOW_ALL, 0)
123{
124	SetLowColor(200, 200, 200);
125	SetViewColor(viewColor);
126	if (*(int32*)&viewColor == *(int32*)&B_TRANSPARENT_COLOR)
127		SetFlags(Flags() | B_WILL_DRAW);
128}
129
130
131ChildView::~ChildView()
132{
133}
134
135
136void
137ChildView::Draw(BRect updateRect)
138{
139	FillRect(updateRect, B_SOLID_LOW);
140}
141
142
143// #pragma mark -
144
145
146int
147main(int argc, char** argv)
148{
149	BApplication app("application/x-vnd.Haiku-DrawAfterChildren");
150
151	BRect frame(100, 100, 700, 400);
152	BWindow* window = new BWindow(frame, "Window",
153		B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE);
154
155	frame.OffsetTo(B_ORIGIN);
156	TestView* view = new TestView(frame);
157	window->AddChild(view);
158
159	frame.InsetBy(20, 20);
160	frame.right = frame.left + frame.Width() / 2 - 10;
161	BView* child = new ChildView(frame, "child 1",
162		(rgb_color){ 200, 200, 200, 255 });
163	view->AddChild(child);
164
165	frame.OffsetBy(frame.Width() + 20, 0);
166	child = new ChildView(frame, "child 2", B_TRANSPARENT_COLOR);
167	view->AddChild(child);
168
169	window->Show();
170
171	app.Run();
172	return 0;
173}
174
175