1*c284bb0fSMatt Madia /*
2*c284bb0fSMatt Madia * Copyright (c) 1999-2000, Eric Moon.
3*c284bb0fSMatt Madia * All rights reserved.
4*c284bb0fSMatt Madia *
5*c284bb0fSMatt Madia * Redistribution and use in source and binary forms, with or without
6*c284bb0fSMatt Madia * modification, are permitted provided that the following conditions
7*c284bb0fSMatt Madia * are met:
8*c284bb0fSMatt Madia *
9*c284bb0fSMatt Madia * 1. Redistributions of source code must retain the above copyright
10*c284bb0fSMatt Madia * notice, this list of conditions, and the following disclaimer.
11*c284bb0fSMatt Madia *
12*c284bb0fSMatt Madia * 2. Redistributions in binary form must reproduce the above copyright
13*c284bb0fSMatt Madia * notice, this list of conditions, and the following disclaimer in the
14*c284bb0fSMatt Madia * documentation and/or other materials provided with the distribution.
15*c284bb0fSMatt Madia *
16*c284bb0fSMatt Madia * 3. The name of the author may not be used to endorse or promote products
17*c284bb0fSMatt Madia * derived from this software without specific prior written permission.
18*c284bb0fSMatt Madia *
19*c284bb0fSMatt Madia * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
20*c284bb0fSMatt Madia * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21*c284bb0fSMatt Madia * OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22*c284bb0fSMatt Madia * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
23*c284bb0fSMatt Madia * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24*c284bb0fSMatt Madia * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25*c284bb0fSMatt Madia * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26*c284bb0fSMatt Madia * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
27*c284bb0fSMatt Madia * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28*c284bb0fSMatt Madia * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29*c284bb0fSMatt Madia */
30*c284bb0fSMatt Madia
31*c284bb0fSMatt Madia
32a0795c6fSMarcus Overhagen // DiagramItemGroup.cpp
33a0795c6fSMarcus Overhagen
34595c89bcSAxel Dörfler /*! \class DiagramItemGroup.
35595c89bcSAxel Dörfler \brief Basic class for managing and accessing DiagramItem objects.
36595c89bcSAxel Dörfler
37595c89bcSAxel Dörfler Objects of this class can manage one or more of the DiagramItem
38595c89bcSAxel Dörfler type M_BOX, M_WIRE and M_ENDPOINT. Many methods let you specify
39595c89bcSAxel Dörfler which type of item you want to deal with.
40595c89bcSAxel Dörfler */
41595c89bcSAxel Dörfler
42a0795c6fSMarcus Overhagen #include "DiagramItemGroup.h"
43a0795c6fSMarcus Overhagen #include "DiagramItem.h"
44a0795c6fSMarcus Overhagen
45a0795c6fSMarcus Overhagen #include <Region.h>
46a0795c6fSMarcus Overhagen
47a0795c6fSMarcus Overhagen __USE_CORTEX_NAMESPACE
48a0795c6fSMarcus Overhagen
49a0795c6fSMarcus Overhagen #include <Debug.h>
50a0795c6fSMarcus Overhagen #define D_METHOD(x) //PRINT (x)
51a0795c6fSMarcus Overhagen
52a0795c6fSMarcus Overhagen
DiagramItemGroup(uint32 acceptedTypes,bool multiSelection)53595c89bcSAxel Dörfler DiagramItemGroup::DiagramItemGroup(uint32 acceptedTypes, bool multiSelection)
54595c89bcSAxel Dörfler :fBoxes(0),
55595c89bcSAxel Dörfler fWires(0),
56595c89bcSAxel Dörfler fEndPoints(0),
57595c89bcSAxel Dörfler fSelection(0),
58595c89bcSAxel Dörfler fTypes(acceptedTypes),
59595c89bcSAxel Dörfler fItemAlignment(1.0, 1.0),
60595c89bcSAxel Dörfler fMultiSelection(multiSelection),
61595c89bcSAxel Dörfler fLastItemUnder(0)
62a0795c6fSMarcus Overhagen {
63a0795c6fSMarcus Overhagen D_METHOD(("DiagramItemGroup::DiagramItemGroup()\n"));
64595c89bcSAxel Dörfler fSelection = new BList(1);
65a0795c6fSMarcus Overhagen }
66a0795c6fSMarcus Overhagen
67595c89bcSAxel Dörfler
~DiagramItemGroup()68a0795c6fSMarcus Overhagen DiagramItemGroup::~DiagramItemGroup()
69a0795c6fSMarcus Overhagen {
70a0795c6fSMarcus Overhagen D_METHOD(("DiagramItemGroup::~DiagramItemGroup()\n"));
71595c89bcSAxel Dörfler
72c8fe1746SKarsten Heimrich int32 count = 0;
73595c89bcSAxel Dörfler if (fWires && (fTypes & DiagramItem::M_WIRE)) {
74c8fe1746SKarsten Heimrich count = fWires->CountItems();
758f30a89dSKarsten Heimrich for (int32 i = 0; i < count; ++i)
768f30a89dSKarsten Heimrich delete static_cast<DiagramItem*>(fWires->ItemAt(i));
77595c89bcSAxel Dörfler delete fWires;
78a0795c6fSMarcus Overhagen }
79595c89bcSAxel Dörfler
80c8fe1746SKarsten Heimrich if (fBoxes && (fTypes & DiagramItem::M_BOX)) {
81c8fe1746SKarsten Heimrich count = fBoxes->CountItems();
828f30a89dSKarsten Heimrich for (int32 i = 0; i < count; ++i)
838f30a89dSKarsten Heimrich delete static_cast<DiagramItem*>(fBoxes->ItemAt(i));
84c8fe1746SKarsten Heimrich delete fBoxes;
85c8fe1746SKarsten Heimrich }
86c8fe1746SKarsten Heimrich
87595c89bcSAxel Dörfler if (fEndPoints && (fTypes & DiagramItem::M_ENDPOINT)) {
88c8fe1746SKarsten Heimrich count = fEndPoints->CountItems();
898f30a89dSKarsten Heimrich for (int32 i = 0; i < count; ++i)
908f30a89dSKarsten Heimrich delete static_cast<DiagramItem*>(fEndPoints->ItemAt(i));
91595c89bcSAxel Dörfler delete fEndPoints;
92a0795c6fSMarcus Overhagen }
93c8fe1746SKarsten Heimrich
94c8fe1746SKarsten Heimrich if (fSelection)
95c8fe1746SKarsten Heimrich delete fSelection;
96a0795c6fSMarcus Overhagen }
97a0795c6fSMarcus Overhagen
98a0795c6fSMarcus Overhagen
99595c89bcSAxel Dörfler // #pragma mark - item accessors
100595c89bcSAxel Dörfler
101595c89bcSAxel Dörfler
1025680c33eSIngo Weinhold /*! Returns the number of items in the group (optionally only those
1035680c33eSIngo Weinhold of the given type \param whichType)
1045680c33eSIngo Weinhold */
105595c89bcSAxel Dörfler uint32
CountItems(uint32 whichType) const106595c89bcSAxel Dörfler DiagramItemGroup::CountItems(uint32 whichType) const
107a0795c6fSMarcus Overhagen {
108595c89bcSAxel Dörfler D_METHOD(("DiagramItemGroup::CountItems()\n"));
109a0795c6fSMarcus Overhagen uint32 count = 0;
110595c89bcSAxel Dörfler if (whichType & fTypes) {
111595c89bcSAxel Dörfler if (whichType & DiagramItem::M_BOX) {
112595c89bcSAxel Dörfler if (fBoxes)
113595c89bcSAxel Dörfler count += fBoxes->CountItems();
114595c89bcSAxel Dörfler }
115595c89bcSAxel Dörfler
116595c89bcSAxel Dörfler if (whichType & DiagramItem::M_WIRE) {
117595c89bcSAxel Dörfler if (fWires)
118595c89bcSAxel Dörfler count += fWires->CountItems();
119595c89bcSAxel Dörfler }
120595c89bcSAxel Dörfler
121595c89bcSAxel Dörfler if (whichType & DiagramItem::M_ENDPOINT) {
122595c89bcSAxel Dörfler if (fEndPoints)
123595c89bcSAxel Dörfler count += fEndPoints->CountItems();
124a0795c6fSMarcus Overhagen }
125a0795c6fSMarcus Overhagen }
126595c89bcSAxel Dörfler
127a0795c6fSMarcus Overhagen return count;
128a0795c6fSMarcus Overhagen }
129a0795c6fSMarcus Overhagen
130595c89bcSAxel Dörfler
131595c89bcSAxel Dörfler /*! Returns a pointer to the item in the lists which is
132595c89bcSAxel Dörfler at the given index; if none is found, this function
133595c89bcSAxel Dörfler returns 0
134595c89bcSAxel Dörfler */
135595c89bcSAxel Dörfler DiagramItem*
ItemAt(uint32 index,uint32 whichType) const136595c89bcSAxel Dörfler DiagramItemGroup::ItemAt(uint32 index, uint32 whichType) const
137a0795c6fSMarcus Overhagen {
138595c89bcSAxel Dörfler D_METHOD(("DiagramItemGroup::ItemAt()\n"));
139595c89bcSAxel Dörfler if (fTypes & whichType) {
140595c89bcSAxel Dörfler if (whichType & DiagramItem::M_BOX) {
141595c89bcSAxel Dörfler if (fBoxes && (index < CountItems(DiagramItem::M_BOX)))
142595c89bcSAxel Dörfler return static_cast<DiagramItem *>(fBoxes->ItemAt(index));
143a0795c6fSMarcus Overhagen else
144595c89bcSAxel Dörfler index -= CountItems(DiagramItem::M_BOX);
145a0795c6fSMarcus Overhagen }
146595c89bcSAxel Dörfler
147595c89bcSAxel Dörfler if (whichType & DiagramItem::M_WIRE) {
148595c89bcSAxel Dörfler if (fWires && (index < CountItems(DiagramItem::M_WIRE)))
149595c89bcSAxel Dörfler return static_cast<DiagramItem *>(fWires->ItemAt(index));
150a0795c6fSMarcus Overhagen else
151595c89bcSAxel Dörfler index -= CountItems(DiagramItem::M_WIRE);
152595c89bcSAxel Dörfler }
153595c89bcSAxel Dörfler
154595c89bcSAxel Dörfler if (whichType & DiagramItem::M_ENDPOINT) {
155595c89bcSAxel Dörfler if (fEndPoints && (index < CountItems(DiagramItem::M_ENDPOINT)))
156595c89bcSAxel Dörfler return static_cast<DiagramItem *>(fEndPoints->ItemAt(index));
157a0795c6fSMarcus Overhagen }
158a0795c6fSMarcus Overhagen }
159595c89bcSAxel Dörfler
160a0795c6fSMarcus Overhagen return 0;
161a0795c6fSMarcus Overhagen }
162a0795c6fSMarcus Overhagen
163595c89bcSAxel Dörfler
164595c89bcSAxel Dörfler /*! This function returns the first box or endpoint found that
165595c89bcSAxel Dörfler contains the given \param point. For connections it looks at all
166595c89bcSAxel Dörfler wires that 'might' contain the point and calls their method
167595c89bcSAxel Dörfler howCloseTo() to find the one closest to the point.
168595c89bcSAxel Dörfler The lists should be sorted by selection time for proper results!
169595c89bcSAxel Dörfler */
170595c89bcSAxel Dörfler DiagramItem*
ItemUnder(BPoint point)171595c89bcSAxel Dörfler DiagramItemGroup::ItemUnder(BPoint point)
172a0795c6fSMarcus Overhagen {
173595c89bcSAxel Dörfler D_METHOD(("DiagramItemGroup::ItemUnder()\n"));
174595c89bcSAxel Dörfler if (fTypes & DiagramItem::M_BOX) {
175595c89bcSAxel Dörfler for (uint32 i = 0; i < CountItems(DiagramItem::M_BOX); i++) {
176595c89bcSAxel Dörfler DiagramItem *item = ItemAt(i, DiagramItem::M_BOX);
1775680c33eSIngo Weinhold if (item->Frame().Contains(point) && (item->howCloseTo(point) == 1.0)) {
178a0795c6fSMarcus Overhagen // DiagramItemGroup *group = dynamic_cast<DiagramItemGroup *>(item);
179595c89bcSAxel Dörfler return (fLastItemUnder = item);
180a0795c6fSMarcus Overhagen }
181a0795c6fSMarcus Overhagen }
182a0795c6fSMarcus Overhagen }
183595c89bcSAxel Dörfler
184595c89bcSAxel Dörfler if (fTypes & DiagramItem::M_WIRE) {
185a0795c6fSMarcus Overhagen float closest = 0.0;
186a0795c6fSMarcus Overhagen DiagramItem *closestItem = 0;
187595c89bcSAxel Dörfler for (uint32 i = 0; i < CountItems(DiagramItem::M_WIRE); i++) {
188595c89bcSAxel Dörfler DiagramItem *item = ItemAt(i, DiagramItem::M_WIRE);
1895680c33eSIngo Weinhold if (item->Frame().Contains(point)) {
190a0795c6fSMarcus Overhagen float howClose = item->howCloseTo(point);
191595c89bcSAxel Dörfler if (howClose > closest) {
192a0795c6fSMarcus Overhagen closestItem = item;
193a0795c6fSMarcus Overhagen if (howClose == 1.0)
194595c89bcSAxel Dörfler return (fLastItemUnder = item);
195a0795c6fSMarcus Overhagen closest = howClose;
196a0795c6fSMarcus Overhagen }
197a0795c6fSMarcus Overhagen }
198a0795c6fSMarcus Overhagen }
199595c89bcSAxel Dörfler
200a0795c6fSMarcus Overhagen if (closest > 0.5)
201595c89bcSAxel Dörfler return (fLastItemUnder = closestItem);
202a0795c6fSMarcus Overhagen }
203595c89bcSAxel Dörfler
204595c89bcSAxel Dörfler if (fTypes & DiagramItem::M_ENDPOINT) {
205595c89bcSAxel Dörfler for (uint32 i = 0; i < CountItems(DiagramItem::M_ENDPOINT); i++) {
206595c89bcSAxel Dörfler DiagramItem *item = ItemAt(i, DiagramItem::M_ENDPOINT);
2075680c33eSIngo Weinhold if (item->Frame().Contains(point) && (item->howCloseTo(point) == 1.0))
208595c89bcSAxel Dörfler return (fLastItemUnder = item);
209a0795c6fSMarcus Overhagen }
210a0795c6fSMarcus Overhagen }
211a0795c6fSMarcus Overhagen
212595c89bcSAxel Dörfler return (fLastItemUnder = 0); // no item was found!
213595c89bcSAxel Dörfler }
214a0795c6fSMarcus Overhagen
215595c89bcSAxel Dörfler
216595c89bcSAxel Dörfler // #pragma mark - item operations
217595c89bcSAxel Dörfler
218595c89bcSAxel Dörfler
219595c89bcSAxel Dörfler //! Adds an \param item to the group; returns true on success.
220595c89bcSAxel Dörfler bool
AddItem(DiagramItem * item)221595c89bcSAxel Dörfler DiagramItemGroup::AddItem(DiagramItem *item)
222a0795c6fSMarcus Overhagen {
223595c89bcSAxel Dörfler D_METHOD(("DiagramItemGroup::AddItem()\n"));
224595c89bcSAxel Dörfler if (item && (fTypes & item->type())) {
225c8fe1746SKarsten Heimrich if (item->m_group)
226c8fe1746SKarsten Heimrich item->m_group->RemoveItem(item);
227c8fe1746SKarsten Heimrich
228595c89bcSAxel Dörfler switch (item->type()) {
229a0795c6fSMarcus Overhagen case DiagramItem::M_BOX:
230595c89bcSAxel Dörfler if (!fBoxes)
231595c89bcSAxel Dörfler fBoxes = new BList();
232a0795c6fSMarcus Overhagen item->m_group = this;
233595c89bcSAxel Dörfler return fBoxes->AddItem(static_cast<void *>(item));
234595c89bcSAxel Dörfler
235a0795c6fSMarcus Overhagen case DiagramItem::M_WIRE:
236595c89bcSAxel Dörfler if (!fWires)
237595c89bcSAxel Dörfler fWires = new BList();
238a0795c6fSMarcus Overhagen item->m_group = this;
239595c89bcSAxel Dörfler return fWires->AddItem(static_cast<void *>(item));
240595c89bcSAxel Dörfler
241a0795c6fSMarcus Overhagen case DiagramItem::M_ENDPOINT:
242595c89bcSAxel Dörfler if (!fEndPoints)
243595c89bcSAxel Dörfler fEndPoints = new BList();
244a0795c6fSMarcus Overhagen item->m_group = this;
245595c89bcSAxel Dörfler return fEndPoints->AddItem(static_cast<void *>(item));
246a0795c6fSMarcus Overhagen }
247a0795c6fSMarcus Overhagen }
248595c89bcSAxel Dörfler
249a0795c6fSMarcus Overhagen return false;
250a0795c6fSMarcus Overhagen }
251a0795c6fSMarcus Overhagen
252595c89bcSAxel Dörfler
253595c89bcSAxel Dörfler //! Removes an \param item from the group; returns true on success.
254595c89bcSAxel Dörfler bool
RemoveItem(DiagramItem * item)255595c89bcSAxel Dörfler DiagramItemGroup::RemoveItem(DiagramItem* item)
256a0795c6fSMarcus Overhagen {
257595c89bcSAxel Dörfler D_METHOD(("DiagramItemGroup::RemoveItem()\n"));
258595c89bcSAxel Dörfler if (item && (fTypes & item->type())) {
259a0795c6fSMarcus Overhagen // reset the lastItemUnder-pointer if it pointed to this item
260595c89bcSAxel Dörfler if (fLastItemUnder == item)
261595c89bcSAxel Dörfler fLastItemUnder = 0;
262595c89bcSAxel Dörfler
263a0795c6fSMarcus Overhagen // remove it from the selection list if it was selected
264a0795c6fSMarcus Overhagen if (item->isSelected())
265595c89bcSAxel Dörfler fSelection->RemoveItem(static_cast<void *>(item));
266595c89bcSAxel Dörfler
267a0795c6fSMarcus Overhagen // try to remove the item from its list
268595c89bcSAxel Dörfler switch (item->type()) {
269a0795c6fSMarcus Overhagen case DiagramItem::M_BOX:
270595c89bcSAxel Dörfler if (fBoxes) {
271a0795c6fSMarcus Overhagen item->m_group = 0;
272595c89bcSAxel Dörfler return fBoxes->RemoveItem(static_cast<void *>(item));
273a0795c6fSMarcus Overhagen }
274595c89bcSAxel Dörfler break;
275595c89bcSAxel Dörfler
276a0795c6fSMarcus Overhagen case DiagramItem::M_WIRE:
277595c89bcSAxel Dörfler if (fWires) {
278a0795c6fSMarcus Overhagen item->m_group = 0;
279595c89bcSAxel Dörfler return fWires->RemoveItem(static_cast<void *>(item));
280a0795c6fSMarcus Overhagen }
281595c89bcSAxel Dörfler break;
282595c89bcSAxel Dörfler
283a0795c6fSMarcus Overhagen case DiagramItem::M_ENDPOINT:
284595c89bcSAxel Dörfler if (fEndPoints) {
285a0795c6fSMarcus Overhagen item->m_group = 0;
286595c89bcSAxel Dörfler return fEndPoints->RemoveItem(static_cast<void *>(item));
287a0795c6fSMarcus Overhagen }
288a0795c6fSMarcus Overhagen }
289a0795c6fSMarcus Overhagen }
290595c89bcSAxel Dörfler
291a0795c6fSMarcus Overhagen return false;
292a0795c6fSMarcus Overhagen }
293a0795c6fSMarcus Overhagen
294595c89bcSAxel Dörfler
295595c89bcSAxel Dörfler /*! Performs a quicksort on a list of items with the provided
296595c89bcSAxel Dörfler compare function (one is already defined in the DiagramItem
297595c89bcSAxel Dörfler implementation); can't handle more than one item type at a
298595c89bcSAxel Dörfler time!
299595c89bcSAxel Dörfler */
300595c89bcSAxel Dörfler void
SortItems(uint32 whichType,int (* compareFunc)(const void *,const void *))301595c89bcSAxel Dörfler DiagramItemGroup::SortItems(uint32 whichType,
302a0795c6fSMarcus Overhagen int (*compareFunc)(const void *, const void *))
303a0795c6fSMarcus Overhagen {
304595c89bcSAxel Dörfler D_METHOD(("DiagramItemGroup::SortItems()\n"));
305595c89bcSAxel Dörfler if ((whichType != DiagramItem::M_ANY) && (fTypes & whichType)) {
306595c89bcSAxel Dörfler switch (whichType) {
307a0795c6fSMarcus Overhagen case DiagramItem::M_BOX:
308595c89bcSAxel Dörfler if (fBoxes)
309595c89bcSAxel Dörfler fBoxes->SortItems(compareFunc);
310a0795c6fSMarcus Overhagen break;
311595c89bcSAxel Dörfler
312a0795c6fSMarcus Overhagen case DiagramItem::M_WIRE:
313595c89bcSAxel Dörfler if (fWires)
314595c89bcSAxel Dörfler fWires->SortItems(compareFunc);
315a0795c6fSMarcus Overhagen break;
316595c89bcSAxel Dörfler
317a0795c6fSMarcus Overhagen case DiagramItem::M_ENDPOINT:
318595c89bcSAxel Dörfler if (fEndPoints)
319595c89bcSAxel Dörfler fEndPoints->SortItems(compareFunc);
320a0795c6fSMarcus Overhagen break;
321a0795c6fSMarcus Overhagen }
322a0795c6fSMarcus Overhagen }
323a0795c6fSMarcus Overhagen }
324a0795c6fSMarcus Overhagen
325595c89bcSAxel Dörfler
3265680c33eSIngo Weinhold /*! Fires a Draw() command at all items of a specific type that
327595c89bcSAxel Dörfler intersect with the \param updateRect;
328595c89bcSAxel Dörfler items are drawn in reverse order; they should be sorted by
329595c89bcSAxel Dörfler selection time before this function gets called, so that
330595c89bcSAxel Dörfler the more recently selected item are drawn above others.
331595c89bcSAxel Dörfler */
332595c89bcSAxel Dörfler void
DrawItems(BRect updateRect,uint32 whichType,BRegion * updateRegion)333595c89bcSAxel Dörfler DiagramItemGroup::DrawItems(BRect updateRect, uint32 whichType, BRegion* updateRegion)
334a0795c6fSMarcus Overhagen {
335595c89bcSAxel Dörfler D_METHOD(("DiagramItemGroup::DrawItems()\n"));
336595c89bcSAxel Dörfler if (whichType & DiagramItem::M_WIRE) {
337595c89bcSAxel Dörfler for (int32 i = CountItems(DiagramItem::M_WIRE) - 1; i >= 0; i--) {
338595c89bcSAxel Dörfler DiagramItem *item = ItemAt(i, DiagramItem::M_WIRE);
3395680c33eSIngo Weinhold if (item->Frame().Intersects(updateRect))
3405680c33eSIngo Weinhold item->Draw(updateRect);
341a0795c6fSMarcus Overhagen }
342a0795c6fSMarcus Overhagen }
343595c89bcSAxel Dörfler
344595c89bcSAxel Dörfler if (whichType & DiagramItem::M_BOX) {
345595c89bcSAxel Dörfler for (int32 i = CountItems(DiagramItem::M_BOX) - 1; i >= 0; i--) {
346595c89bcSAxel Dörfler DiagramItem *item = ItemAt(i, DiagramItem::M_BOX);
3475680c33eSIngo Weinhold if (item && item->Frame().Intersects(updateRect)) {
3485680c33eSIngo Weinhold item->Draw(updateRect);
349a0795c6fSMarcus Overhagen if (updateRegion)
3505680c33eSIngo Weinhold updateRegion->Exclude(item->Frame());
351a0795c6fSMarcus Overhagen }
352a0795c6fSMarcus Overhagen }
353a0795c6fSMarcus Overhagen }
354595c89bcSAxel Dörfler
355595c89bcSAxel Dörfler if (whichType & DiagramItem::M_ENDPOINT) {
356595c89bcSAxel Dörfler for (int32 i = CountItems(DiagramItem::M_ENDPOINT) - 1; i >= 0; i--) {
357595c89bcSAxel Dörfler DiagramItem *item = ItemAt(i, DiagramItem::M_ENDPOINT);
3585680c33eSIngo Weinhold if (item && item->Frame().Intersects(updateRect))
3595680c33eSIngo Weinhold item->Draw(updateRect);
360a0795c6fSMarcus Overhagen }
361a0795c6fSMarcus Overhagen }
362a0795c6fSMarcus Overhagen }
363a0795c6fSMarcus Overhagen
364595c89bcSAxel Dörfler
365595c89bcSAxel Dörfler /*! Returns in outRegion the \param region of items that lay "over" the given
366595c89bcSAxel Dörfler DiagramItem in \param which; returns false if no items are above or the item
367595c89bcSAxel Dörfler doesn't exist.
368595c89bcSAxel Dörfler */
369595c89bcSAxel Dörfler bool
GetClippingAbove(DiagramItem * which,BRegion * region)370595c89bcSAxel Dörfler DiagramItemGroup::GetClippingAbove(DiagramItem *which, BRegion *region)
371a0795c6fSMarcus Overhagen {
372595c89bcSAxel Dörfler D_METHOD(("DiagramItemGroup::GetClippingAbove()\n"));
373a0795c6fSMarcus Overhagen bool found = false;
374595c89bcSAxel Dörfler if (which && region) {
375595c89bcSAxel Dörfler switch (which->type()) {
376a0795c6fSMarcus Overhagen case DiagramItem::M_BOX:
377a0795c6fSMarcus Overhagen {
378595c89bcSAxel Dörfler int32 index = fBoxes->IndexOf(which);
379595c89bcSAxel Dörfler if (index >= 0) { // the item was found
3805680c33eSIngo Weinhold BRect r = which->Frame();
381595c89bcSAxel Dörfler for (int32 i = 0; i < index; i++) {
382595c89bcSAxel Dörfler DiagramItem *item = ItemAt(i, DiagramItem::M_BOX);
3835680c33eSIngo Weinhold if (item && item->Frame().Intersects(r)) {
3845680c33eSIngo Weinhold region->Include(item->Frame() & r);
385a0795c6fSMarcus Overhagen found = true;
386a0795c6fSMarcus Overhagen }
387a0795c6fSMarcus Overhagen }
388a0795c6fSMarcus Overhagen }
389a0795c6fSMarcus Overhagen break;
390a0795c6fSMarcus Overhagen }
391595c89bcSAxel Dörfler
392a0795c6fSMarcus Overhagen case DiagramItem::M_WIRE:
393a0795c6fSMarcus Overhagen {
3945680c33eSIngo Weinhold BRect r = which->Frame();
395595c89bcSAxel Dörfler for (uint32 i = 0; i < CountItems(DiagramItem::M_BOX); i++) {
396595c89bcSAxel Dörfler DiagramItem *item = ItemAt(i, DiagramItem::M_BOX);
3975680c33eSIngo Weinhold if (item && item->Frame().Intersects(r)) {
3985680c33eSIngo Weinhold region->Include(item->Frame() & r);
399a0795c6fSMarcus Overhagen found = true;
400a0795c6fSMarcus Overhagen }
401a0795c6fSMarcus Overhagen }
402a0795c6fSMarcus Overhagen break;
403a0795c6fSMarcus Overhagen }
404a0795c6fSMarcus Overhagen }
405a0795c6fSMarcus Overhagen }
406595c89bcSAxel Dörfler
407a0795c6fSMarcus Overhagen return found;
408a0795c6fSMarcus Overhagen }
409a0795c6fSMarcus Overhagen
410a0795c6fSMarcus Overhagen
411595c89bcSAxel Dörfler // #pragma mark - selection accessors
412595c89bcSAxel Dörfler
413595c89bcSAxel Dörfler
414595c89bcSAxel Dörfler /*! Returns the type of DiagramItems in the current selection
415595c89bcSAxel Dörfler (currently only one type at a time is supported!)
416595c89bcSAxel Dörfler */
417595c89bcSAxel Dörfler uint32
SelectedType() const418595c89bcSAxel Dörfler DiagramItemGroup::SelectedType() const
419a0795c6fSMarcus Overhagen {
420595c89bcSAxel Dörfler D_METHOD(("DiagramItemGroup::SelectedType()\n"));
421595c89bcSAxel Dörfler if (CountSelectedItems() > 0)
422595c89bcSAxel Dörfler return SelectedItemAt(0)->type();
423595c89bcSAxel Dörfler
424a0795c6fSMarcus Overhagen return 0;
425a0795c6fSMarcus Overhagen }
426a0795c6fSMarcus Overhagen
427595c89bcSAxel Dörfler
428595c89bcSAxel Dörfler //! Returns the number of items in the current selection
429595c89bcSAxel Dörfler uint32
CountSelectedItems() const430595c89bcSAxel Dörfler DiagramItemGroup::CountSelectedItems() const
431a0795c6fSMarcus Overhagen {
432595c89bcSAxel Dörfler D_METHOD(("DiagramItemGroup::CountSelectedItems()\n"));
433595c89bcSAxel Dörfler if (fSelection)
434595c89bcSAxel Dörfler return fSelection->CountItems();
435595c89bcSAxel Dörfler
436a0795c6fSMarcus Overhagen return 0;
437a0795c6fSMarcus Overhagen }
438a0795c6fSMarcus Overhagen
439595c89bcSAxel Dörfler
440595c89bcSAxel Dörfler /*! Returns a pointer to the item in the list which is
441595c89bcSAxel Dörfler at the given \param index; if none is found, this function
442595c89bcSAxel Dörfler returns 0
443595c89bcSAxel Dörfler */
444595c89bcSAxel Dörfler DiagramItem*
SelectedItemAt(uint32 index) const445595c89bcSAxel Dörfler DiagramItemGroup::SelectedItemAt(uint32 index) const
446a0795c6fSMarcus Overhagen {
447595c89bcSAxel Dörfler D_METHOD(("DiagramItemGroup::SelectedItemAt()\n"));
448595c89bcSAxel Dörfler if (fSelection)
449595c89bcSAxel Dörfler return static_cast<DiagramItem *>(fSelection->ItemAt(index));
450595c89bcSAxel Dörfler
451a0795c6fSMarcus Overhagen return 0;
452a0795c6fSMarcus Overhagen }
453a0795c6fSMarcus Overhagen
454a0795c6fSMarcus Overhagen
455595c89bcSAxel Dörfler // #pragma mark - selection related operations
456595c89bcSAxel Dörfler
457595c89bcSAxel Dörfler
458595c89bcSAxel Dörfler /*! Selects an item, optionally replacing the complete former
459595c89bcSAxel Dörfler selection. If the type of the item to be selected differs
460595c89bcSAxel Dörfler from the type of items currently selected, this methods
461595c89bcSAxel Dörfler automatically replaces the former selection
462595c89bcSAxel Dörfler */
463595c89bcSAxel Dörfler bool
SelectItem(DiagramItem * which,bool deselectOthers)464595c89bcSAxel Dörfler DiagramItemGroup::SelectItem(DiagramItem* which, bool deselectOthers)
465a0795c6fSMarcus Overhagen {
466595c89bcSAxel Dörfler D_METHOD(("DiagramItemGroup::SelectItem()\n"));
467a0795c6fSMarcus Overhagen bool selectionChanged = false;
468595c89bcSAxel Dörfler if (which && !which->isSelected() && which->isSelectable()) {
469a0795c6fSMarcus Overhagen // check if the item's type is the same as of the other
470a0795c6fSMarcus Overhagen // selected items
471595c89bcSAxel Dörfler if (fMultiSelection) {
472595c89bcSAxel Dörfler if (which->type() != SelectedType())
473a0795c6fSMarcus Overhagen deselectOthers = true;
474a0795c6fSMarcus Overhagen }
475a0795c6fSMarcus Overhagen
476a0795c6fSMarcus Overhagen // check if the former selection has to be deselected
477595c89bcSAxel Dörfler if (deselectOthers || !fMultiSelection) {
478595c89bcSAxel Dörfler while (CountSelectedItems() > 0)
479595c89bcSAxel Dörfler DeselectItem(SelectedItemAt(0));
480a0795c6fSMarcus Overhagen }
481a0795c6fSMarcus Overhagen
482a0795c6fSMarcus Overhagen // select the item
483595c89bcSAxel Dörfler if (deselectOthers || CountSelectedItems() == 0)
484a0795c6fSMarcus Overhagen which->select();
485a0795c6fSMarcus Overhagen else
486a0795c6fSMarcus Overhagen which->selectAdding();
487595c89bcSAxel Dörfler
488595c89bcSAxel Dörfler fSelection->AddItem(which);
489a0795c6fSMarcus Overhagen selectionChanged = true;
490a0795c6fSMarcus Overhagen }
491a0795c6fSMarcus Overhagen
492a0795c6fSMarcus Overhagen // resort the lists if necessary
493595c89bcSAxel Dörfler if (selectionChanged) {
494595c89bcSAxel Dörfler SortItems(which->type(), compareSelectionTime);
495595c89bcSAxel Dörfler SortSelectedItems(compareSelectionTime);
496a0795c6fSMarcus Overhagen return true;
497a0795c6fSMarcus Overhagen }
498595c89bcSAxel Dörfler
499a0795c6fSMarcus Overhagen return false;
500a0795c6fSMarcus Overhagen }
501a0795c6fSMarcus Overhagen
502595c89bcSAxel Dörfler
503595c89bcSAxel Dörfler //! Simply deselects one item
504595c89bcSAxel Dörfler bool
DeselectItem(DiagramItem * which)505595c89bcSAxel Dörfler DiagramItemGroup::DeselectItem(DiagramItem* which)
506a0795c6fSMarcus Overhagen {
507595c89bcSAxel Dörfler D_METHOD(("DiagramItemGroup::DeselectItem()\n"));
508595c89bcSAxel Dörfler if (which && which->isSelected()) {
509595c89bcSAxel Dörfler fSelection->RemoveItem(which);
510a0795c6fSMarcus Overhagen which->deselect();
511595c89bcSAxel Dörfler SortItems(which->type(), compareSelectionTime);
512595c89bcSAxel Dörfler SortSelectedItems(compareSelectionTime);
513a0795c6fSMarcus Overhagen return true;
514a0795c6fSMarcus Overhagen }
515595c89bcSAxel Dörfler
516a0795c6fSMarcus Overhagen return false;
517a0795c6fSMarcus Overhagen }
518a0795c6fSMarcus Overhagen
519595c89bcSAxel Dörfler
520595c89bcSAxel Dörfler //! Selects all items of the given \param itemType
521595c89bcSAxel Dörfler bool
SelectAll(uint32 itemType)522595c89bcSAxel Dörfler DiagramItemGroup::SelectAll(uint32 itemType)
523a0795c6fSMarcus Overhagen {
524595c89bcSAxel Dörfler D_METHOD(("DiagramItemGroup::SelectAll()\n"));
525a0795c6fSMarcus Overhagen bool selectionChanged = false;
526595c89bcSAxel Dörfler if (fTypes & itemType) {
527595c89bcSAxel Dörfler for (uint32 i = 0; i < CountItems(itemType); i++) {
528595c89bcSAxel Dörfler if (SelectItem(ItemAt(i, itemType), false))
529a0795c6fSMarcus Overhagen selectionChanged = true;
530a0795c6fSMarcus Overhagen }
531a0795c6fSMarcus Overhagen }
532595c89bcSAxel Dörfler
533a0795c6fSMarcus Overhagen return selectionChanged;
534a0795c6fSMarcus Overhagen }
535a0795c6fSMarcus Overhagen
536595c89bcSAxel Dörfler
537595c89bcSAxel Dörfler //! Deselects all items of the given \param itemType
538595c89bcSAxel Dörfler bool
DeselectAll(uint32 itemType)539595c89bcSAxel Dörfler DiagramItemGroup::DeselectAll(uint32 itemType)
540a0795c6fSMarcus Overhagen {
541595c89bcSAxel Dörfler D_METHOD(("DiagramItemGroup::DeselectAll()\n"));
542a0795c6fSMarcus Overhagen bool selectionChanged = false;
543595c89bcSAxel Dörfler if (fTypes & itemType) {
544595c89bcSAxel Dörfler for (uint32 i = 0; i < CountItems(itemType); i++) {
545595c89bcSAxel Dörfler if (DeselectItem(ItemAt(i, itemType)))
546a0795c6fSMarcus Overhagen selectionChanged = true;
547a0795c6fSMarcus Overhagen }
548a0795c6fSMarcus Overhagen }
549595c89bcSAxel Dörfler
550a0795c6fSMarcus Overhagen return selectionChanged;
551a0795c6fSMarcus Overhagen }
552a0795c6fSMarcus Overhagen
553595c89bcSAxel Dörfler
554595c89bcSAxel Dörfler /*! Performs a quicksort on the list of selected items with the
555595c89bcSAxel Dörfler provided compare function (one is already defined in the DiagramItem
556595c89bcSAxel Dörfler implementation)
557595c89bcSAxel Dörfler */
558595c89bcSAxel Dörfler void
SortSelectedItems(int (* compareFunc)(const void *,const void *))559595c89bcSAxel Dörfler DiagramItemGroup::SortSelectedItems(int (*compareFunc)(const void *, const void *))
560a0795c6fSMarcus Overhagen {
561595c89bcSAxel Dörfler D_METHOD(("DiagramItemGroup::SortSelectedItems()\n"));
562595c89bcSAxel Dörfler fSelection->SortItems(compareFunc);
563a0795c6fSMarcus Overhagen }
564a0795c6fSMarcus Overhagen
565595c89bcSAxel Dörfler
566595c89bcSAxel Dörfler /*! Moves all selected items by a given amount, taking
567595c89bcSAxel Dörfler item alignment into account; in updateRegion the areas
568595c89bcSAxel Dörfler that still require updating by the caller are returned
569595c89bcSAxel Dörfler */
570595c89bcSAxel Dörfler void
DragSelectionBy(float x,float y,BRegion * updateRegion)571595c89bcSAxel Dörfler DiagramItemGroup::DragSelectionBy(float x, float y, BRegion* updateRegion)
572a0795c6fSMarcus Overhagen {
573595c89bcSAxel Dörfler D_METHOD(("DiagramItemGroup::DragSelectionBy()\n"));
574595c89bcSAxel Dörfler if (SelectedType() == DiagramItem::M_BOX) {
575595c89bcSAxel Dörfler Align(&x, &y);
576595c89bcSAxel Dörfler if ((x != 0) || (y != 0)) {
577595c89bcSAxel Dörfler for (int32 i = CountSelectedItems() - 1; i >= 0; i--) {
578595c89bcSAxel Dörfler DiagramItem *item = dynamic_cast<DiagramItem *>(SelectedItemAt(i));
579a0795c6fSMarcus Overhagen if (item->isDraggable())
5805680c33eSIngo Weinhold item->MoveBy(x, y, updateRegion);
581a0795c6fSMarcus Overhagen }
582a0795c6fSMarcus Overhagen }
583a0795c6fSMarcus Overhagen }
584a0795c6fSMarcus Overhagen }
585595c89bcSAxel Dörfler
586595c89bcSAxel Dörfler
587595c89bcSAxel Dörfler //! Removes all selected items from the group
588595c89bcSAxel Dörfler void
RemoveSelection()589595c89bcSAxel Dörfler DiagramItemGroup::RemoveSelection()
590595c89bcSAxel Dörfler {
591595c89bcSAxel Dörfler D_METHOD(("DiagramItemGroup::RemoveSelection()\n"));
592595c89bcSAxel Dörfler for (uint32 i = 0; i < CountSelectedItems(); i++)
593595c89bcSAxel Dörfler RemoveItem(SelectedItemAt(i));
594a0795c6fSMarcus Overhagen }
595a0795c6fSMarcus Overhagen
596a0795c6fSMarcus Overhagen
597595c89bcSAxel Dörfler // #pragma mark - alignment related accessors & operations
598a0795c6fSMarcus Overhagen
599595c89bcSAxel Dörfler
600595c89bcSAxel Dörfler void
GetItemAlignment(float * horizontal,float * vertical)601595c89bcSAxel Dörfler DiagramItemGroup::GetItemAlignment(float *horizontal, float *vertical)
602a0795c6fSMarcus Overhagen {
603595c89bcSAxel Dörfler D_METHOD(("DiagramItemGroup::GetItemAlignment()\n"));
604a0795c6fSMarcus Overhagen if (horizontal)
605595c89bcSAxel Dörfler *horizontal = fItemAlignment.x;
606a0795c6fSMarcus Overhagen if (vertical)
607595c89bcSAxel Dörfler *vertical = fItemAlignment.y;
608a0795c6fSMarcus Overhagen }
609a0795c6fSMarcus Overhagen
610595c89bcSAxel Dörfler
611595c89bcSAxel Dörfler //! Align a given point(\param x, \param y) to the current grid
612595c89bcSAxel Dörfler void
Align(float * x,float * y) const613595c89bcSAxel Dörfler DiagramItemGroup::Align(float *x, float *y) const
614a0795c6fSMarcus Overhagen {
615595c89bcSAxel Dörfler D_METHOD(("DiagramItemGroup::Align()\n"));
616595c89bcSAxel Dörfler *x = ((int)*x / (int)fItemAlignment.x) * fItemAlignment.x;
617595c89bcSAxel Dörfler *y = ((int)*y / (int)fItemAlignment.y) * fItemAlignment.y;
618a0795c6fSMarcus Overhagen }
619a0795c6fSMarcus Overhagen
620595c89bcSAxel Dörfler
621595c89bcSAxel Dörfler //! Align a given \param point to the current grid
622595c89bcSAxel Dörfler BPoint
Align(BPoint point) const623595c89bcSAxel Dörfler DiagramItemGroup::Align(BPoint point) const
624a0795c6fSMarcus Overhagen {
625595c89bcSAxel Dörfler D_METHOD(("DiagramItemGroup::Align()\n"));
626a0795c6fSMarcus Overhagen float x = point.x, y = point.y;
627595c89bcSAxel Dörfler Align(&x, &y);
628a0795c6fSMarcus Overhagen return BPoint(x, y);
629a0795c6fSMarcus Overhagen }
630