xref: /haiku/src/tests/servers/app/draw_after_children/DrawAfterChildren.cpp (revision 1e60bdeab63fa7a57bc9a55b032052e95a18bd2c)
1 
2 #include <stdio.h>
3 
4 #include <Application.h>
5 #include <View.h>
6 #include <Window.h>
7 
8 /*-----------------------------------------------------------------------------
9 
10 OBSERVATION 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 
38 CONCLUSION:
39 
40 It 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 
50 That areas exposed by moving child views are not repainted could
51 be considered a bug of the R5 implementation.
52 
53 -----------------------------------------------------------------------------*/
54 
55 
56 
57 class TestView : public BView {
58 public:
59 	TestView(BRect frame);
60 	~TestView();
61 
62 	virtual	void Draw(BRect updateRect);
63 	virtual void DrawAfterChildren(BRect updateRect);
64 };
65 
66 
67 TestView::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 
75 TestView::~TestView()
76 {
77 }
78 
79 
80 void
81 TestView::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 
94 void
95 TestView::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 
112 class ChildView : public BView {
113 public:
114 	ChildView(BRect frame, const char* name, rgb_color viewColor);
115 	~ChildView();
116 
117 	virtual	void Draw(BRect updateRect);
118 };
119 
120 
121 ChildView::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 
131 ChildView::~ChildView()
132 {
133 }
134 
135 
136 void
137 ChildView::Draw(BRect updateRect)
138 {
139 	FillRect(updateRect, B_SOLID_LOW);
140 }
141 
142 
143 // #pragma mark -
144 
145 
146 int
147 main(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