2 * Copyright (c) 1999-2000, Eric Moon.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions, and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions, and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
27 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 DiagramItem subclass providing a basic framework for
36 boxes in diagrams, i.e. objects that can contain various
40 #include "DiagramBox.h"
41 #include "DiagramDefs.h"
42 #include "DiagramEndPoint.h"
43 #include "DiagramView.h"
46 #include <Messenger.h>
48 __USE_CORTEX_NAMESPACE
51 #define D_METHOD(x) //PRINT (x)
52 #define D_MESSAGE(x) //PRINT (x)
53 #define D_MOUSE(x) //PRINT (x)
54 #define D_DRAW(x) //PRINT (x)
60 DiagramBox::DiagramBox(BRect frame
, uint32 flags
)
61 : DiagramItem(DiagramItem::M_BOX
),
62 DiagramItemGroup(DiagramItem::M_ENDPOINT
),
66 D_METHOD(("DiagramBox::DiagramBox()\n"));
71 DiagramBox::~DiagramBox()
73 D_METHOD(("DiagramBox::~DiagramBox()\n"));
77 // #pragma mark - derived from DiagramItemGroup (public)
80 /*! Extends the DiagramItemGroup implementation by setting
81 the items owner and calling the attachedToDiagram() hook
85 DiagramBox::AddItem(DiagramItem
*item
)
87 D_METHOD(("DiagramBox::AddItem()\n"));
89 if (DiagramItemGroup::AddItem(item
)) {
91 item
->_SetOwner(m_view
);
92 item
->attachedToDiagram();
101 /*! Extends the DiagramItemGroup implementation by calling
102 the detachedToDiagram() hook on the \a item
105 DiagramBox::RemoveItem(DiagramItem
*item
)
107 D_METHOD(("DiagramBox::RemoveItem()\n"));
109 item
->detachedFromDiagram();
110 if (DiagramItemGroup::RemoveItem(item
)) {
119 // #pragma mark - derived from DiagramItem (public)
122 /*! Prepares the drawing stack and clipping region, then
126 DiagramBox::Draw(BRect updateRect
)
128 D_DRAW(("DiagramBox::Draw()\n"));
132 if (fFlags
& M_DRAW_UNDER_ENDPOINTS
) {
133 BRegion region
, clipping
;
134 region
.Include(Frame());
135 if (group()->GetClippingAbove(this, &clipping
))
136 region
.Exclude(&clipping
);
137 view()->ConstrainClippingRegion(®ion
);
139 for (uint32 i
= 0; i
< CountItems(); i
++) {
140 DiagramItem
*item
= ItemAt(i
);
141 if (region
.Intersects(item
->Frame()))
142 item
->Draw(item
->Frame());
145 BRegion region
, clipping
;
146 region
.Include(Frame());
147 if (view()->GetClippingAbove(this, &clipping
))
148 region
.Exclude(&clipping
);
149 for (uint32 i
= 0; i
< CountItems(); i
++) {
150 DiagramItem
*item
= ItemAt(i
);
152 if (region
.Intersects(r
= item
->Frame())) {
157 view()->ConstrainClippingRegion(®ion
);
166 /*! Is called from the parent DiagramViews MouseDown() implementation
167 if the Box was hit; this version initiates selection and dragging
170 DiagramBox::MouseDown(BPoint point
, uint32 buttons
, uint32 clicks
)
172 D_MOUSE(("DiagramBox::MouseDown()\n"));
173 DiagramItem
*item
= ItemUnder(point
);
175 item
->MouseDown(point
, buttons
, clicks
);
176 else if (clicks
== 1) {
177 if (isSelectable()) {
178 BMessage
selectMsg(M_SELECTION_CHANGED
);
179 if (modifiers() & B_SHIFT_KEY
)
180 selectMsg
.AddBool("replace", false);
182 selectMsg
.AddBool("replace", true);
183 selectMsg
.AddPointer("item", reinterpret_cast<void *>(this));
184 DiagramView
* v
= view();
185 BMessenger(v
).SendMessage(&selectMsg
);
187 if (isDraggable() && (buttons
== B_PRIMARY_MOUSE_BUTTON
)) {
188 BMessage
dragMsg(M_BOX_DRAGGED
);
189 dragMsg
.AddPointer("item", static_cast<void *>(this));
190 dragMsg
.AddPoint("offset", point
- Frame().LeftTop());
191 view()->DragMessage(&dragMsg
, BRect(0.0, 0.0, -1.0, -1.0), view());
198 /*! Is called from the DiagramViews MouseMoved() when no message is being
199 dragged, but the mouse has moved above the box
202 DiagramBox::MouseOver(BPoint point
, uint32 transit
)
204 D_MOUSE(("DiagramBox::MouseOver()\n"));
205 DiagramItem
*last
= _LastItemUnder();
206 if (last
&& (transit
== B_EXITED_VIEW
)) {
207 last
->MouseOver(point
, B_EXITED_VIEW
);
210 DiagramItem
*item
= ItemUnder(point
);
214 last
->MouseOver(point
, B_EXITED_VIEW
);
215 item
->MouseOver(point
, B_ENTERED_VIEW
);
217 item
->MouseOver(point
, B_INSIDE_VIEW
);
220 last
->MouseOver(point
, B_EXITED_VIEW
);
225 /*! Is called from the DiagramViews MouseMoved() when a message is being
226 dragged over the DiagramBox
229 DiagramBox::MessageDragged(BPoint point
, uint32 transit
, const BMessage
*message
)
231 D_MOUSE(("DiagramBox::MessageDragged()\n"));
232 DiagramItem
*last
= _LastItemUnder();
233 if (last
&& (transit
== B_EXITED_VIEW
)) {
234 last
->MessageDragged(point
, B_EXITED_VIEW
, message
);
237 DiagramItem
*item
= ItemUnder(point
);
241 last
->MessageDragged(point
, B_EXITED_VIEW
, message
);
242 item
->MessageDragged(point
, B_ENTERED_VIEW
, message
);
244 item
->MessageDragged(point
, B_INSIDE_VIEW
, message
);
247 last
->MessageDragged(point
, B_EXITED_VIEW
, message
);
248 if (message
->what
== M_WIRE_DRAGGED
)
249 view()->trackWire(point
);
254 /*! Is called from the DiagramViews MessageReceived() function when a
255 message has been dropped on the DiagramBox
258 DiagramBox::MessageDropped(BPoint point
, BMessage
*message
)
260 D_METHOD(("DiagramBox::MessageDropped()\n"));
261 DiagramItem
*item
= ItemUnder(point
);
263 item
->MessageDropped(point
, message
);
269 // #pragma mark - operations (public)
272 /*! Moves the box by a given amount, and returns in updateRegion the
273 frames of wires impacted by the move
276 DiagramBox::MoveBy(float x
, float y
, BRegion
*wireRegion
)
278 D_METHOD(("DiagramBox::MoveBy()\n"));
282 for (uint32 i
= 0; i
< CountItems(); i
++) {
283 DiagramEndPoint
*endPoint
= dynamic_cast<DiagramEndPoint
*>(ItemAt(i
));
285 endPoint
->MoveBy(x
, y
, wireRegion
);
288 wireRegion
->Include(fFrame
);
289 fFrame
.OffsetBy(x
, y
);
290 wireRegion
->Include(fFrame
);
293 fFrame
.OffsetBy(x
, y
);
300 //! Resizes the boxes frame without doing any updating
302 DiagramBox::ResizeBy(float horizontal
, float vertical
)
304 D_METHOD(("DiagramBox::ResizeBy()\n"));
305 fFrame
.right
+= horizontal
;
306 fFrame
.bottom
+= vertical
;
310 // #pragma mark - internal operations (private)
313 //! Is called by the DiagramView when added
315 DiagramBox::_SetOwner(DiagramView
*owner
)
317 D_METHOD(("DiagramBox::_SetOwner()\n"));
319 for (uint32 i
= 0; i
< CountItems(DiagramItem::M_ENDPOINT
); i
++) {
320 DiagramItem
*item
= ItemAt(i
);
321 item
->_SetOwner(m_view
);
323 item
->attachedToDiagram();