1 // DiagramEndPoint.cpp 2 3 #include "DiagramEndPoint.h" 4 #include "DiagramDefs.h" 5 #include "DiagramWire.h" 6 #include "DiagramView.h" 7 8 #include <Message.h> 9 #include <Messenger.h> 10 __USE_CORTEX_NAMESPACE 11 12 #include <Debug.h> 13 #define D_METHOD(x) //PRINT (x) 14 #define D_MESSAGE(x) //PRINT (x) 15 #define D_MOUSE(x) //PRINT (x) 16 17 // -------------------------------------------------------- // 18 // *** ctor/dtor 19 // -------------------------------------------------------- // 20 21 DiagramEndPoint::DiagramEndPoint( 22 BRect frame) 23 : DiagramItem(DiagramItem::M_ENDPOINT), 24 m_frame(frame), 25 m_wire(0), 26 m_connected(false), 27 m_connecting(false) 28 { 29 D_METHOD(("DiagramEndPoint::DiagramEndPoint()\n")); 30 makeDraggable(true); 31 } 32 33 DiagramEndPoint::~DiagramEndPoint() 34 { 35 D_METHOD(("DiagramEndPoint::~DiagramEndPoint()\n")); 36 } 37 38 // -------------------------------------------------------- // 39 // *** hook functions 40 // -------------------------------------------------------- // 41 42 BPoint DiagramEndPoint::connectionPoint() const 43 { 44 D_METHOD(("DiagramEndPoint::connectionPoint()\n")); 45 return BPoint(Frame().left + Frame().Height() / 2.0, Frame().top + Frame().Width() / 2.0); 46 } 47 48 bool DiagramEndPoint::connectionRequested( 49 DiagramEndPoint *fromWhich) 50 { 51 D_METHOD(("DiagramEndPoint::connectionRequested()\n")); 52 if (!isConnected()) 53 { 54 return true; 55 } 56 return false; 57 } 58 59 // -------------------------------------------------------- // 60 // *** derived from DiagramItem 61 // -------------------------------------------------------- // 62 63 void DiagramEndPoint::Draw( 64 BRect updateRect) 65 { 66 D_METHOD(("DiagramEndPoint::Draw()\n")); 67 if (view()) 68 { 69 view()->PushState(); 70 { 71 BRegion region; 72 region.Include(Frame() & updateRect); 73 view()->ConstrainClippingRegion(®ion); 74 drawEndPoint(); 75 } 76 view()->PopState(); 77 } 78 } 79 80 void DiagramEndPoint::MouseDown( 81 BPoint point, 82 uint32 buttons, 83 uint32 clicks) 84 { 85 D_MOUSE(("DiagramEndPoint::MouseDown()\n")); 86 if (clicks == 1) 87 { 88 if (isSelectable()) 89 { 90 BMessage selectMsg(M_SELECTION_CHANGED); 91 if (modifiers() & B_SHIFT_KEY) 92 { 93 selectMsg.AddBool("replace", false); 94 } 95 else 96 { 97 selectMsg.AddBool("replace", true); 98 } 99 selectMsg.AddPointer("item", reinterpret_cast<void *>(this)); 100 DiagramView* v = view(); 101 BMessenger(v).SendMessage(&selectMsg); 102 } 103 if (isDraggable() && (buttons == B_PRIMARY_MOUSE_BUTTON)) 104 { 105 BMessage dragMsg(M_WIRE_DRAGGED); 106 dragMsg.AddPointer("from", static_cast<void *>(this)); 107 view()->DragMessage(&dragMsg, BRect(0.0, 0.0, -1.0, -1.0), view()); 108 view()->MessageDragged(point, B_INSIDE_VIEW, &dragMsg); 109 } 110 } 111 } 112 113 void DiagramEndPoint::MessageDragged( 114 BPoint point, 115 uint32 transit, 116 const BMessage *message) 117 { 118 D_MOUSE(("DiagramEndPoint::MessageDragged()\n")); 119 switch (message->what) 120 { 121 case M_WIRE_DRAGGED: 122 { 123 D_MESSAGE(("DiagramEndPoint::MessageDragged(M_WIRE_DRAGGED)\n")); 124 switch (transit) 125 { 126 case B_INSIDE_VIEW: 127 { 128 //PRINT((" -> transit: B_INSIDE_VIEW\n")); 129 // this is a WORK-AROUND caused by the unreliability 130 // of BViews DragMessage() routine !! 131 if (isConnecting()) 132 { 133 break; 134 } 135 else if (isConnected()) 136 { 137 view()->trackWire(point); 138 } 139 /* this should be enough in theory: 140 if (!isConnecting()) 141 { 142 view()->trackWire(point); 143 } 144 //break;*/ 145 } 146 case B_ENTERED_VIEW: 147 { 148 //PRINT((" -> transit: B_ENTERED_VIEW\n")); 149 DiagramEndPoint *endPoint; 150 if ((message->FindPointer("from", reinterpret_cast<void **>(&endPoint)) == B_OK) 151 && (endPoint != this)) 152 { 153 if (connectionRequested(endPoint)) 154 { 155 view()->trackWire(connectionPoint()); 156 if (!isConnecting()) 157 { 158 m_connecting = true; 159 connected(); 160 } 161 } 162 else 163 { 164 view()->trackWire(point); 165 if (isConnecting()) 166 { 167 m_connecting = false; 168 disconnected(); 169 } 170 } 171 } 172 break; 173 } 174 case B_EXITED_VIEW: 175 { 176 //PRINT((" -> transit: B_EXITED_VIEW\n")); 177 if (isConnecting()) 178 { 179 m_connecting = false; 180 disconnected(); 181 } 182 break; 183 } 184 } 185 break; 186 } 187 default: 188 { 189 DiagramItem::MessageDragged(point, transit, message); 190 } 191 } 192 } 193 194 void DiagramEndPoint::MessageDropped( 195 BPoint point, 196 BMessage *message) 197 { 198 D_MESSAGE(("DiagramEndPoint::MessageDropped()\n")); 199 switch (message->what) 200 { 201 case M_WIRE_DRAGGED: 202 { 203 D_MESSAGE(("DiagramEndPoint::MessageDropped(M_WIRE_DRAGGED)\n")); 204 DiagramEndPoint *endPoint; 205 if ((message->FindPointer("from", reinterpret_cast<void **>(&endPoint)) == B_OK) 206 && (endPoint != this)) 207 { 208 bool success = connectionRequested(endPoint); 209 BMessage dropMsg(M_WIRE_DROPPED); 210 dropMsg.AddPointer("from", reinterpret_cast<void *>(endPoint)); 211 dropMsg.AddPointer("to", reinterpret_cast<void *>(this)); 212 dropMsg.AddBool("success", success); 213 DiagramView* v = view(); 214 BMessenger(v).SendMessage(&dropMsg); 215 if (isConnecting()) 216 { 217 m_connecting = false; 218 disconnected(); 219 } 220 } 221 return; 222 } 223 default: 224 { 225 DiagramItem::MessageDropped(point, message); 226 } 227 } 228 } 229 230 // -------------------------------------------------------- // 231 // *** frame related operations 232 // -------------------------------------------------------- // 233 234 void DiagramEndPoint::MoveBy( 235 float x, 236 float y, 237 BRegion *updateRegion) 238 { 239 D_METHOD(("DiagramEndPoint::MoveBy()\n")); 240 if (isConnected() && m_wire && updateRegion) 241 { 242 updateRegion->Include(m_wire->Frame()); 243 m_frame.OffsetBy(x, y); 244 m_wire->endPointMoved(this); 245 updateRegion->Include(m_wire->Frame()); 246 } 247 else 248 { 249 m_frame.OffsetBy(x, y); 250 if (m_wire) 251 { 252 m_wire->endPointMoved(this); 253 } 254 } 255 } 256 257 void DiagramEndPoint::ResizeBy( 258 float horizontal, 259 float vertical) 260 { 261 D_METHOD(("DiagramEndPoint::ResizeBy()\n")); 262 m_frame.right += horizontal; 263 m_frame.bottom += vertical; 264 } 265 266 // -------------------------------------------------------- // 267 // *** connection methods 268 // -------------------------------------------------------- // 269 270 void DiagramEndPoint::connect( 271 DiagramWire *wire) 272 { 273 D_METHOD(("DiagramEndPoint::connect()\n")); 274 if (!m_connected && wire) 275 { 276 m_connected = true; 277 m_wire = wire; 278 makeDraggable(false); 279 connected(); 280 } 281 } 282 283 void DiagramEndPoint::disconnect() 284 { 285 D_METHOD(("DiagramEndPoint::disconnect()\n")); 286 if (m_connected) 287 { 288 m_connected = false; 289 m_wire = 0; 290 makeDraggable(true); 291 disconnected(); 292 } 293 } 294 295 // END -- DiagramEndPoint.cpp -- 296