1 /*
2 * Copyright (c) 1999-2000, Eric Moon.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions, and the following disclaimer.
11 *
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.
15 *
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.
18 *
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.
29 */
30
31
32 // DormantNodeView.cpp
33
34 #include "DormantNodeView.h"
35 // DormantNodeView
36 #include "DormantNodeWindow.h"
37 #include "DormantNodeListItem.h"
38 // InfoWindow
39 #include "InfoWindowManager.h"
40
41 // Interface Kit
42 #include <Deskbar.h>
43 #include <Region.h>
44 #include <Screen.h>
45 #include <ScrollBar.h>
46 // Media Kit
47 #include <MediaRoster.h>
48 // Storage Kit
49 #include <Mime.h>
50
51 __USE_CORTEX_NAMESPACE
52
53 #include <Debug.h>
54 #define D_ALLOC(x) //PRINT (x) // ctor/dtor
55 #define D_HOOK(x) //PRINT (x) // BListView impl.
56 #define D_MESSAGE(x) //PRINT (x) // MessageReceived()
57 #define D_INTERNAL(x) //PRINT (x) // internal operations
58
59 // -------------------------------------------------------- //
60 // ctor/dtor (public)
61 // -------------------------------------------------------- //
62
DormantNodeView(BRect frame,const char * name,uint32 resizeMode)63 DormantNodeView::DormantNodeView(
64 BRect frame,
65 const char *name,
66 uint32 resizeMode)
67 : BListView(frame, name, B_SINGLE_SELECTION_LIST, resizeMode),
68 m_lastItemUnder(0) {
69 D_ALLOC(("DormantNodeView::DormantNodeView()\n"));
70
71 }
72
~DormantNodeView()73 DormantNodeView::~DormantNodeView() {
74 D_ALLOC(("DormantNodeView::~DormantNodeView()\n"));
75
76 }
77
78 // -------------------------------------------------------- //
79 // BListView impl. (public)
80 // -------------------------------------------------------- //
81
AttachedToWindow()82 void DormantNodeView::AttachedToWindow() {
83 D_HOOK(("DormantNodeView::AttachedToWindow()\n"));
84
85 // populate the list
86 _populateList();
87
88 // Start watching the MediaRoster for flavor changes
89 BMediaRoster *roster = BMediaRoster::CurrentRoster();
90 if (roster) {
91 BMessenger messenger(this, Window());
92 roster->StartWatching(messenger, B_MEDIA_FLAVORS_CHANGED);
93 }
94 }
95
DetachedFromWindow()96 void DormantNodeView::DetachedFromWindow() {
97 D_HOOK(("DormantNodeView::DetachedFromWindow()\n"));
98
99 // delete the lists contents
100 _freeList();
101
102 // Stop watching the MediaRoster for flavor changes
103 BMediaRoster *roster = BMediaRoster::CurrentRoster();
104 if (roster) {
105 BMessenger messenger(this, Window());
106 roster->StopWatching(messenger, B_MEDIA_FLAVORS_CHANGED);
107 }
108 }
109
GetPreferredSize(float * width,float * height)110 void DormantNodeView::GetPreferredSize(
111 float* width,
112 float* height) {
113 D_HOOK(("DormantNodeView::GetPreferredSize()\n"));
114
115 // calculate the accumulated size of all list items
116 *width = 0;
117 *height = 0;
118 for (int32 i = 0; i < CountItems(); i++) {
119 DormantNodeListItem *item;
120 item = dynamic_cast<DormantNodeListItem *>(ItemAt(i));
121 if (item) {
122 BRect r = item->getRealFrame(be_plain_font);
123 if (r.Width() > *width) {
124 *width = r.Width();
125 }
126 *height += r.Height() + 1.0;
127 }
128 }
129 }
130
MessageReceived(BMessage * message)131 void DormantNodeView::MessageReceived(
132 BMessage *message) {
133 D_MESSAGE(("DormantNodeView::MessageReceived()\n"));
134
135 switch (message->what) {
136 case B_MEDIA_FLAVORS_CHANGED: {
137 D_MESSAGE((" -> B_MEDIA_FLAVORS_CHANGED\n"));
138
139 // init & re-populate the list
140 int32 addOnID = 0;
141 if (message->FindInt32("be:addon_id", &addOnID) != B_OK) {
142 D_MESSAGE((" -> messages doesn't contain 'be:addon_id'!\n"));
143 return;
144 }
145 _updateList(addOnID);
146 break;
147 }
148 case InfoWindowManager::M_INFO_WINDOW_REQUESTED: {
149 D_MESSAGE((" -> InfoWindowManager::M_INFO_WINDOW_REQUESTED)\n"));
150
151 DormantNodeListItem *item;
152 item = dynamic_cast<DormantNodeListItem *>(ItemAt(CurrentSelection()));
153 if (item) {
154 InfoWindowManager *manager = InfoWindowManager::Instance();
155 if (manager && manager->Lock()) {
156 manager->openWindowFor(item->info());
157 manager->Unlock();
158 }
159 }
160 break;
161 }
162 default: {
163 _inherited::MessageReceived(message);
164 }
165 }
166 }
167
MouseDown(BPoint point)168 void DormantNodeView::MouseDown(
169 BPoint point) {
170 D_HOOK(("DormantNodeView::MouseDown()\n"));
171
172 BMessage* message = Window()->CurrentMessage();
173 int32 buttons = message->FindInt32("buttons");
174 if (buttons == B_SECONDARY_MOUSE_BUTTON) {
175 int32 index;
176 if ((index = IndexOf(point)) >= 0) {
177 DormantNodeListItem *item = dynamic_cast<DormantNodeListItem *>(ItemAt(index));
178 if (item) {
179 Select(index);
180 BRect r = item->getRealFrame(be_plain_font);
181 if (r.Contains(point)) {
182 item->showContextMenu(point, this);
183 }
184 }
185 }
186 }
187
188 _inherited::MouseDown(point);
189 }
190
MouseMoved(BPoint point,uint32 transit,const BMessage * message)191 void DormantNodeView::MouseMoved(
192 BPoint point,
193 uint32 transit,
194 const BMessage *message) {
195 D_HOOK(("DormantNodeView::MouseMoved()\n"));
196
197 int32 index;
198 if (!message && ((index = IndexOf(point)) >= 0)) {
199 DormantNodeListItem *item =
200 dynamic_cast<DormantNodeListItem *>(ItemAt(index));
201 DormantNodeListItem *last =
202 dynamic_cast<DormantNodeListItem *>(m_lastItemUnder);
203 if (item != NULL) {
204 BRect r = item->getRealFrame(be_plain_font);
205 if (r.Contains(point)) {
206 if (item != last) {
207 if (last != NULL)
208 last->MouseOver(this, point, B_EXITED_VIEW);
209 item->MouseOver(this, point, B_ENTERED_VIEW);
210 m_lastItemUnder = item;
211 }
212 else {
213 item->MouseOver(this, point, B_INSIDE_VIEW);
214 }
215 }
216 }
217 else if (last != NULL) {
218 last->MouseOver(this, point, B_EXITED_VIEW);
219 }
220 }
221
222 _inherited::MouseMoved(point, transit, message);
223 }
224
InitiateDrag(BPoint point,int32 index,bool wasSelected)225 bool DormantNodeView::InitiateDrag(
226 BPoint point,
227 int32 index,
228 bool wasSelected) {
229 D_HOOK(("DormantNodeView::InitiateDrag()\n"));
230
231 DormantNodeListItem *item = dynamic_cast<DormantNodeListItem *>(ItemAt(CurrentSelection()));
232 if (item) {
233 BMessage dragMsg(M_INSTANTIATE_NODE);
234 dragMsg.AddData("which", B_RAW_TYPE,
235 reinterpret_cast<const void *>(&item->info()),
236 sizeof(item->info()));
237 point -= ItemFrame(index).LeftTop();
238 DragMessage(&dragMsg, item->getDragBitmap(), B_OP_ALPHA, point);
239 return true;
240 }
241 return false;
242 }
243
244 // -------------------------------------------------------- //
245 // internal operations (private)
246 // -------------------------------------------------------- //
247
_populateList()248 void DormantNodeView::_populateList() {
249 D_INTERNAL(("DormantNodeView::_populateList()\n"));
250
251 // init the resizable node-info buffer
252 BMediaRoster *roster = BMediaRoster::CurrentRoster();
253 const int32 bufferInc = 64;
254 int32 bufferSize = bufferInc;
255 dormant_node_info *infoBuffer = new dormant_node_info[bufferSize];
256 int32 numNodes;
257
258 // fill the buffer
259 while (true) {
260 numNodes = bufferSize;
261 status_t error = roster->GetDormantNodes(infoBuffer, &numNodes);
262 if (error) {
263 return;
264 }
265 if (numNodes < bufferSize) {
266 break;
267 }
268
269 // reallocate buffer & try again
270 delete [] infoBuffer;
271 bufferSize += bufferInc;
272 infoBuffer = new dormant_node_info[bufferSize];
273 }
274
275 // populate the list
276 for (int32 i = 0; i < numNodes; i++) {
277 DormantNodeListItem *item = new DormantNodeListItem(infoBuffer[i]);
278 AddItem(item);
279 }
280 SortItems(compareName);
281 }
282
_freeList()283 void DormantNodeView::_freeList() {
284 D_HOOK(("DormantNodeView::_freeList()\n"));
285
286 // remove and delete all items in the list
287 while (CountItems() > 0) {
288 BListItem *item = ItemAt(0);
289 if (RemoveItem(item)) {
290 delete item;
291 }
292 }
293 }
294
_updateList(int32 addOnID)295 void DormantNodeView::_updateList(
296 int32 addOnID) {
297 D_INTERNAL(("DormantNodeView::_updateList(%ld)\n", addOnID));
298
299 // init the resizable node-info buffer
300 BMediaRoster *roster = BMediaRoster::CurrentRoster();
301 const int32 bufferInc = 64;
302 int32 bufferSize = bufferInc;
303 dormant_node_info *infoBuffer = new dormant_node_info[bufferSize];
304 int32 numNodes;
305
306 // fill the buffer
307 while (true) {
308 numNodes = bufferSize;
309 status_t error = roster->GetDormantNodes(infoBuffer, &numNodes);
310 if (error) {
311 return;
312 }
313 if (numNodes < bufferSize) {
314 break;
315 }
316
317 // reallocate buffer & try again
318 delete [] infoBuffer;
319 bufferSize += bufferInc;
320 infoBuffer = new dormant_node_info[bufferSize];
321 }
322
323 // sort the list by add-on id to avoid multiple searches through
324 // the list
325 SortItems(compareAddOnID);
326
327 // Remove all nodes managed by this add-on
328 int32 start;
329 for (start = 0; start < CountItems(); start++) {
330 DormantNodeListItem *item = dynamic_cast<DormantNodeListItem *>(ItemAt(start));
331 if (item && (item->info().addon == addOnID)) {
332 break;
333 }
334 }
335 int32 count = 0;
336 for (int32 i = start; start < CountItems(); i++) {
337 DormantNodeListItem *item = dynamic_cast<DormantNodeListItem *>(ItemAt(i));
338 if (!item || (item->info().addon != addOnID)) {
339 break;
340 }
341 count++;
342 }
343 RemoveItems(start, count);
344
345 // add the items
346 for (int32 i = 0; i < numNodes; i++) {
347 if (infoBuffer[i].addon != addOnID) {
348 continue;
349 }
350 AddItem(new DormantNodeListItem(infoBuffer[i]));
351 }
352
353 SortItems(compareName);
354 }
355
356 // END -- DormantNodeView.cpp --
357