1 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 2 // 3 // Copyright (c) 2003, OpenBeOS 4 // 5 // This software is part of the OpenBeOS distribution and is covered 6 // by the OpenBeOS license. 7 // 8 // 9 // File: MediaListItem.cpp 10 // Author: Sikosis, Jérôme Duval 11 // Description: Media Preferences 12 // Created : June 25, 2003 13 // 14 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 15 #include "MediaListItem.h" 16 17 #include <string.h> 18 19 #include <MediaAddOn.h> 20 #include <View.h> 21 22 #include "MediaIcons.h" 23 #include "MediaWindow.h" 24 25 26 #define kITEM_MARGIN 1 27 #define GREATER_THAN -1 28 #define LESS_THAN 1 29 30 31 MediaIcons* MediaListItem::sIcons = NULL; 32 33 34 struct MediaListItem::Renderer { 35 Renderer() 36 : 37 fTitle(NULL), 38 fPrimaryIcon(NULL), 39 fSecondaryIcon(NULL), 40 fDoubleInsets(true), 41 fSelected(false) 42 { 43 } 44 45 // The first icon added is drawn next to the label, 46 // the second is drawn to the right of the label. 47 void AddIcon(BBitmap* icon) 48 { 49 if (!fPrimaryIcon) 50 fPrimaryIcon = icon; 51 else { 52 fSecondaryIcon = fPrimaryIcon; 53 fPrimaryIcon = icon; 54 } 55 } 56 57 void SetTitle(const char* title) 58 { 59 fTitle = title; 60 } 61 62 void SetSelected(bool selected) 63 { 64 fSelected = selected; 65 } 66 67 // set whether or not to leave enough room for two icons, 68 // defaults to true. 69 void UseDoubleInset(bool doubleInset) 70 { 71 fDoubleInsets = doubleInset; 72 } 73 74 void Render(BView* onto, BRect frame, bool complete = false) 75 { 76 const rgb_color lowColor = onto->LowColor(); 77 const rgb_color highColor = onto->HighColor(); 78 const rgb_color kBlack = {0, 0, 0, 255}; 79 80 if (fSelected || complete) { 81 if (fSelected) 82 onto->SetLowColor(tint_color(lowColor, B_DARKEN_2_TINT)); 83 onto->FillRect(frame, B_SOLID_LOW); 84 } 85 86 frame.left += 4; 87 frame.top += kITEM_MARGIN; 88 BRect iconFrame(MediaIcons::IconRectAt(frame.LeftTop() + BPoint(1, 0))); 89 90 onto->SetDrawingMode(B_OP_OVER); 91 if (fPrimaryIcon && !fDoubleInsets) { 92 onto->DrawBitmap(fPrimaryIcon, iconFrame); 93 frame.left = iconFrame.right + 1; 94 } else if (fSecondaryIcon) { 95 onto->DrawBitmap(fSecondaryIcon, iconFrame); 96 } 97 iconFrame = MediaIcons::IconRectAt(iconFrame.RightTop() + BPoint(1, 0)); 98 99 if (fDoubleInsets && fPrimaryIcon) { 100 onto->DrawBitmap(fPrimaryIcon, iconFrame); 101 frame.left = iconFrame.right + 1; 102 } 103 104 onto->SetDrawingMode(B_OP_COPY); 105 onto->SetHighColor(kBlack); 106 107 BFont font = be_plain_font; 108 font_height fontInfo; 109 font.GetHeight(&fontInfo); 110 float lineHeight = fontInfo.ascent + fontInfo.descent 111 + fontInfo.leading; 112 onto->SetFont(&font); 113 onto->MovePenTo(frame.left + 8, frame.top 114 + ((frame.Height() - (lineHeight)) / 2) 115 + (fontInfo.ascent + fontInfo.descent) - 1); 116 onto->DrawString(fTitle); 117 118 onto->SetHighColor(highColor); 119 onto->SetLowColor(lowColor); 120 } 121 122 float ItemWidth() 123 { 124 float width = 4.0f; 125 // left margin 126 127 float iconSpace = MediaIcons::sBounds.Width() + 1.0f; 128 if (fDoubleInsets) 129 iconSpace *= 2.0f; 130 width += iconSpace; 131 width += 8.0f; 132 // space between icons and text 133 134 width += be_plain_font->StringWidth(fTitle) + 3.0f; 135 return width; 136 } 137 138 private: 139 140 const char* fTitle; 141 BBitmap* fPrimaryIcon; 142 BBitmap* fSecondaryIcon; 143 bool fDoubleInsets; 144 bool fSelected; 145 }; 146 147 148 MediaListItem::MediaListItem() 149 : 150 BListItem((uint32)0) 151 { 152 } 153 154 155 void 156 MediaListItem::Update(BView* owner, const BFont* font) 157 { 158 // we need to override the update method so we can make sure our 159 // list item size doesn't change 160 BListItem::Update(owner, font); 161 162 float iconHeight = MediaIcons::sBounds.Height() + 1; 163 if ((Height() < iconHeight + kITEM_MARGIN * 2)) { 164 SetHeight(iconHeight + kITEM_MARGIN * 2); 165 } 166 167 Renderer renderer; 168 renderer.SetTitle(Label()); 169 SetRenderParameters(renderer); 170 SetWidth(renderer.ItemWidth()); 171 } 172 173 174 void 175 MediaListItem::DrawItem(BView* owner, BRect frame, bool complete) 176 { 177 Renderer renderer; 178 renderer.SetSelected(IsSelected()); 179 renderer.SetTitle(Label()); 180 SetRenderParameters(renderer); 181 renderer.Render(owner, frame, complete); 182 } 183 184 185 int 186 MediaListItem::Compare(const void* itemOne, const void* itemTwo) 187 { 188 MediaListItem* firstItem = *(MediaListItem**)itemOne; 189 MediaListItem* secondItem = *(MediaListItem**)itemTwo; 190 191 return firstItem->CompareWith(secondItem); 192 } 193 194 195 // #pragma mark - NodeListItem 196 197 198 NodeListItem::NodeListItem(const dormant_node_info* node, media_type type) 199 : 200 MediaListItem(), 201 fNodeInfo(node), 202 fMediaType(type), 203 fIsDefaultInput(false), 204 fIsDefaultOutput(false) 205 { 206 } 207 208 209 void 210 NodeListItem::SetRenderParameters(MediaListItem::Renderer& renderer) 211 { 212 MediaIcons::IconSet* iconSet = &Icons()->videoIcons; 213 if (fMediaType == MediaListItem::AUDIO_TYPE) 214 iconSet = &Icons()->audioIcons; 215 216 if (fIsDefaultInput) 217 renderer.AddIcon(&iconSet->inputIcon); 218 if (fIsDefaultOutput) 219 renderer.AddIcon(&iconSet->outputIcon); 220 } 221 222 223 const char* 224 NodeListItem::Label() 225 { 226 return fNodeInfo->name; 227 } 228 229 230 void 231 NodeListItem::SetMediaType(media_type type) 232 { 233 fMediaType = type; 234 } 235 236 237 void 238 NodeListItem::SetDefaultOutput(bool isDefault) 239 { 240 fIsDefaultOutput = isDefault; 241 } 242 243 244 void 245 NodeListItem::SetDefaultInput(bool isDefault) 246 { 247 fIsDefaultInput = isDefault; 248 } 249 250 251 void 252 NodeListItem::AlterWindow(MediaWindow* window) 253 { 254 window->SelectNode(fNodeInfo); 255 } 256 257 258 void 259 NodeListItem::Accept(MediaListItem::Visitor& visitor) 260 { 261 visitor.Visit(this); 262 } 263 264 265 int 266 NodeListItem::CompareWith(MediaListItem* item) 267 { 268 Comparator comparator(this); 269 item->Accept(comparator); 270 return comparator.result; 271 } 272 273 274 NodeListItem::Comparator::Comparator(NodeListItem* compareOthersTo) 275 : 276 result(GREATER_THAN), 277 fTarget(compareOthersTo) 278 { 279 } 280 281 282 void 283 NodeListItem::Comparator::Visit(NodeListItem* item) 284 { 285 result = GREATER_THAN; 286 287 if (fTarget->Type() != item->Type() && fTarget->Type() == VIDEO_TYPE) 288 result = LESS_THAN; 289 else 290 result = strcmp(fTarget->Label(), item->Label()); 291 } 292 293 294 void 295 NodeListItem::Comparator::Visit(DeviceListItem* item) 296 { 297 result = LESS_THAN; 298 if (fTarget->Type() != item->Type() && fTarget->Type() == AUDIO_TYPE) 299 result = GREATER_THAN; 300 } 301 302 303 void 304 NodeListItem::Comparator::Visit(AudioMixerListItem* item) 305 { 306 result = LESS_THAN; 307 } 308 309 310 // #pragma mark - DeviceListItem 311 312 313 DeviceListItem::DeviceListItem(const char* title, 314 MediaListItem::media_type type) 315 : 316 MediaListItem(), 317 fTitle(title), 318 fMediaType(type) 319 { 320 } 321 322 323 void 324 DeviceListItem::Accept(MediaListItem::Visitor& visitor) 325 { 326 visitor.Visit(this); 327 } 328 329 330 int 331 DeviceListItem::CompareWith(MediaListItem* item) 332 { 333 Comparator comparator(this); 334 item->Accept(comparator); 335 return comparator.result; 336 } 337 338 339 DeviceListItem::Comparator::Comparator(DeviceListItem* compareOthersTo) 340 : 341 result(GREATER_THAN), 342 fTarget(compareOthersTo) 343 { 344 } 345 346 347 void 348 DeviceListItem::Comparator::Visit(NodeListItem* item) 349 { 350 result = GREATER_THAN; 351 if (fTarget->Type() != item->Type() && fTarget->Type() == AUDIO_TYPE) 352 result = LESS_THAN; 353 } 354 355 356 void 357 DeviceListItem::Comparator::Visit(DeviceListItem* item) 358 { 359 result = LESS_THAN; 360 if (fTarget->Type() == AUDIO_TYPE) 361 result = GREATER_THAN; 362 } 363 364 365 void 366 DeviceListItem::Comparator::Visit(AudioMixerListItem* item) 367 { 368 result = LESS_THAN; 369 if (fTarget->Type() == AUDIO_TYPE) 370 result = GREATER_THAN; 371 } 372 373 374 void 375 DeviceListItem::SetRenderParameters(Renderer& renderer) 376 { 377 renderer.AddIcon(&Icons()->devicesIcon); 378 renderer.UseDoubleInset(false); 379 } 380 381 382 void 383 DeviceListItem::AlterWindow(MediaWindow* window) 384 { 385 if (fMediaType == MediaListItem::AUDIO_TYPE) 386 window->SelectAudioSettings(fTitle); 387 else 388 window->SelectVideoSettings(fTitle); 389 } 390 391 392 // #pragma mark - AudioMixerListItem 393 394 395 AudioMixerListItem::AudioMixerListItem(const char* title) 396 : 397 MediaListItem(), 398 fTitle(title) 399 { 400 } 401 402 403 void 404 AudioMixerListItem::AlterWindow(MediaWindow* window) 405 { 406 window->SelectAudioMixer(fTitle); 407 } 408 409 410 void 411 AudioMixerListItem::Accept(MediaListItem::Visitor& visitor) 412 { 413 visitor.Visit(this); 414 } 415 416 417 int 418 AudioMixerListItem::CompareWith(MediaListItem* item) 419 { 420 Comparator comparator(this); 421 item->Accept(comparator); 422 return comparator.result; 423 } 424 425 426 AudioMixerListItem::Comparator::Comparator(AudioMixerListItem* compareOthersTo) 427 : 428 result(0), 429 fTarget(compareOthersTo) 430 { 431 } 432 433 434 void 435 AudioMixerListItem::Comparator::Visit(NodeListItem* item) 436 { 437 result = GREATER_THAN; 438 } 439 440 441 void 442 AudioMixerListItem::Comparator::Visit(DeviceListItem* item) 443 { 444 result = GREATER_THAN; 445 if (item->Type() == AUDIO_TYPE) 446 result = LESS_THAN; 447 } 448 449 450 void 451 AudioMixerListItem::Comparator::Visit(AudioMixerListItem* item) 452 { 453 result = 0; 454 } 455 456 457 void 458 AudioMixerListItem::SetRenderParameters(Renderer& renderer) 459 { 460 renderer.AddIcon(&Icons()->mixerIcon); 461 } 462