1 #include <Message.h> 2 #include <Messenger.h> 3 #include <Window.h> 4 5 #include <stdio.h> 6 #include <stack.h> 7 8 #include "MyView.h" 9 #include "Layer.h" 10 11 extern BWindow *wind; 12 struct node { 13 node() 14 { 15 pointers = NULL; 16 } 17 node(const BRect& r, int32 maxPointers) 18 { 19 init(r, maxPointers); 20 } 21 ~node() 22 { 23 delete [] pointers; 24 } 25 26 void init(const BRect& r, int32 maxPointers) 27 { 28 rect = r; 29 pointers = new node*[maxPointers]; 30 in_degree = 0; 31 next_pointer = 0; 32 } 33 34 void push(node* node) 35 { 36 pointers[next_pointer] = node; 37 next_pointer++; 38 } 39 node* top() 40 { 41 return pointers[next_pointer]; 42 } 43 node* pop() 44 { 45 node* ret = top(); 46 next_pointer--; 47 return ret; 48 } 49 50 BRect rect; 51 int32 in_degree; 52 node** pointers; 53 int32 next_pointer; 54 }; 55 56 bool 57 is_left_of(const BRect& a, const BRect& b) 58 { 59 return (a.right < b.left); 60 } 61 bool 62 is_above(const BRect& a, const BRect& b) 63 { 64 return (a.bottom < b.top); 65 } 66 67 MyView::MyView(BRect frame, const char *name, uint32 resizingMode, uint32 flags) 68 : BView(frame, name, resizingMode, flags) 69 { 70 SetViewColor(B_TRANSPARENT_COLOR); 71 fTracking = false; 72 fIsResize = false; 73 fIs2ndButton= false; 74 fMovingLayer = NULL; 75 76 rgb_color col; 77 col.red = 49; 78 col.green = 101; 79 col.blue = 156; 80 topLayer = new Layer(Bounds(), "topLayer", B_FOLLOW_ALL, 0, col); 81 topLayer->SetRootLayer(this); 82 83 topLayer->rebuild_visible_regions(BRegion(Bounds()), BRegion(Bounds()), NULL); 84 fRedrawReg.Set(Bounds()); 85 } 86 87 MyView::~MyView() 88 { 89 delete topLayer; 90 } 91 92 Layer* MyView::FindLayer(Layer *lay, BPoint &where) const 93 { 94 if (lay->Visible()->Contains(where)) 95 return lay; 96 else 97 for (Layer *child = lay->BottomChild(); child; child = lay->UpperSibling()) 98 { 99 Layer *found = FindLayer(child, where); 100 if (found) 101 return found; 102 } 103 return NULL; 104 } 105 106 void MyView::MouseDown(BPoint where) 107 { 108 SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); 109 int32 buttons; 110 Looper()->CurrentMessage()->FindInt32("buttons", &buttons); 111 fLastPos = where; 112 if (buttons == B_PRIMARY_MOUSE_BUTTON) 113 { 114 fTracking = true; 115 fMovingLayer = FindLayer(topLayer, where); 116 if (fMovingLayer == topLayer) 117 fMovingLayer = NULL; 118 if (fMovingLayer) 119 { 120 BRect bounds(fMovingLayer->Bounds()); 121 fMovingLayer->ConvertToScreen2(&bounds); 122 BRect resizeRect(bounds.right-10, bounds.bottom-10, bounds.right, bounds.bottom); 123 if (resizeRect.Contains(where)) 124 fIsResize = true; 125 else 126 fIsResize = false; 127 } 128 } 129 else if (buttons == B_SECONDARY_MOUSE_BUTTON) 130 { 131 fIs2ndButton = true; 132 } 133 else if (buttons == B_TERTIARY_MOUSE_BUTTON) 134 { 135 DrawSubTree(topLayer); 136 } 137 } 138 139 void MyView::MouseUp(BPoint where) 140 { 141 fTracking = false; 142 fIs2ndButton = false; 143 fMovingLayer = NULL; 144 } 145 146 void MyView::MouseMoved(BPoint where, uint32 code, const BMessage *a_message) 147 { 148 if (fTracking) 149 { 150 float dx, dy; 151 dx = where.x - fLastPos.x; 152 dy = where.y - fLastPos.y; 153 fLastPos = where; 154 155 if (dx != 0 || dy != 0) 156 { 157 if (fMovingLayer) 158 { 159 if (fIsResize) 160 fMovingLayer->ResizeBy(dx, dy); 161 else 162 fMovingLayer->MoveBy(dx, dy); 163 } 164 } 165 } 166 else if (fIs2ndButton) 167 { 168 SetHighColor(0,0,0); 169 StrokeLine(fLastPos, where); 170 Flush(); 171 fLastPos = where; 172 } 173 } 174 175 void MyView::MessageReceived(BMessage *msg) 176 { 177 switch(msg->what) 178 { 179 case B_MOUSE_WHEEL_CHANGED: 180 { 181 float dy; 182 msg->FindFloat("be:wheel_delta_y", &dy); 183 184 BPoint pt; 185 uint32 buttons; 186 Layer *lay; 187 GetMouse(&pt, &buttons, false); 188 if ((lay = FindLayer(topLayer, pt))) 189 lay->ScrollBy(0, dy*5); 190 break; 191 } 192 default: 193 BView::MessageReceived(msg); 194 } 195 } 196 197 void MyView::CopyRegion(BRegion *region, int32 xOffset, int32 yOffset) 198 { 199 wind->Lock(); 200 int32 count = region->CountRects(); 201 202 // TODO: make this step unnecessary 203 // (by using different stack impl inside node) 204 node nodes[count]; 205 for (int32 i= 0; i < count; i++) { 206 nodes[i].init(region->RectAt(i), count); 207 } 208 209 for (int32 i = 0; i < count; i++) { 210 BRect a = region->RectAt(i); 211 for (int32 k = i + 1; k < count; k++) { 212 BRect b = region->RectAt(k); 213 int cmp = 0; 214 // compare horizontally 215 if (xOffset > 0) { 216 if (is_left_of(a, b)) { 217 cmp -= 1; 218 } else if (is_left_of(b, a)) { 219 cmp += 1; 220 } 221 } else if (xOffset < 0) { 222 if (is_left_of(a, b)) { 223 cmp += 1; 224 } else if (is_left_of(b, a)) { 225 cmp -= 1; 226 } 227 } 228 // compare vertically 229 if (yOffset > 0) { 230 if (is_above(a, b)) { 231 cmp -= 1; 232 } else if (is_above(b, a)) { 233 cmp += 1; 234 } 235 } else if (yOffset < 0) { 236 if (is_above(a, b)) { 237 cmp += 1; 238 } else if (is_above(b, a)) { 239 cmp -= 1; 240 } 241 } 242 // add appropriate node as successor 243 if (cmp > 0) { 244 nodes[i].push(&nodes[k]); 245 nodes[k].in_degree++; 246 } else if (cmp < 0) { 247 nodes[k].push(&nodes[i]); 248 nodes[i].in_degree++; 249 } 250 } 251 } 252 // put all nodes onto a stack that have an "indegree" count of zero 253 stack<node*> inDegreeZeroNodes; 254 for (int32 i = 0; i < count; i++) { 255 if (nodes[i].in_degree == 0) { 256 inDegreeZeroNodes.push(&nodes[i]); 257 } 258 } 259 // pop the rects from the stack, do the actual copy operation 260 // and decrease the "indegree" count of the other rects not 261 // currently on the stack and to which the current rect pointed 262 // to. If their "indegree" count reaches zero, put them onto the 263 // stack as well. 264 265 while (!inDegreeZeroNodes.empty()) { 266 node* n = inDegreeZeroNodes.top(); 267 inDegreeZeroNodes.pop(); 268 269 CopyBits(n->rect, BRect(n->rect).OffsetByCopy(xOffset, yOffset)); 270 271 for (int32 k = 0; k < n->next_pointer; k++) { 272 n->pointers[k]->in_degree--; 273 if (n->pointers[k]->in_degree == 0) 274 inDegreeZeroNodes.push(n->pointers[k]); 275 } 276 } 277 wind->Unlock(); 278 } 279 280 void MyView::RequestRedraw() 281 { 282 wind->Lock(); 283 284 ConstrainClippingRegion(&fRedrawReg); 285 PushState(); 286 DrawSubTree(topLayer); 287 PopState(); 288 ConstrainClippingRegion(NULL); 289 290 fRedrawReg.MakeEmpty(); 291 292 wind->Unlock(); 293 } 294 295 void MyView::Draw(BRect area) 296 { 297 // empty. you can trigger a redraw by clicking the middle mouse button. 298 } 299 300 void MyView::DrawSubTree(Layer* lay) 301 { 302 //printf("======== %s =======\n", lay->Name()); 303 // lay->Visible()->PrintToStream(); 304 // lay->FullVisible()->PrintToStream(); 305 for (Layer *child = lay->BottomChild(); child; child = lay->UpperSibling()) 306 DrawSubTree(child); 307 308 ConstrainClippingRegion(lay->Visible()); 309 SetHighColor(lay->HighColor()); 310 BRegion reg; 311 lay->GetWantedRegion(reg); 312 FillRect(reg.Frame()); 313 Flush(); 314 ConstrainClippingRegion(NULL); 315 } 316