xref: /haiku/src/preferences/media/MediaListItem.cpp (revision 4bd0c1066b227cec4b79883bdef697c7a27f2e90)
1 // ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
2 //
3 //	Copyright (c) 2003, OpenBeOS
4 //
5 //  This software is part of the OpenBeOS 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 
32 MediaIcons* MediaListItem::sIcons = NULL;
33 
34 
35 struct 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 && fPrimaryIcon) {
102 			onto->DrawBitmap(fPrimaryIcon, iconFrame);
103 			point.x = iconFrame.right + 1;
104 		}
105 
106 		onto->SetDrawingMode(B_OP_COPY);
107 
108 		BFont font = be_plain_font;
109 		font_height	fontInfo;
110 		font.GetHeight(&fontInfo);
111 
112 		onto->SetFont(&font);
113 		onto->MovePenTo(point.x + 8, frame.top
114 			+ fontInfo.ascent + (frame.Height()
115 			- ceilf(fontInfo.ascent + fontInfo.descent)) / 2.0f);
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 
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 void
311 NodeListItem::Comparator::Visit(MidiListItem* item)
312 {
313 	result = GREATER_THAN;
314 }
315 
316 
317 // #pragma mark - DeviceListItem
318 
319 
320 DeviceListItem::DeviceListItem(const char* title,
321 	MediaListItem::media_type type)
322 	:
323 	MediaListItem(),
324 	fTitle(title),
325 	fMediaType(type)
326 {
327 }
328 
329 
330 void
331 DeviceListItem::Accept(MediaListItem::Visitor& visitor)
332 {
333 	visitor.Visit(this);
334 }
335 
336 
337 int
338 DeviceListItem::CompareWith(MediaListItem* item)
339 {
340 	Comparator comparator(this);
341 	item->Accept(comparator);
342 	return comparator.result;
343 }
344 
345 
346 DeviceListItem::Comparator::Comparator(DeviceListItem* compareOthersTo)
347 	:
348 	result(GREATER_THAN),
349 	fTarget(compareOthersTo)
350 {
351 }
352 
353 
354 void
355 DeviceListItem::Comparator::Visit(NodeListItem* item)
356 {
357 	result = GREATER_THAN;
358 	if (fTarget->Type() != item->Type() && fTarget->Type() == AUDIO_TYPE)
359 		result = LESS_THAN;
360 }
361 
362 
363 void
364 DeviceListItem::Comparator::Visit(DeviceListItem* item)
365 {
366 	result = LESS_THAN;
367 	if (fTarget->Type() == AUDIO_TYPE)
368 		result = GREATER_THAN;
369 }
370 
371 
372 void
373 DeviceListItem::Comparator::Visit(AudioMixerListItem* item)
374 {
375 	result = LESS_THAN;
376 	if (fTarget->Type() == AUDIO_TYPE)
377 		result = GREATER_THAN;
378 }
379 
380 
381 void
382 DeviceListItem::Comparator::Visit(MidiListItem* item)
383 {
384 	result = LESS_THAN;
385 }
386 
387 
388 void
389 DeviceListItem::SetRenderParameters(Renderer& renderer)
390 {
391 	renderer.AddIcon(&Icons()->devicesIcon);
392 	renderer.UseDoubleInset(false);
393 }
394 
395 
396 void
397 DeviceListItem::AlterWindow(MediaWindow* window)
398 {
399 	if (fMediaType == MediaListItem::AUDIO_TYPE)
400 		window->SelectAudioSettings(fTitle);
401 	else
402 		window->SelectVideoSettings(fTitle);
403 }
404 
405 
406 // #pragma mark - AudioMixerListItem
407 
408 
409 AudioMixerListItem::AudioMixerListItem(const char* title)
410 	:
411 	MediaListItem(),
412 	fTitle(title)
413 {
414 }
415 
416 
417 void
418 AudioMixerListItem::AlterWindow(MediaWindow* window)
419 {
420 	window->SelectAudioMixer(fTitle);
421 }
422 
423 
424 void
425 AudioMixerListItem::Accept(MediaListItem::Visitor& visitor)
426 {
427 	visitor.Visit(this);
428 }
429 
430 
431 int
432 AudioMixerListItem::CompareWith(MediaListItem* item)
433 {
434 	Comparator comparator(this);
435 	item->Accept(comparator);
436 	return comparator.result;
437 }
438 
439 
440 AudioMixerListItem::Comparator::Comparator(AudioMixerListItem* compareOthersTo)
441 	:
442 	result(0),
443 	fTarget(compareOthersTo)
444 {
445 }
446 
447 
448 void
449 AudioMixerListItem::Comparator::Visit(NodeListItem* item)
450 {
451 	result = GREATER_THAN;
452 }
453 
454 
455 void
456 AudioMixerListItem::Comparator::Visit(DeviceListItem* item)
457 {
458 	result = GREATER_THAN;
459 	if (item->Type() == AUDIO_TYPE)
460 		result = LESS_THAN;
461 }
462 
463 
464 void
465 AudioMixerListItem::Comparator::Visit(AudioMixerListItem* item)
466 {
467 	result = 0;
468 }
469 
470 
471 void
472 AudioMixerListItem::Comparator::Visit(MidiListItem* item)
473 {
474 	result = GREATER_THAN;
475 }
476 
477 
478 void
479 AudioMixerListItem::SetRenderParameters(Renderer& renderer)
480 {
481 	renderer.AddIcon(&Icons()->mixerIcon);
482 }
483 
484 
485 // #pragma mark - MidiListItem
486 
487 MidiListItem::MidiListItem(const char* title)
488 	:
489 	MediaListItem(),
490 	fTitle(title)
491 {
492 }
493 
494 
495 void
496 MidiListItem::AlterWindow(MediaWindow* window)
497 {
498 	window->SelectMidiSettings(fTitle);
499 }
500 
501 
502 const char*
503 MidiListItem::Label()
504 {
505 	return "MIDI";
506 }
507 
508 
509 void
510 MidiListItem::Accept(MediaListItem::Visitor& visitor)
511 {
512 	visitor.Visit(this);
513 }
514 
515 
516 int
517 MidiListItem::CompareWith(MediaListItem* item)
518 {
519 	Comparator comparator(this);
520 	item->Accept(comparator);
521 	return comparator.result;
522 }
523 
524 
525 MidiListItem::Comparator::Comparator(MidiListItem* compareOthersTo)
526 	:
527 	result(0),
528 	fTarget(compareOthersTo)
529 {
530 }
531 
532 
533 void
534 MidiListItem::Comparator::Visit(NodeListItem* item)
535 {
536 	result = GREATER_THAN;
537 }
538 
539 
540 void
541 MidiListItem::Comparator::Visit(DeviceListItem* item)
542 {
543 	result = GREATER_THAN;
544 	if (item->Type() == AUDIO_TYPE)
545 		result = LESS_THAN;
546 }
547 
548 
549 void
550 MidiListItem::Comparator::Visit(AudioMixerListItem* item)
551 {
552 	result = LESS_THAN;
553 }
554 
555 
556 void
557 MidiListItem::Comparator::Visit(MidiListItem* item)
558 {
559 	result = 0;
560 }
561 
562 
563 void
564 MidiListItem::SetRenderParameters(Renderer& renderer)
565 {
566 	// TODO: Create a nice icon
567 	renderer.AddIcon(&Icons()->mixerIcon);
568 }
569