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 31MediaIcons* MediaListItem::sIcons = NULL; 32 33 34struct 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) + 16.0f; 135 return width; 136 } 137 138private: 139 140 const char* fTitle; 141 BBitmap* fPrimaryIcon; 142 BBitmap* fSecondaryIcon; 143 bool fDoubleInsets; 144 bool fSelected; 145}; 146 147 148MediaListItem::MediaListItem() 149 : 150 BListItem((uint32)0) 151{ 152} 153 154 155void 156MediaListItem::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 174void 175MediaListItem::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 185int 186MediaListItem::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 198NodeListItem::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 209void 210NodeListItem::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 223const char* 224NodeListItem::Label() 225{ 226 return fNodeInfo->name; 227} 228 229 230void 231NodeListItem::SetMediaType(media_type type) 232{ 233 fMediaType = type; 234} 235 236 237void 238NodeListItem::SetDefaultOutput(bool isDefault) 239{ 240 fIsDefaultOutput = isDefault; 241} 242 243 244void 245NodeListItem::SetDefaultInput(bool isDefault) 246{ 247 fIsDefaultInput = isDefault; 248} 249 250 251void 252NodeListItem::AlterWindow(MediaWindow* window) 253{ 254 window->SelectNode(fNodeInfo); 255} 256 257 258void 259NodeListItem::Accept(MediaListItem::Visitor& visitor) 260{ 261 visitor.Visit(this); 262} 263 264 265int 266NodeListItem::CompareWith(MediaListItem* item) 267{ 268 Comparator comparator(this); 269 item->Accept(comparator); 270 return comparator.result; 271} 272 273 274NodeListItem::Comparator::Comparator(NodeListItem* compareOthersTo) 275 : 276 result(GREATER_THAN), 277 fTarget(compareOthersTo) 278{ 279} 280 281 282void 283NodeListItem::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 294void 295NodeListItem::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 303void 304NodeListItem::Comparator::Visit(AudioMixerListItem* item) 305{ 306 result = LESS_THAN; 307} 308 309 310// #pragma mark - DeviceListItem 311 312 313DeviceListItem::DeviceListItem(const char* title, 314 MediaListItem::media_type type) 315 : 316 MediaListItem(), 317 fTitle(title), 318 fMediaType(type) 319{ 320} 321 322 323void 324DeviceListItem::Accept(MediaListItem::Visitor& visitor) 325{ 326 visitor.Visit(this); 327} 328 329 330int 331DeviceListItem::CompareWith(MediaListItem* item) 332{ 333 Comparator comparator(this); 334 item->Accept(comparator); 335 return comparator.result; 336} 337 338 339DeviceListItem::Comparator::Comparator(DeviceListItem* compareOthersTo) 340 : 341 result(GREATER_THAN), 342 fTarget(compareOthersTo) 343{ 344} 345 346 347void 348DeviceListItem::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 356void 357DeviceListItem::Comparator::Visit(DeviceListItem* item) 358{ 359 result = LESS_THAN; 360 if (fTarget->Type() == AUDIO_TYPE) 361 result = GREATER_THAN; 362} 363 364 365void 366DeviceListItem::Comparator::Visit(AudioMixerListItem* item) 367{ 368 result = LESS_THAN; 369 if (fTarget->Type() == AUDIO_TYPE) 370 result = GREATER_THAN; 371} 372 373 374void 375DeviceListItem::SetRenderParameters(Renderer& renderer) 376{ 377 renderer.AddIcon(&Icons()->devicesIcon); 378 renderer.UseDoubleInset(false); 379} 380 381 382void 383DeviceListItem::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 395AudioMixerListItem::AudioMixerListItem(const char* title) 396 : 397 MediaListItem(), 398 fTitle(title) 399{ 400} 401 402 403void 404AudioMixerListItem::AlterWindow(MediaWindow* window) 405{ 406 window->SelectAudioMixer(fTitle); 407} 408 409 410void 411AudioMixerListItem::Accept(MediaListItem::Visitor& visitor) 412{ 413 visitor.Visit(this); 414} 415 416 417int 418AudioMixerListItem::CompareWith(MediaListItem* item) 419{ 420 Comparator comparator(this); 421 item->Accept(comparator); 422 return comparator.result; 423} 424 425 426AudioMixerListItem::Comparator::Comparator(AudioMixerListItem* compareOthersTo) 427 : 428 result(0), 429 fTarget(compareOthersTo) 430{ 431} 432 433 434void 435AudioMixerListItem::Comparator::Visit(NodeListItem* item) 436{ 437 result = GREATER_THAN; 438} 439 440 441void 442AudioMixerListItem::Comparator::Visit(DeviceListItem* item) 443{ 444 result = GREATER_THAN; 445 if (item->Type() == AUDIO_TYPE) 446 result = LESS_THAN; 447} 448 449 450void 451AudioMixerListItem::Comparator::Visit(AudioMixerListItem* item) 452{ 453 result = 0; 454} 455 456 457void 458AudioMixerListItem::SetRenderParameters(Renderer& renderer) 459{ 460 renderer.AddIcon(&Icons()->mixerIcon); 461} 462