xref: /haiku/src/apps/cortex/DiagramView/DiagramBox.cpp (revision 3e216965baa8d58a67bf7372e2bfa13d999f5a9d)
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 // *** ctor/dtor (public)
21 // -------------------------------------------------------- //
22 
23 DiagramBox::DiagramBox(
24 	BRect frame,
25 	uint32 flags)
26 	: DiagramItem(DiagramItem::M_BOX),
27 	  DiagramItemGroup(DiagramItem::M_ENDPOINT),
28 	  m_frame(frame),
29 	  m_flags(flags)
30 {
31 	D_METHOD(("DiagramBox::DiagramBox()\n"));
32 	makeDraggable(true);
33 }
34 
35 DiagramBox::~DiagramBox()
36 {
37 	D_METHOD(("DiagramBox::~DiagramBox()\n"));
38 }
39 
40 // -------------------------------------------------------- //
41 // *** derived from DiagramItemGroup (public)
42 // -------------------------------------------------------- //
43 
44 bool DiagramBox::addItem(
45 	DiagramItem *item)
46 {
47 	D_METHOD(("DiagramBox::addItem()\n"));
48 	if (item)
49 	{
50 		if (DiagramItemGroup::addItem(item))
51 		{
52 			if (m_view)
53 			{
54 				item->_setOwner(m_view);
55 				item->attachedToDiagram();
56 			}
57 			return true;
58 		}
59 	}
60 	return false;
61 }
62 
63 bool DiagramBox::removeItem(
64 	DiagramItem *item)
65 {
66 	D_METHOD(("DiagramBox::removeItem()\n"));
67 	if (item)
68 	{
69 		item->detachedFromDiagram();
70 		if (DiagramItemGroup::removeItem(item))
71 		{
72 			item->_setOwner(0);
73 			return true;
74 		}
75 	}
76 	return false;
77 }
78 
79 // -------------------------------------------------------- //
80 // *** derived from DiagramItem (public)
81 // -------------------------------------------------------- //
82 
83 void DiagramBox::draw(
84 	BRect updateRect)
85 {
86 	D_DRAW(("DiagramBox::draw()\n"));
87 	if (view())
88 	{
89 		view()->PushState();
90 		{
91 			if (m_flags & M_DRAW_UNDER_ENDPOINTS)
92 			{
93 				BRegion region, clipping;
94 				region.Include(frame());
95 				if (group()->getClippingAbove(this, &clipping))
96 					region.Exclude(&clipping);
97 				view()->ConstrainClippingRegion(&region);
98 				drawBox();
99 				for (int32 i = 0; i < countItems(); i++)
100 				{
101 					DiagramItem *item = itemAt(i);
102 					if (region.Intersects(item->frame()))
103 					{
104 						item->draw(item->frame());
105 					}
106 				}
107 			}
108 			else
109 			{
110 				BRegion region, clipping;
111 				region.Include(frame());
112 				if (view()->getClippingAbove(this, &clipping))
113 					region.Exclude(&clipping);
114 				for (int32 i = 0; i < countItems(); i++)
115 				{
116 					DiagramItem *item = itemAt(i);
117 					BRect r;
118 					if (region.Intersects(r = item->frame()))
119 					{
120 						item->draw(r);
121 						region.Exclude(r);
122 					}
123 				}
124 				view()->ConstrainClippingRegion(&region);
125 				drawBox();
126 			}
127 		}
128 		view()->PopState();
129 	}
130 }
131 
132 void DiagramBox::mouseDown(
133 	BPoint point,
134 	uint32 buttons,
135 	uint32 clicks)
136 {
137 	D_MOUSE(("DiagramBox::mouseDown()\n"));
138 	DiagramItem *item = itemUnder(point);
139 	if (item)
140 	{
141 		item->mouseDown(point, buttons, clicks);
142 	}
143 	else if (clicks == 1)
144 	{
145 		if (isSelectable())
146 		{
147 			BMessage selectMsg(M_SELECTION_CHANGED);
148 			if (modifiers() & B_SHIFT_KEY)
149 			{
150 				selectMsg.AddBool("replace", false);
151 			}
152 			else
153 			{
154 				selectMsg.AddBool("replace", true);
155 			}
156 			selectMsg.AddPointer("item", reinterpret_cast<void *>(this));
157 			DiagramView* v = view();
158 			BMessenger(v).SendMessage(&selectMsg);
159 		}
160 		if (isDraggable() && (buttons == B_PRIMARY_MOUSE_BUTTON))
161 		{
162 			BMessage dragMsg(M_BOX_DRAGGED);
163 			dragMsg.AddPointer("item", static_cast<void *>(this));
164 			dragMsg.AddPoint("offset", point - frame().LeftTop());
165 			view()->DragMessage(&dragMsg, BRect(0.0, 0.0, -1.0, -1.0), view());
166 		}
167 	}
168 }
169 
170 void DiagramBox::mouseOver(
171 	BPoint point,
172 	uint32 transit)
173 {
174 	D_MOUSE(("DiagramBox::mouseOver()\n"));
175 	DiagramItem *last = lastItemUnder();
176 	if (last && (transit == B_EXITED_VIEW))
177 	{
178 		last->mouseOver(point, B_EXITED_VIEW);
179 		resetItemUnder();
180 	}
181 	else
182 	{
183 		DiagramItem *item = itemUnder(point);
184 		if (item)
185 		{
186 			if (item != last)
187 			{
188 				if (last)
189 					last->mouseOver(point, B_EXITED_VIEW);
190 				item->mouseOver(point, B_ENTERED_VIEW);
191 			}
192 			else
193 			{
194 				item->mouseOver(point, B_INSIDE_VIEW);
195 			}
196 		}
197 		else if (last)
198 		{
199 			last->mouseOver(point, B_EXITED_VIEW);
200 		}
201 	}
202 }
203 
204 void DiagramBox::messageDragged(
205 	BPoint point,
206 	uint32 transit,
207 	const BMessage *message)
208 {
209 	D_MOUSE(("DiagramBox::messageDragged()\n"));
210 	DiagramItem *last = lastItemUnder();
211 	if (last && (transit == B_EXITED_VIEW))
212 	{
213 		last->messageDragged(point, B_EXITED_VIEW, message);
214 		resetItemUnder();
215 	}
216 	else
217 	{
218 		DiagramItem *item = itemUnder(point);
219 		if (item)
220 		{
221 			if (item != last)
222 			{
223 				if (last)
224 				{
225 					last->messageDragged(point, B_EXITED_VIEW, message);
226 				}
227 				item->messageDragged(point, B_ENTERED_VIEW, message);
228 			}
229 			else
230 			{
231 				item->messageDragged(point, B_INSIDE_VIEW, message);
232 			}
233 			return;
234 		}
235 		else if (last)
236 		{
237 			last->messageDragged(point, B_EXITED_VIEW, message);
238 		}
239 		if (message->what == M_WIRE_DRAGGED)
240 		{
241 			view()->trackWire(point);
242 		}
243 	}
244 }
245 
246 void DiagramBox::messageDropped(
247 	BPoint point,
248 	BMessage *message)
249 {
250 	D_METHOD(("DiagramBox::messageDropped()\n"));
251 	DiagramItem *item = itemUnder(point);
252 	if (item)
253 	{
254 		item->messageDropped(point, message);
255 		return;
256 	}
257 }
258 
259 // -------------------------------------------------------- //
260 // *** operations (public)
261 // -------------------------------------------------------- //
262 
263 void DiagramBox::moveBy(
264 	float x,
265 	float y,
266 	BRegion *wireRegion)
267 {
268 	D_METHOD(("DiagramBox::moveBy()\n"));
269 	if (view())
270 	{
271 		view()->PushState();
272 		{
273 			for (int32 i = 0; i < countItems(); i++)
274 			{
275 				DiagramEndPoint *endPoint = dynamic_cast<DiagramEndPoint *>(itemAt(i));
276 				if (endPoint)
277 				{
278 					endPoint->moveBy(x, y, wireRegion);
279 				}
280 			}
281 			if (wireRegion)
282 			{
283 				wireRegion->Include(m_frame);
284 				m_frame.OffsetBy(x, y);
285 				wireRegion->Include(m_frame);
286 			}
287 			else
288 			{
289 				m_frame.OffsetBy(x, y);
290 			}
291 		}
292 		view()->PopState();
293 	}
294 }
295 
296 void DiagramBox::resizeBy(
297 	float horizontal,
298 	float vertical)
299 {
300 	D_METHOD(("DiagramBox::resizeBy()\n"));
301 	m_frame.right += horizontal;
302 	m_frame.bottom += vertical;
303 }
304 
305 // -------------------------------------------------------- //
306 // *** internal operations (private)
307 // -------------------------------------------------------- //
308 
309 void DiagramBox::_setOwner(
310 	DiagramView *owner)
311 {
312 	D_METHOD(("DiagramBox::_setOwner()\n"));
313 	m_view = owner;
314 	for (int32 i = 0; i < countItems(DiagramItem::M_ENDPOINT); i++)
315 	{
316 		DiagramItem *item = itemAt(i);
317 		item->_setOwner(m_view);
318 		if (m_view)
319 		{
320 			item->attachedToDiagram();
321 		}
322 	}
323 }
324 
325 // END -- DiagramBox.cpp --
326