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