xref: /haiku/src/apps/cortex/DiagramView/DiagramBox.cpp (revision 5115ca085884f7b604a3d607688f0ca20fb7cf57)
1 // DiagramBox.cpp
2 
3 #include "DiagramBox.h"
4 #include "DiagramDefs.h"
5 #include "DiagramEndPoint.h"
6 #include "DiagramView.h"
7 
8 #include <Message.h>
9 #include <Messenger.h>
10 
11 __USE_CORTEX_NAMESPACE
12 
13 #include <Debug.h>
14 #define D_METHOD(x) //PRINT (x)
15 #define D_MESSAGE(x) //PRINT (x)
16 #define D_MOUSE(x) //PRINT (x)
17 #define D_DRAW(x) //PRINT (x)
18 
19 
20 //	#pragma mark -
21 
22 
23 DiagramBox::DiagramBox(BRect frame, uint32 flags)
24 	: DiagramItem(DiagramItem::M_BOX),
25 	DiagramItemGroup(DiagramItem::M_ENDPOINT),
26 	m_frame(frame),
27 	m_flags(flags)
28 {
29 	D_METHOD(("DiagramBox::DiagramBox()\n"));
30 	makeDraggable(true);
31 }
32 
33 
34 DiagramBox::~DiagramBox()
35 {
36 	D_METHOD(("DiagramBox::~DiagramBox()\n"));
37 }
38 
39 
40 // derived from DiagramItemGroup (public)
41 bool
42 DiagramBox::addItem(DiagramItem *item)
43 {
44 	D_METHOD(("DiagramBox::addItem()\n"));
45 	if (item) {
46 		if (DiagramItemGroup::addItem(item)) {
47 			if (m_view) {
48 				item->_setOwner(m_view);
49 				item->attachedToDiagram();
50 			}
51 			return true;
52 		}
53 	}
54 	return false;
55 }
56 
57 
58 bool
59 DiagramBox::removeItem(DiagramItem *item)
60 {
61 	D_METHOD(("DiagramBox::removeItem()\n"));
62 	if (item) {
63 		item->detachedFromDiagram();
64 		if (DiagramItemGroup::removeItem(item)) {
65 			item->_setOwner(0);
66 			return true;
67 		}
68 	}
69 	return false;
70 }
71 
72 
73 // derived from DiagramItem (public)
74 void
75 DiagramBox::draw(BRect updateRect)
76 {
77 	D_DRAW(("DiagramBox::draw()\n"));
78 	if (view()) {
79 		view()->PushState();
80 		{
81 			if (m_flags & M_DRAW_UNDER_ENDPOINTS) {
82 				BRegion region, clipping;
83 				region.Include(frame());
84 				if (group()->getClippingAbove(this, &clipping))
85 					region.Exclude(&clipping);
86 				view()->ConstrainClippingRegion(&region);
87 				drawBox();
88 				for (uint32 i = 0; i < countItems(); i++) {
89 					DiagramItem *item = itemAt(i);
90 					if (region.Intersects(item->frame()))
91 						item->draw(item->frame());
92 				}
93 			} else {
94 				BRegion region, clipping;
95 				region.Include(frame());
96 				if (view()->getClippingAbove(this, &clipping))
97 					region.Exclude(&clipping);
98 				for (uint32 i = 0; i < countItems(); i++) {
99 					DiagramItem *item = itemAt(i);
100 					BRect r;
101 					if (region.Intersects(r = item->frame())) {
102 						item->draw(r);
103 						region.Exclude(r);
104 					}
105 				}
106 				view()->ConstrainClippingRegion(&region);
107 				drawBox();
108 			}
109 		}
110 		view()->PopState();
111 	}
112 }
113 
114 
115 void
116 DiagramBox::mouseDown(BPoint point, uint32 buttons, uint32 clicks)
117 {
118 	D_MOUSE(("DiagramBox::mouseDown()\n"));
119 	DiagramItem *item = itemUnder(point);
120 	if (item)
121 		item->mouseDown(point, buttons, clicks);
122 	else if (clicks == 1) {
123 		if (isSelectable()) {
124 			BMessage selectMsg(M_SELECTION_CHANGED);
125 			if (modifiers() & B_SHIFT_KEY)
126 				selectMsg.AddBool("replace", false);
127 			else
128 				selectMsg.AddBool("replace", true);
129 			selectMsg.AddPointer("item", reinterpret_cast<void *>(this));
130 			DiagramView* v = view();
131 			BMessenger(v).SendMessage(&selectMsg);
132 		}
133 		if (isDraggable() && (buttons == B_PRIMARY_MOUSE_BUTTON)) {
134 			BMessage dragMsg(M_BOX_DRAGGED);
135 			dragMsg.AddPointer("item", static_cast<void *>(this));
136 			dragMsg.AddPoint("offset", point - frame().LeftTop());
137 			view()->DragMessage(&dragMsg, BRect(0.0, 0.0, -1.0, -1.0), view());
138 		}
139 	}
140 }
141 
142 
143 void
144 DiagramBox::mouseOver(BPoint point, uint32 transit)
145 {
146 	D_MOUSE(("DiagramBox::mouseOver()\n"));
147 	DiagramItem *last = lastItemUnder();
148 	if (last && (transit == B_EXITED_VIEW)) {
149 		last->mouseOver(point, B_EXITED_VIEW);
150 		resetItemUnder();
151 	} else {
152 		DiagramItem *item = itemUnder(point);
153 		if (item) {
154 			if (item != last) {
155 				if (last)
156 					last->mouseOver(point, B_EXITED_VIEW);
157 				item->mouseOver(point, B_ENTERED_VIEW);
158 			} else
159 				item->mouseOver(point, B_INSIDE_VIEW);
160 		}
161 		else if (last)
162 			last->mouseOver(point, B_EXITED_VIEW);
163 	}
164 }
165 
166 
167 void
168 DiagramBox::messageDragged(BPoint point, uint32 transit, const BMessage *message)
169 {
170 	D_MOUSE(("DiagramBox::messageDragged()\n"));
171 	DiagramItem *last = lastItemUnder();
172 	if (last && (transit == B_EXITED_VIEW)) {
173 		last->messageDragged(point, B_EXITED_VIEW, message);
174 		resetItemUnder();
175 	} else {
176 		DiagramItem *item = itemUnder(point);
177 		if (item) {
178 			if (item != last) {
179 				if (last)
180 					last->messageDragged(point, B_EXITED_VIEW, message);
181 				item->messageDragged(point, B_ENTERED_VIEW, message);
182 			} else
183 				item->messageDragged(point, B_INSIDE_VIEW, message);
184 			return;
185 		} else if (last)
186 			last->messageDragged(point, B_EXITED_VIEW, message);
187 		if (message->what == M_WIRE_DRAGGED)
188 			view()->trackWire(point);
189 	}
190 }
191 
192 
193 void
194 DiagramBox::messageDropped(BPoint point, BMessage *message)
195 {
196 	D_METHOD(("DiagramBox::messageDropped()\n"));
197 	DiagramItem *item = itemUnder(point);
198 	if (item) {
199 		item->messageDropped(point, message);
200 		return;
201 	}
202 }
203 
204 
205 // operations (public)
206 void
207 DiagramBox::moveBy(float x, float y, BRegion *wireRegion)
208 {
209 	D_METHOD(("DiagramBox::moveBy()\n"));
210 	if (view()) {
211 		view()->PushState();
212 		{
213 			for (uint32 i = 0; i < countItems(); i++) {
214 				DiagramEndPoint *endPoint = dynamic_cast<DiagramEndPoint *>(itemAt(i));
215 				if (endPoint)
216 					endPoint->moveBy(x, y, wireRegion);
217 			}
218 			if (wireRegion) {
219 				wireRegion->Include(m_frame);
220 				m_frame.OffsetBy(x, y);
221 				wireRegion->Include(m_frame);
222 			}
223 			else
224 				m_frame.OffsetBy(x, y);
225 		}
226 		view()->PopState();
227 	}
228 }
229 
230 
231 void
232 DiagramBox::resizeBy(float horizontal, float vertical)
233 {
234 	D_METHOD(("DiagramBox::resizeBy()\n"));
235 	m_frame.right += horizontal;
236 	m_frame.bottom += vertical;
237 }
238 
239 
240 // internal operations (private)
241 void
242 DiagramBox::_setOwner(DiagramView *owner)
243 {
244 	D_METHOD(("DiagramBox::_setOwner()\n"));
245 	m_view = owner;
246 	for (uint32 i = 0; i < countItems(DiagramItem::M_ENDPOINT); i++) {
247 		DiagramItem *item = itemAt(i);
248 		item->_setOwner(m_view);
249 		if (m_view)
250 			item->attachedToDiagram();
251 	}
252 }
253