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 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 73 DormantNodeView::~DormantNodeView() { 74 D_ALLOC(("DormantNodeView::~DormantNodeView()\n")); 75 76 } 77 78 // -------------------------------------------------------- // 79 // BListView impl. (public) 80 // -------------------------------------------------------- // 81 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 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 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 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 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 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 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 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 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 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