1// ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ 2// 3// Copyright (c) 2003, Haiku 4// 5// This software is part of the Haiku distribution and is covered 6// by the MIT 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#include "MidiSettingsView.h" 25 26 27#define kITEM_MARGIN 1 28#define GREATER_THAN -1 29#define LESS_THAN 1 30 31 32MediaIcons* MediaListItem::sIcons = NULL; 33 34 35struct MediaListItem::Renderer { 36 Renderer() 37 : 38 fTitle(NULL), 39 fPrimaryIcon(NULL), 40 fSecondaryIcon(NULL), 41 fDoubleInsets(true), 42 fSelected(false) 43 { 44 } 45 46 // The first icon added is drawn next to the label, 47 // the second is drawn to the right of the label. 48 void AddIcon(BBitmap* icon) 49 { 50 if (!fPrimaryIcon) 51 fPrimaryIcon = icon; 52 else { 53 fSecondaryIcon = fPrimaryIcon; 54 fPrimaryIcon = icon; 55 } 56 } 57 58 void SetTitle(const char* title) 59 { 60 fTitle = title; 61 } 62 63 void SetSelected(bool selected) 64 { 65 fSelected = selected; 66 } 67 68 // set whether or not to leave enough room for two icons, 69 // defaults to true. 70 void UseDoubleInset(bool doubleInset) 71 { 72 fDoubleInsets = doubleInset; 73 } 74 75 void Render(BView* onto, BRect frame, bool complete = false) 76 { 77 const rgb_color lowColor = onto->LowColor(); 78 const rgb_color highColor = onto->HighColor(); 79 80 if (fSelected || complete) { 81 if (fSelected) 82 onto->SetLowColor(ui_color(B_LIST_SELECTED_BACKGROUND_COLOR)); 83 onto->FillRect(frame, B_SOLID_LOW); 84 } 85 86 BPoint point(frame.left + 4.0f, 87 frame.top + (frame.Height() - MediaIcons::sBounds.Height()) / 2.0f); 88 89 BRect iconFrame(MediaIcons::IconRectAt(point + BPoint(1, 0))); 90 91 onto->SetDrawingMode(B_OP_OVER); 92 if (fPrimaryIcon && !fDoubleInsets) { 93 onto->DrawBitmap(fPrimaryIcon, iconFrame); 94 point.x = iconFrame.right + 1; 95 } else if (fSecondaryIcon) { 96 onto->DrawBitmap(fSecondaryIcon, iconFrame); 97 } 98 99 iconFrame = MediaIcons::IconRectAt(iconFrame.RightTop() + BPoint(1, 0)); 100 101 if (fDoubleInsets) { 102 if (fPrimaryIcon != NULL) 103 onto->DrawBitmap(fPrimaryIcon, iconFrame); 104 point.x = iconFrame.right + 1; 105 } 106 107 onto->SetDrawingMode(B_OP_COPY); 108 109 BFont font = be_plain_font; 110 font_height fontInfo; 111 font.GetHeight(&fontInfo); 112 113 onto->SetFont(&font); 114 onto->MovePenTo(point.x + 8, frame.top 115 + fontInfo.ascent + (frame.Height() 116 - ceilf(fontInfo.ascent + fontInfo.descent)) / 2.0f); 117 onto->DrawString(fTitle); 118 119 onto->SetHighColor(highColor); 120 onto->SetLowColor(lowColor); 121 } 122 123 float ItemWidth() 124 { 125 float width = 4.0f; 126 // left margin 127 128 float iconSpace = MediaIcons::sBounds.Width() + 1.0f; 129 if (fDoubleInsets) 130 iconSpace *= 2.0f; 131 width += iconSpace; 132 width += 8.0f; 133 // space between icons and text 134 135 width += be_plain_font->StringWidth(fTitle) + 16.0f; 136 return width; 137 } 138 139private: 140 141 const char* fTitle; 142 BBitmap* fPrimaryIcon; 143 BBitmap* fSecondaryIcon; 144 bool fDoubleInsets; 145 bool fSelected; 146}; 147 148 149MediaListItem::MediaListItem() 150 : 151 BListItem((uint32)0) 152{ 153} 154 155 156void 157MediaListItem::Update(BView* owner, const BFont* font) 158{ 159 // we need to override the update method so we can make sure our 160 // list item size doesn't change 161 BListItem::Update(owner, font); 162 163 float iconHeight = MediaIcons::sBounds.Height() + 1; 164 if ((Height() < iconHeight + kITEM_MARGIN * 2)) { 165 SetHeight(iconHeight + kITEM_MARGIN * 2); 166 } 167 168 Renderer renderer; 169 renderer.SetTitle(Label()); 170 SetRenderParameters(renderer); 171 SetWidth(renderer.ItemWidth()); 172} 173 174 175void 176MediaListItem::DrawItem(BView* owner, BRect frame, bool complete) 177{ 178 Renderer renderer; 179 renderer.SetSelected(IsSelected()); 180 renderer.SetTitle(Label()); 181 SetRenderParameters(renderer); 182 renderer.Render(owner, frame, complete); 183} 184 185 186int 187MediaListItem::Compare(const void* itemOne, const void* itemTwo) 188{ 189 MediaListItem* firstItem = *(MediaListItem**)itemOne; 190 MediaListItem* secondItem = *(MediaListItem**)itemTwo; 191 192 return firstItem->CompareWith(secondItem); 193} 194 195 196// #pragma mark - NodeListItem 197 198 199NodeListItem::NodeListItem(const dormant_node_info* node, media_type type) 200 : 201 MediaListItem(), 202 fNodeInfo(node), 203 fMediaType(type), 204 fIsDefaultInput(false), 205 fIsDefaultOutput(false) 206{ 207} 208 209 210void 211NodeListItem::SetRenderParameters(MediaListItem::Renderer& renderer) 212{ 213 MediaIcons::IconSet* iconSet = &Icons()->videoIcons; 214 if (fMediaType == MediaListItem::AUDIO_TYPE) 215 iconSet = &Icons()->audioIcons; 216 217 if (fIsDefaultInput) 218 renderer.AddIcon(&iconSet->inputIcon); 219 if (fIsDefaultOutput) 220 renderer.AddIcon(&iconSet->outputIcon); 221} 222 223 224const char* 225NodeListItem::Label() 226{ 227 return fNodeInfo->name; 228} 229 230 231void 232NodeListItem::SetMediaType(media_type type) 233{ 234 fMediaType = type; 235} 236 237 238void 239NodeListItem::SetDefaultOutput(bool isDefault) 240{ 241 fIsDefaultOutput = isDefault; 242} 243 244 245void 246NodeListItem::SetDefaultInput(bool isDefault) 247{ 248 fIsDefaultInput = isDefault; 249} 250 251 252void 253NodeListItem::AlterWindow(MediaWindow* window) 254{ 255 window->SelectNode(fNodeInfo); 256} 257 258 259void 260NodeListItem::Accept(MediaListItem::Visitor& visitor) 261{ 262 visitor.Visit(this); 263} 264 265 266int 267NodeListItem::CompareWith(MediaListItem* item) 268{ 269 Comparator comparator(this); 270 item->Accept(comparator); 271 return comparator.result; 272} 273 274 275NodeListItem::Comparator::Comparator(NodeListItem* compareOthersTo) 276 : 277 result(GREATER_THAN), 278 fTarget(compareOthersTo) 279{ 280} 281 282 283void 284NodeListItem::Comparator::Visit(NodeListItem* item) 285{ 286 result = GREATER_THAN; 287 288 if (fTarget->Type() != item->Type() && fTarget->Type() == VIDEO_TYPE) 289 result = LESS_THAN; 290 else 291 result = strcmp(fTarget->Label(), item->Label()); 292} 293 294 295void 296NodeListItem::Comparator::Visit(DeviceListItem* item) 297{ 298 result = LESS_THAN; 299 if (fTarget->Type() != item->Type() && fTarget->Type() == AUDIO_TYPE) 300 result = GREATER_THAN; 301} 302 303 304void 305NodeListItem::Comparator::Visit(AudioMixerListItem* item) 306{ 307 result = LESS_THAN; 308} 309 310 311void 312NodeListItem::Comparator::Visit(MidiListItem* item) 313{ 314 result = GREATER_THAN; 315} 316 317 318// #pragma mark - DeviceListItem 319 320 321DeviceListItem::DeviceListItem(const char* title, 322 MediaListItem::media_type type) 323 : 324 MediaListItem(), 325 fTitle(title), 326 fMediaType(type) 327{ 328} 329 330 331void 332DeviceListItem::Accept(MediaListItem::Visitor& visitor) 333{ 334 visitor.Visit(this); 335} 336 337 338int 339DeviceListItem::CompareWith(MediaListItem* item) 340{ 341 Comparator comparator(this); 342 item->Accept(comparator); 343 return comparator.result; 344} 345 346 347DeviceListItem::Comparator::Comparator(DeviceListItem* compareOthersTo) 348 : 349 result(GREATER_THAN), 350 fTarget(compareOthersTo) 351{ 352} 353 354 355void 356DeviceListItem::Comparator::Visit(NodeListItem* item) 357{ 358 result = GREATER_THAN; 359 if (fTarget->Type() != item->Type() && fTarget->Type() == AUDIO_TYPE) 360 result = LESS_THAN; 361} 362 363 364void 365DeviceListItem::Comparator::Visit(DeviceListItem* item) 366{ 367 result = LESS_THAN; 368 if (fTarget->Type() == AUDIO_TYPE) 369 result = GREATER_THAN; 370} 371 372 373void 374DeviceListItem::Comparator::Visit(AudioMixerListItem* item) 375{ 376 result = LESS_THAN; 377 if (fTarget->Type() == AUDIO_TYPE) 378 result = GREATER_THAN; 379} 380 381 382void 383DeviceListItem::Comparator::Visit(MidiListItem* item) 384{ 385 result = LESS_THAN; 386} 387 388 389void 390DeviceListItem::SetRenderParameters(Renderer& renderer) 391{ 392 renderer.AddIcon(&Icons()->devicesIcon); 393 renderer.UseDoubleInset(false); 394} 395 396 397void 398DeviceListItem::AlterWindow(MediaWindow* window) 399{ 400 if (fMediaType == MediaListItem::AUDIO_TYPE) 401 window->SelectAudioSettings(fTitle); 402 else 403 window->SelectVideoSettings(fTitle); 404} 405 406 407// #pragma mark - AudioMixerListItem 408 409 410AudioMixerListItem::AudioMixerListItem(const char* title) 411 : 412 MediaListItem(), 413 fTitle(title) 414{ 415} 416 417 418void 419AudioMixerListItem::AlterWindow(MediaWindow* window) 420{ 421 window->SelectAudioMixer(fTitle); 422} 423 424 425void 426AudioMixerListItem::Accept(MediaListItem::Visitor& visitor) 427{ 428 visitor.Visit(this); 429} 430 431 432int 433AudioMixerListItem::CompareWith(MediaListItem* item) 434{ 435 Comparator comparator(this); 436 item->Accept(comparator); 437 return comparator.result; 438} 439 440 441AudioMixerListItem::Comparator::Comparator(AudioMixerListItem* compareOthersTo) 442 : 443 result(0), 444 fTarget(compareOthersTo) 445{ 446} 447 448 449void 450AudioMixerListItem::Comparator::Visit(NodeListItem* item) 451{ 452 result = GREATER_THAN; 453} 454 455 456void 457AudioMixerListItem::Comparator::Visit(DeviceListItem* item) 458{ 459 result = GREATER_THAN; 460 if (item->Type() == AUDIO_TYPE) 461 result = LESS_THAN; 462} 463 464 465void 466AudioMixerListItem::Comparator::Visit(AudioMixerListItem* item) 467{ 468 result = 0; 469} 470 471 472void 473AudioMixerListItem::Comparator::Visit(MidiListItem* item) 474{ 475 result = GREATER_THAN; 476} 477 478 479void 480AudioMixerListItem::SetRenderParameters(Renderer& renderer) 481{ 482 renderer.AddIcon(&Icons()->mixerIcon); 483} 484 485 486// #pragma mark - MidiListItem 487 488MidiListItem::MidiListItem(const char* title) 489 : 490 MediaListItem(), 491 fTitle(title) 492{ 493} 494 495 496void 497MidiListItem::AlterWindow(MediaWindow* window) 498{ 499 window->SelectMidiSettings(fTitle); 500} 501 502 503const char* 504MidiListItem::Label() 505{ 506 return "MIDI"; 507} 508 509 510void 511MidiListItem::Accept(MediaListItem::Visitor& visitor) 512{ 513 visitor.Visit(this); 514} 515 516 517int 518MidiListItem::CompareWith(MediaListItem* item) 519{ 520 Comparator comparator(this); 521 item->Accept(comparator); 522 return comparator.result; 523} 524 525 526MidiListItem::Comparator::Comparator(MidiListItem* compareOthersTo) 527 : 528 result(0), 529 fTarget(compareOthersTo) 530{ 531} 532 533 534void 535MidiListItem::Comparator::Visit(NodeListItem* item) 536{ 537 result = GREATER_THAN; 538} 539 540 541void 542MidiListItem::Comparator::Visit(DeviceListItem* item) 543{ 544 result = GREATER_THAN; 545 if (item->Type() == AUDIO_TYPE) 546 result = LESS_THAN; 547} 548 549 550void 551MidiListItem::Comparator::Visit(AudioMixerListItem* item) 552{ 553 result = LESS_THAN; 554} 555 556 557void 558MidiListItem::Comparator::Visit(MidiListItem* item) 559{ 560 result = 0; 561} 562 563 564void 565MidiListItem::SetRenderParameters(Renderer& renderer) 566{ 567 // TODO: Create a nice icon 568 renderer.AddIcon(&Icons()->mixerIcon); 569} 570