xref: /haiku/src/preferences/media/MediaListItem.cpp (revision 68ea01249e1e2088933cb12f9c28d4e5c5d1c9ef)
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) {
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 
139 private:
140 
141 	const char*	fTitle;
142 	BBitmap*	fPrimaryIcon;
143 	BBitmap*	fSecondaryIcon;
144 	bool		fDoubleInsets;
145 	bool		fSelected;
146 };
147 
148 
149 MediaListItem::MediaListItem()
150 	:
151 	BListItem((uint32)0)
152 {
153 }
154 
155 
156 void
157 MediaListItem::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 
175 void
176 MediaListItem::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 
186 int
187 MediaListItem::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 
199 NodeListItem::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 
210 void
211 NodeListItem::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 
224 const char*
225 NodeListItem::Label()
226 {
227 	return fNodeInfo->name;
228 }
229 
230 
231 void
232 NodeListItem::SetMediaType(media_type type)
233 {
234 	fMediaType = type;
235 }
236 
237 
238 void
239 NodeListItem::SetDefaultOutput(bool isDefault)
240 {
241 	fIsDefaultOutput = isDefault;
242 }
243 
244 
245 void
246 NodeListItem::SetDefaultInput(bool isDefault)
247 {
248 	fIsDefaultInput = isDefault;
249 }
250 
251 
252 void
253 NodeListItem::AlterWindow(MediaWindow* window)
254 {
255 	window->SelectNode(fNodeInfo);
256 }
257 
258 
259 void
260 NodeListItem::Accept(MediaListItem::Visitor& visitor)
261 {
262 	visitor.Visit(this);
263 }
264 
265 
266 int
267 NodeListItem::CompareWith(MediaListItem* item)
268 {
269 	Comparator comparator(this);
270 	item->Accept(comparator);
271 	return comparator.result;
272 }
273 
274 
275 NodeListItem::Comparator::Comparator(NodeListItem* compareOthersTo)
276 	:
277 	result(GREATER_THAN),
278 	fTarget(compareOthersTo)
279 {
280 }
281 
282 
283 void
284 NodeListItem::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 
295 void
296 NodeListItem::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 
304 void
305 NodeListItem::Comparator::Visit(AudioMixerListItem* item)
306 {
307 	result = LESS_THAN;
308 }
309 
310 
311 void
312 NodeListItem::Comparator::Visit(MidiListItem* item)
313 {
314 	result = GREATER_THAN;
315 }
316 
317 
318 // #pragma mark - DeviceListItem
319 
320 
321 DeviceListItem::DeviceListItem(const char* title,
322 	MediaListItem::media_type type)
323 	:
324 	MediaListItem(),
325 	fTitle(title),
326 	fMediaType(type)
327 {
328 }
329 
330 
331 void
332 DeviceListItem::Accept(MediaListItem::Visitor& visitor)
333 {
334 	visitor.Visit(this);
335 }
336 
337 
338 int
339 DeviceListItem::CompareWith(MediaListItem* item)
340 {
341 	Comparator comparator(this);
342 	item->Accept(comparator);
343 	return comparator.result;
344 }
345 
346 
347 DeviceListItem::Comparator::Comparator(DeviceListItem* compareOthersTo)
348 	:
349 	result(GREATER_THAN),
350 	fTarget(compareOthersTo)
351 {
352 }
353 
354 
355 void
356 DeviceListItem::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 
364 void
365 DeviceListItem::Comparator::Visit(DeviceListItem* item)
366 {
367 	result = LESS_THAN;
368 	if (fTarget->Type() == AUDIO_TYPE)
369 		result = GREATER_THAN;
370 }
371 
372 
373 void
374 DeviceListItem::Comparator::Visit(AudioMixerListItem* item)
375 {
376 	result = LESS_THAN;
377 	if (fTarget->Type() == AUDIO_TYPE)
378 		result = GREATER_THAN;
379 }
380 
381 
382 void
383 DeviceListItem::Comparator::Visit(MidiListItem* item)
384 {
385 	result = LESS_THAN;
386 }
387 
388 
389 void
390 DeviceListItem::SetRenderParameters(Renderer& renderer)
391 {
392 	renderer.AddIcon(&Icons()->devicesIcon);
393 	renderer.UseDoubleInset(false);
394 }
395 
396 
397 void
398 DeviceListItem::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 
410 AudioMixerListItem::AudioMixerListItem(const char* title)
411 	:
412 	MediaListItem(),
413 	fTitle(title)
414 {
415 }
416 
417 
418 void
419 AudioMixerListItem::AlterWindow(MediaWindow* window)
420 {
421 	window->SelectAudioMixer(fTitle);
422 }
423 
424 
425 void
426 AudioMixerListItem::Accept(MediaListItem::Visitor& visitor)
427 {
428 	visitor.Visit(this);
429 }
430 
431 
432 int
433 AudioMixerListItem::CompareWith(MediaListItem* item)
434 {
435 	Comparator comparator(this);
436 	item->Accept(comparator);
437 	return comparator.result;
438 }
439 
440 
441 AudioMixerListItem::Comparator::Comparator(AudioMixerListItem* compareOthersTo)
442 	:
443 	result(0),
444 	fTarget(compareOthersTo)
445 {
446 }
447 
448 
449 void
450 AudioMixerListItem::Comparator::Visit(NodeListItem* item)
451 {
452 	result = GREATER_THAN;
453 }
454 
455 
456 void
457 AudioMixerListItem::Comparator::Visit(DeviceListItem* item)
458 {
459 	result = GREATER_THAN;
460 	if (item->Type() == AUDIO_TYPE)
461 		result = LESS_THAN;
462 }
463 
464 
465 void
466 AudioMixerListItem::Comparator::Visit(AudioMixerListItem* item)
467 {
468 	result = 0;
469 }
470 
471 
472 void
473 AudioMixerListItem::Comparator::Visit(MidiListItem* item)
474 {
475 	result = GREATER_THAN;
476 }
477 
478 
479 void
480 AudioMixerListItem::SetRenderParameters(Renderer& renderer)
481 {
482 	renderer.AddIcon(&Icons()->mixerIcon);
483 }
484 
485 
486 // #pragma mark - MidiListItem
487 
488 MidiListItem::MidiListItem(const char* title)
489 	:
490 	MediaListItem(),
491 	fTitle(title)
492 {
493 }
494 
495 
496 void
497 MidiListItem::AlterWindow(MediaWindow* window)
498 {
499 	window->SelectMidiSettings(fTitle);
500 }
501 
502 
503 const char*
504 MidiListItem::Label()
505 {
506 	return "MIDI";
507 }
508 
509 
510 void
511 MidiListItem::Accept(MediaListItem::Visitor& visitor)
512 {
513 	visitor.Visit(this);
514 }
515 
516 
517 int
518 MidiListItem::CompareWith(MediaListItem* item)
519 {
520 	Comparator comparator(this);
521 	item->Accept(comparator);
522 	return comparator.result;
523 }
524 
525 
526 MidiListItem::Comparator::Comparator(MidiListItem* compareOthersTo)
527 	:
528 	result(0),
529 	fTarget(compareOthersTo)
530 {
531 }
532 
533 
534 void
535 MidiListItem::Comparator::Visit(NodeListItem* item)
536 {
537 	result = GREATER_THAN;
538 }
539 
540 
541 void
542 MidiListItem::Comparator::Visit(DeviceListItem* item)
543 {
544 	result = GREATER_THAN;
545 	if (item->Type() == AUDIO_TYPE)
546 		result = LESS_THAN;
547 }
548 
549 
550 void
551 MidiListItem::Comparator::Visit(AudioMixerListItem* item)
552 {
553 	result = LESS_THAN;
554 }
555 
556 
557 void
558 MidiListItem::Comparator::Visit(MidiListItem* item)
559 {
560 	result = 0;
561 }
562 
563 
564 void
565 MidiListItem::SetRenderParameters(Renderer& renderer)
566 {
567 	// TODO: Create a nice icon
568 	renderer.AddIcon(&Icons()->mixerIcon);
569 }
570