1e6753e37SKarsten Heimrich/*
29b780235SStefano Ceccherini * Copyright 2005-2015, Haiku Inc. All Rights Reserved.
3625c061aSAxel Dörfler * Distributed under the terms of the MIT License.
4d89b690dSStephan Aßmus *
5d89b690dSStephan Aßmus * Authors:
69b780235SStefano Ceccherini *		Stefano Ceccherini (stefano.ceccherini@gmail.com)
7d89b690dSStephan Aßmus *		Stephan A��mus <superstippi@gmx.de>
8625c061aSAxel Dörfler */
9e6753e37SKarsten Heimrich
10625c061aSAxel Dörfler#include <ChannelSlider.h>
112f86ba45SStephan Aßmus
12d89b690dSStephan Aßmus#include <new>
13d89b690dSStephan Aßmus
142f86ba45SStephan Aßmus#include <Bitmap.h>
152f86ba45SStephan Aßmus#include <ControlLook.h>
161c3a6ab0SStefano Ceccherini#include <Debug.h>
171c3a6ab0SStefano Ceccherini#include <PropertyInfo.h>
18e605d526SStefano Ceccherini#include <Screen.h>
190677ddf4SStefano Ceccherini#include <Window.h>
201c3a6ab0SStefano Ceccherini
212879eb37SJérôme Duval
22f6fd4d6aSStefano Ceccheriniconst static unsigned char
23f6fd4d6aSStefano CeccherinikVerticalKnobData[] = {
24f6fd4d6aSStefano Ceccherini	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
25f6fd4d6aSStefano Ceccherini	0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
26f6fd4d6aSStefano Ceccherini	0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0xff,
27f6fd4d6aSStefano Ceccherini	0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0xff,
28f6fd4d6aSStefano Ceccherini	0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12,
29f6fd4d6aSStefano Ceccherini	0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12,
30f6fd4d6aSStefano Ceccherini	0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12,
31f6fd4d6aSStefano Ceccherini	0xff, 0x00, 0x3f, 0x3f, 0xcb, 0xcb, 0xcb, 0xcb, 0x3f, 0x3f, 0x00, 0x12,
32f6fd4d6aSStefano Ceccherini	0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12,
33f6fd4d6aSStefano Ceccherini	0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12,
34f6fd4d6aSStefano Ceccherini	0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12,
35f6fd4d6aSStefano Ceccherini	0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12,
36f6fd4d6aSStefano Ceccherini	0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12,
37f6fd4d6aSStefano Ceccherini	0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12,
38f6fd4d6aSStefano Ceccherini	0xff, 0xff, 0xff, 0xff, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0xff
39f6fd4d6aSStefano Ceccherini};
40f6fd4d6aSStefano Ceccherini
41f6fd4d6aSStefano Ceccherini
42f6fd4d6aSStefano Ceccheriniconst static unsigned char
43f6fd4d6aSStefano CeccherinikHorizontalKnobData[] = {
44e6753e37SKarsten Heimrich	0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45e6753e37SKarsten Heimrich	0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
46e6753e37SKarsten Heimrich	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0xff, 0xff, 0xff, 0x00, 0x3f, 0x3f,
47e6753e37SKarsten Heimrich	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0xff, 0xff,
48e6753e37SKarsten Heimrich	0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xcb, 0x3f, 0x3f, 0x3f, 0x3f,
49e6753e37SKarsten Heimrich	0x3f, 0x00, 0x12, 0xff, 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xcb,
50e6753e37SKarsten Heimrich	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12, 0xff, 0xff, 0x00, 0x3f, 0x3f,
51e6753e37SKarsten Heimrich	0x3f, 0x3f, 0x3f, 0xcb, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12, 0xff,
52e6753e37SKarsten Heimrich	0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0xcb, 0x3f, 0x3f, 0x3f, 0x3f,
53e6753e37SKarsten Heimrich	0x3f, 0x00, 0x12, 0xff, 0xff, 0x00, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
54e6753e37SKarsten Heimrich	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12, 0xff, 0xff, 0x00, 0x3f, 0x3f,
55e6753e37SKarsten Heimrich	0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x00, 0x12, 0xff,
56e6753e37SKarsten Heimrich	0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57e6753e37SKarsten Heimrich	0x00, 0x0c, 0x12, 0xff, 0xff, 0xff, 0xff, 0xff, 0x12, 0x12, 0x12, 0x12,
58e6753e37SKarsten Heimrich	0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
59e6753e37SKarsten Heimrich	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
60f6fd4d6aSStefano Ceccherini};
61f6fd4d6aSStefano Ceccherini
621c3a6ab0SStefano Ceccherini
631c3a6ab0SStefano Ceccherinistatic property_info
641c3a6ab0SStefano CeccherinisPropertyInfo[] = {
651c3a6ab0SStefano Ceccherini	{ "Orientation",
66f4fc3d62SJérôme Duval		{ B_GET_PROPERTY, B_SET_PROPERTY, 0 },
67f4fc3d62SJérôme Duval		{ B_DIRECT_SPECIFIER, 0 }, NULL, 0, { B_INT32_TYPE }
68f4fc3d62SJérôme Duval	},
69e6753e37SKarsten Heimrich
707730601aSStefano Ceccherini	{ 0 }
711c3a6ab0SStefano Ceccherini};
72e6753e37SKarsten Heimrich
73625c061aSAxel Dörfler
745fa4ff6aSKarsten Heimrichconst static float kPadding = 3.0;
757d84be4dSStefano Ceccherini
76e6753e37SKarsten Heimrich
77d89b690dSStephan AßmusBChannelSlider::BChannelSlider(BRect area, const char* name, const char* label,
78d89b690dSStephan Aßmus	BMessage* model, int32 channels, uint32 resizeMode, uint32 flags)
79625c061aSAxel Dörfler	: BChannelControl(area, name, label, model, channels, resizeMode, flags)
80625c061aSAxel Dörfler{
81e6753e37SKarsten Heimrich	_InitData();
82625c061aSAxel Dörfler}
83625c061aSAxel Dörfler
84625c061aSAxel Dörfler
85d89b690dSStephan AßmusBChannelSlider::BChannelSlider(BRect area, const char* name, const char* label,
86e724b26fSJohn Scipione	BMessage* model, orientation orientation, int32 channels,
872f86ba45SStephan Aßmus		uint32 resizeMode, uint32 flags)
88625c061aSAxel Dörfler	: BChannelControl(area, name, label, model, channels, resizeMode, flags)
891c3a6ab0SStefano Ceccherini
90625c061aSAxel Dörfler{
91e6753e37SKarsten Heimrich	_InitData();
922f86ba45SStephan Aßmus	SetOrientation(orientation);
932f86ba45SStephan Aßmus}
942f86ba45SStephan Aßmus
952f86ba45SStephan Aßmus
96d89b690dSStephan AßmusBChannelSlider::BChannelSlider(const char* name, const char* label,
97e724b26fSJohn Scipione	BMessage* model, orientation orientation, int32 channels,
982f86ba45SStephan Aßmus		uint32 flags)
992f86ba45SStephan Aßmus	: BChannelControl(name, label, model, channels, flags)
1002f86ba45SStephan Aßmus
1012f86ba45SStephan Aßmus{
1022f86ba45SStephan Aßmus	_InitData();
1032f86ba45SStephan Aßmus	SetOrientation(orientation);
104625c061aSAxel Dörfler}
105625c061aSAxel Dörfler
106625c061aSAxel Dörfler
107d89b690dSStephan AßmusBChannelSlider::BChannelSlider(BMessage* archive)
108625c061aSAxel Dörfler	: BChannelControl(archive)
109625c061aSAxel Dörfler{
110e6753e37SKarsten Heimrich	_InitData();
111859c5ac3SStefano Ceccherini
112859c5ac3SStefano Ceccherini	orientation orient;
113d89b690dSStephan Aßmus	if (archive->FindInt32("_orient", (int32*)&orient) == B_OK)
114859c5ac3SStefano Ceccherini		SetOrientation(orient);
115625c061aSAxel Dörfler}
116625c061aSAxel Dörfler
117625c061aSAxel Dörfler
118625c061aSAxel DörflerBChannelSlider::~BChannelSlider()
119625c061aSAxel Dörfler{
120e6753e37SKarsten Heimrich	delete fBacking;
121e605d526SStefano Ceccherini	delete fLeftKnob;
122e605d526SStefano Ceccherini	delete fMidKnob;
123e605d526SStefano Ceccherini	delete fRightKnob;
1245040785eSStefano Ceccherini	delete[] fInitialValues;
125625c061aSAxel Dörfler}
126625c061aSAxel Dörfler
127625c061aSAxel Dörfler
128d89b690dSStephan AßmusBArchivable*
129d89b690dSStephan AßmusBChannelSlider::Instantiate(BMessage* archive)
130625c061aSAxel Dörfler{
1311c3a6ab0SStefano Ceccherini	if (validate_instantiation(archive, "BChannelSlider"))
1325fa4ff6aSKarsten Heimrich		return new (std::nothrow) BChannelSlider(archive);
1335fa4ff6aSKarsten Heimrich
1345fa4ff6aSKarsten Heimrich	return NULL;
135625c061aSAxel Dörfler}
136625c061aSAxel Dörfler
137625c061aSAxel Dörfler
138625c061aSAxel Dörflerstatus_t
139d89b690dSStephan AßmusBChannelSlider::Archive(BMessage* into, bool deep) const
140625c061aSAxel Dörfler{
141859c5ac3SStefano Ceccherini	status_t status = BChannelControl::Archive(into, deep);
142859c5ac3SStefano Ceccherini	if (status == B_OK)
143859c5ac3SStefano Ceccherini		status = into->AddInt32("_orient", (int32)Orientation());
144859c5ac3SStefano Ceccherini
145859c5ac3SStefano Ceccherini	return status;
146625c061aSAxel Dörfler}
147625c061aSAxel Dörfler
148625c061aSAxel Dörfler
149625c061aSAxel Dörflervoid
150625c061aSAxel DörflerBChannelSlider::AttachedToWindow()
151625c061aSAxel Dörfler{
1527a96554cSlooncraz	AdoptParentColors();
153e6753e37SKarsten Heimrich	BChannelControl::AttachedToWindow();
154625c061aSAxel Dörfler}
155625c061aSAxel Dörfler
156625c061aSAxel Dörfler
157625c061aSAxel Dörflervoid
158625c061aSAxel DörflerBChannelSlider::AllAttached()
159625c061aSAxel Dörfler{
160e6753e37SKarsten Heimrich	BChannelControl::AllAttached();
161625c061aSAxel Dörfler}
162625c061aSAxel Dörfler
163625c061aSAxel Dörfler
164625c061aSAxel Dörflervoid
165625c061aSAxel DörflerBChannelSlider::DetachedFromWindow()
166625c061aSAxel Dörfler{
167e6753e37SKarsten Heimrich	BChannelControl::DetachedFromWindow();
168625c061aSAxel Dörfler}
169625c061aSAxel Dörfler
170625c061aSAxel Dörfler
171625c061aSAxel Dörflervoid
172625c061aSAxel DörflerBChannelSlider::AllDetached()
173625c061aSAxel Dörfler{
174e6753e37SKarsten Heimrich	BChannelControl::AllDetached();
175625c061aSAxel Dörfler}
176625c061aSAxel Dörfler
177625c061aSAxel Dörfler
178625c061aSAxel Dörflervoid
179d89b690dSStephan AßmusBChannelSlider::MessageReceived(BMessage* message)
180625c061aSAxel Dörfler{
1817a96554cSlooncraz	if (message->what == B_COLORS_UPDATED
1827a96554cSlooncraz		&& fBacking != NULL && fBackingView != NULL) {
1837a96554cSlooncraz		rgb_color color;
1847a96554cSlooncraz		if (message->FindColor(ui_color_name(B_PANEL_BACKGROUND_COLOR), &color)
1857a96554cSlooncraz				== B_OK
1867a96554cSlooncraz			&& fBacking->Lock()) {
1877a96554cSlooncraz
1887a96554cSlooncraz			if (fBackingView->LockLooper()) {
1897a96554cSlooncraz				fBackingView->SetLowColor(color);
1907a96554cSlooncraz				fBackingView->UnlockLooper();
1917a96554cSlooncraz			}
1927a96554cSlooncraz			fBacking->Unlock();
1937a96554cSlooncraz		}
1947a96554cSlooncraz	}
1957a96554cSlooncraz
196b9b67246SStefano Ceccherini	switch (message->what) {
197e6753e37SKarsten Heimrich		case B_SET_PROPERTY: {
198b9b67246SStefano Ceccherini		case B_GET_PROPERTY:
199b9b67246SStefano Ceccherini			BMessage reply(B_REPLY);
200b9b67246SStefano Ceccherini			int32 index = 0;
201b9b67246SStefano Ceccherini			BMessage specifier;
202b9b67246SStefano Ceccherini			int32 what = 0;
203d89b690dSStephan Aßmus			const char* property = NULL;
204b9b67246SStefano Ceccherini			bool handled = false;
205e6753e37SKarsten Heimrich			status_t status = message->GetCurrentSpecifier(&index, &specifier,
206d89b690dSStephan Aßmus				&what, &property);
207e6753e37SKarsten Heimrich			BPropertyInfo propInfo(sPropertyInfo);
208e6753e37SKarsten Heimrich			if (status == B_OK
209d89b690dSStephan Aßmus				&& propInfo.FindMatch(message, index, &specifier, what,
210d89b690dSStephan Aßmus					property) >= 0) {
211b9b67246SStefano Ceccherini				handled = true;
212b9b67246SStefano Ceccherini				if (message->what == B_SET_PROPERTY) {
213b9b67246SStefano Ceccherini					orientation orient;
214d89b690dSStephan Aßmus					if (specifier.FindInt32("data", (int32*)&orient) == B_OK) {
215b9b67246SStefano Ceccherini						SetOrientation(orient);
216b9b67246SStefano Ceccherini						Invalidate(Bounds());
217b9b67246SStefano Ceccherini					}
218b9b67246SStefano Ceccherini				} else if (message->what == B_GET_PROPERTY)
2195040785eSStefano Ceccherini					reply.AddInt32("result", (int32)Orientation());
2205040785eSStefano Ceccherini				else
221e6753e37SKarsten Heimrich					status = B_BAD_SCRIPT_SYNTAX;
222e6753e37SKarsten Heimrich			}
223e6753e37SKarsten Heimrich
224b9b67246SStefano Ceccherini			if (handled) {
225b9b67246SStefano Ceccherini				reply.AddInt32("error", status);
226b9b67246SStefano Ceccherini				message->SendReply(&reply);
227e6753e37SKarsten Heimrich			} else {
228e6753e37SKarsten Heimrich				BChannelControl::MessageReceived(message);
229e6753e37SKarsten Heimrich			}
230e6753e37SKarsten Heimrich		}	break;
231e6753e37SKarsten Heimrich
232b9b67246SStefano Ceccherini		default:
233e6753e37SKarsten Heimrich			BChannelControl::MessageReceived(message);
234b9b67246SStefano Ceccherini			break;
235b9b67246SStefano Ceccherini	}
236625c061aSAxel Dörfler}
237625c061aSAxel Dörfler
238625c061aSAxel Dörfler
239625c061aSAxel Dörflervoid
2401c3a6ab0SStefano CeccheriniBChannelSlider::Draw(BRect updateRect)
241625c061aSAxel Dörfler{
242e6753e37SKarsten Heimrich	_UpdateFontDimens();
243e6753e37SKarsten Heimrich	_DrawThumbs();
244e6753e37SKarsten Heimrich
2457a96554cSlooncraz	SetHighColor(ui_color(B_PANEL_TEXT_COLOR));
2465fa4ff6aSKarsten Heimrich	BRect bounds(Bounds());
24724ab95eeSJérôme Duval	if (Label()) {
24824ab95eeSJérôme Duval		float labelWidth = StringWidth(Label());
2495fa4ff6aSKarsten Heimrich		DrawString(Label(), BPoint((bounds.Width() - labelWidth) / 2.0,
2505fa4ff6aSKarsten Heimrich			fBaseLine));
2515fa4ff6aSKarsten Heimrich	}
252e6753e37SKarsten Heimrich
2535fa4ff6aSKarsten Heimrich	if (MinLimitLabel()) {
254d89b690dSStephan Aßmus		if (fIsVertical) {
2555fa4ff6aSKarsten Heimrich			if (MinLimitLabel()) {
256d89b690dSStephan Aßmus				float x = (bounds.Width() - StringWidth(MinLimitLabel()))
257d89b690dSStephan Aßmus					/ 2.0;
258d89b690dSStephan Aßmus				DrawString(MinLimitLabel(), BPoint(x, bounds.bottom
259d89b690dSStephan Aßmus					- kPadding));
2605fa4ff6aSKarsten Heimrich			}
2615fa4ff6aSKarsten Heimrich		} else {
262d89b690dSStephan Aßmus			if (MinLimitLabel()) {
263d89b690dSStephan Aßmus				DrawString(MinLimitLabel(), BPoint(kPadding, bounds.bottom
264d89b690dSStephan Aßmus					- kPadding));
265d89b690dSStephan Aßmus			}
2665fa4ff6aSKarsten Heimrich		}
2675fa4ff6aSKarsten Heimrich	}
2685fa4ff6aSKarsten Heimrich
2695fa4ff6aSKarsten Heimrich	if (MaxLimitLabel()) {
270d89b690dSStephan Aßmus		if (fIsVertical) {
2715fa4ff6aSKarsten Heimrich			if (MaxLimitLabel()) {
272d89b690dSStephan Aßmus				float x = (bounds.Width() - StringWidth(MaxLimitLabel()))
273d89b690dSStephan Aßmus					/ 2.0;
2745fa4ff6aSKarsten Heimrich				DrawString(MaxLimitLabel(), BPoint(x, 2 * fLineFeed));
2755fa4ff6aSKarsten Heimrich			}
2765fa4ff6aSKarsten Heimrich		} else {
2775fa4ff6aSKarsten Heimrich			if (MaxLimitLabel()) {
278d89b690dSStephan Aßmus				DrawString(MaxLimitLabel(), BPoint(bounds.right - kPadding
279d89b690dSStephan Aßmus					- StringWidth(MaxLimitLabel()), bounds.bottom - kPadding));
2805fa4ff6aSKarsten Heimrich			}
2815fa4ff6aSKarsten Heimrich		}
28224ab95eeSJérôme Duval	}
283625c061aSAxel Dörfler}
284625c061aSAxel Dörfler
285625c061aSAxel Dörfler
286625c061aSAxel Dörflervoid
287625c061aSAxel DörflerBChannelSlider::MouseDown(BPoint where)
288625c061aSAxel Dörfler{
2890677ddf4SStefano Ceccherini	if (!IsEnabled())
2900677ddf4SStefano Ceccherini		BControl::MouseDown(where);
2910677ddf4SStefano Ceccherini	else {
2920677ddf4SStefano Ceccherini		fCurrentChannel = -1;
293d89b690dSStephan Aßmus		fMinPoint = 0;
294e6753e37SKarsten Heimrich
2950677ddf4SStefano Ceccherini		// Search the channel on which the mouse was over
296e6753e37SKarsten Heimrich		int32 numChannels = CountChannels();
2970677ddf4SStefano Ceccherini		for (int32 channel = 0; channel < numChannels; channel++) {
2980677ddf4SStefano Ceccherini			BRect frame = ThumbFrameFor(channel);
2990677ddf4SStefano Ceccherini			frame.OffsetBy(fClickDelta);
300e6753e37SKarsten Heimrich
3010677ddf4SStefano Ceccherini			float range = ThumbRangeFor(channel);
302d89b690dSStephan Aßmus			if (fIsVertical) {
303d89b690dSStephan Aßmus				fMinPoint = frame.top + frame.Height() / 2;
3040677ddf4SStefano Ceccherini				frame.bottom += range;
3050677ddf4SStefano Ceccherini			} else {
3067d84be4dSStefano Ceccherini				// TODO: Fix this, the clickzone isn't perfect
3075040785eSStefano Ceccherini				frame.right += range;
308d89b690dSStephan Aßmus				fMinPoint = frame.Width();
3090677ddf4SStefano Ceccherini			}
310e6753e37SKarsten Heimrich
3117d84be4dSStefano Ceccherini			// Click was on a slider.
3120677ddf4SStefano Ceccherini			if (frame.Contains(where)) {
3130677ddf4SStefano Ceccherini				fCurrentChannel = channel;
314789b86ecSJérôme Duval				SetCurrentChannel(channel);
315d6b77167SStefano Ceccherini				break;
316e6753e37SKarsten Heimrich			}
317e6753e37SKarsten Heimrich		}
318e6753e37SKarsten Heimrich
3197d84be4dSStefano Ceccherini		// Click wasn't on a slider. Bail out.
320e7467adaSStefano Ceccherini		if (fCurrentChannel == -1)
321e7467adaSStefano Ceccherini			return;
322e6753e37SKarsten Heimrich
323e7467adaSStefano Ceccherini		uint32 buttons = 0;
324d89b690dSStephan Aßmus		BMessage* currentMessage = Window()->CurrentMessage();
325e7467adaSStefano Ceccherini		if (currentMessage != NULL)
326d89b690dSStephan Aßmus			currentMessage->FindInt32("buttons", (int32*)&buttons);
327e6753e37SKarsten Heimrich
328e7467adaSStefano Ceccherini		fAllChannels = (buttons & B_SECONDARY_MOUSE_BUTTON) == 0;
329e6753e37SKarsten Heimrich
330e7467adaSStefano Ceccherini		if (fInitialValues != NULL && fAllChannels) {
331e7467adaSStefano Ceccherini			delete[] fInitialValues;
332e7467adaSStefano Ceccherini			fInitialValues = NULL;
333e7467adaSStefano Ceccherini		}
334e6753e37SKarsten Heimrich
335e7467adaSStefano Ceccherini		if (fInitialValues == NULL)
3365fa4ff6aSKarsten Heimrich			fInitialValues = new (std::nothrow) int32[numChannels];
337e6753e37SKarsten Heimrich
3385fa4ff6aSKarsten Heimrich		if (fInitialValues) {
3395fa4ff6aSKarsten Heimrich			if (fAllChannels) {
3405fa4ff6aSKarsten Heimrich				for (int32 i = 0; i < numChannels; i++)
3415fa4ff6aSKarsten Heimrich					fInitialValues[i] = ValueFor(i);
3425fa4ff6aSKarsten Heimrich			} else {
3435fa4ff6aSKarsten Heimrich				fInitialValues[fCurrentChannel] = ValueFor(fCurrentChannel);
3445fa4ff6aSKarsten Heimrich			}
3455fa4ff6aSKarsten Heimrich		}
346e6753e37SKarsten Heimrich
347e7467adaSStefano Ceccherini		if (Window()->Flags() & B_ASYNCHRONOUS_CONTROLS) {
348e7467adaSStefano Ceccherini			if (!IsTracking()) {
349e7467adaSStefano Ceccherini				SetTracking(true);
350e6753e37SKarsten Heimrich				_DrawThumbs();
351e6753e37SKarsten Heimrich				Flush();
3520677ddf4SStefano Ceccherini			}
353e6753e37SKarsten Heimrich
354e6753e37SKarsten Heimrich			_MouseMovedCommon(where, B_ORIGIN);
355e6753e37SKarsten Heimrich			SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS |
356e6753e37SKarsten Heimrich				B_NO_POINTER_HISTORY);
357e7467adaSStefano Ceccherini		} else {
358e7467adaSStefano Ceccherini			do {
359e7467adaSStefano Ceccherini				snooze(30000);
360e7467adaSStefano Ceccherini				GetMouse(&where, &buttons);
361e6753e37SKarsten Heimrich				_MouseMovedCommon(where, B_ORIGIN);
362e7467adaSStefano Ceccherini			} while (buttons != 0);
363e6753e37SKarsten Heimrich			_FinishChange();
364e7467adaSStefano Ceccherini			fCurrentChannel = -1;
365e7467adaSStefano Ceccherini			fAllChannels = false;
3660677ddf4SStefano Ceccherini		}
3670677ddf4SStefano Ceccherini	}
368625c061aSAxel Dörfler}
369625c061aSAxel Dörfler
370625c061aSAxel Dörfler
371625c061aSAxel Dörflervoid
3721c3a6ab0SStefano CeccheriniBChannelSlider::MouseUp(BPoint where)
373625c061aSAxel Dörfler{
3740677ddf4SStefano Ceccherini	if (IsEnabled() && IsTracking()) {
375e6753e37SKarsten Heimrich		_FinishChange();
3760677ddf4SStefano Ceccherini		SetTracking(false);
3770677ddf4SStefano Ceccherini		fAllChannels = false;
3780677ddf4SStefano Ceccherini		fCurrentChannel = -1;
379d89b690dSStephan Aßmus		fMinPoint = 0;
3805fa4ff6aSKarsten Heimrich	} else {
381e6753e37SKarsten Heimrich		BChannelControl::MouseUp(where);
3825fa4ff6aSKarsten Heimrich	}
383625c061aSAxel Dörfler}
384625c061aSAxel Dörfler
385625c061aSAxel Dörfler
386625c061aSAxel Dörflervoid
387d89b690dSStephan AßmusBChannelSlider::MouseMoved(BPoint where, uint32 code, const BMessage* message)
388625c061aSAxel Dörfler{
3891c3a6ab0SStefano Ceccherini	if (IsEnabled() && IsTracking())
390e6753e37SKarsten Heimrich		_MouseMovedCommon(where, B_ORIGIN);
3911c3a6ab0SStefano Ceccherini	else
392e6753e37SKarsten Heimrich		BChannelControl::MouseMoved(where, code, message);
393625c061aSAxel Dörfler}
394625c061aSAxel Dörfler
395625c061aSAxel Dörfler
396625c061aSAxel Dörflervoid
397625c061aSAxel DörflerBChannelSlider::WindowActivated(bool state)
398625c061aSAxel Dörfler{
399e6753e37SKarsten Heimrich	BChannelControl::WindowActivated(state);
400625c061aSAxel Dörfler}
401625c061aSAxel Dörfler
402625c061aSAxel Dörfler
403625c061aSAxel Dörflervoid
404d89b690dSStephan AßmusBChannelSlider::KeyDown(const char* bytes, int32 numBytes)
405625c061aSAxel Dörfler{
4060677ddf4SStefano Ceccherini	BControl::KeyDown(bytes, numBytes);
407625c061aSAxel Dörfler}
408625c061aSAxel Dörfler
409625c061aSAxel Dörfler
410625c061aSAxel Dörflervoid
411d89b690dSStephan AßmusBChannelSlider::KeyUp(const char* bytes, int32 numBytes)
412625c061aSAxel Dörfler{
4131c3a6ab0SStefano Ceccherini	BView::KeyUp(bytes, numBytes);
414625c061aSAxel Dörfler}
415625c061aSAxel Dörfler
416625c061aSAxel Dörfler
417625c061aSAxel Dörflervoid
4181c3a6ab0SStefano CeccheriniBChannelSlider::FrameResized(float newWidth, float newHeight)
419625c061aSAxel Dörfler{
420e6753e37SKarsten Heimrich	BChannelControl::FrameResized(newWidth, newHeight);
4212f86ba45SStephan Aßmus
4222f86ba45SStephan Aßmus	delete fBacking;
4232f86ba45SStephan Aßmus	fBacking = NULL;
4242f86ba45SStephan Aßmus
4251c3a6ab0SStefano Ceccherini	Invalidate(Bounds());
426625c061aSAxel Dörfler}
427625c061aSAxel Dörfler
428625c061aSAxel Dörfler
429625c061aSAxel Dörflervoid
430d89b690dSStephan AßmusBChannelSlider::SetFont(const BFont* font, uint32 mask)
431625c061aSAxel Dörfler{
432e6753e37SKarsten Heimrich	BChannelControl::SetFont(font, mask);
433625c061aSAxel Dörfler}
434625c061aSAxel Dörfler
435625c061aSAxel Dörfler
436625c061aSAxel Dörflervoid
437625c061aSAxel DörflerBChannelSlider::MakeFocus(bool focusState)
438625c061aSAxel Dörfler{
4391c3a6ab0SStefano Ceccherini	if (focusState && !IsFocus())
4401c3a6ab0SStefano Ceccherini		fFocusChannel = -1;
441e6753e37SKarsten Heimrich	BChannelControl::MakeFocus(focusState);
442625c061aSAxel Dörfler}
443625c061aSAxel Dörfler
444625c061aSAxel Dörfler
445625c061aSAxel Dörflervoid
446d89b690dSStephan AßmusBChannelSlider::GetPreferredSize(float* width, float* height)
447625c061aSAxel Dörfler{
4485fa4ff6aSKarsten Heimrich	_UpdateFontDimens();
4495fa4ff6aSKarsten Heimrich
450d89b690dSStephan Aßmus	if (fIsVertical) {
4515fa4ff6aSKarsten Heimrich		*width = 11.0 * CountChannels();
4525fa4ff6aSKarsten Heimrich		*width = max_c(*width, ceilf(StringWidth(Label())));
4535fa4ff6aSKarsten Heimrich		*width = max_c(*width, ceilf(StringWidth(MinLimitLabel())));
4545fa4ff6aSKarsten Heimrich		*width = max_c(*width, ceilf(StringWidth(MaxLimitLabel())));
4555fa4ff6aSKarsten Heimrich		*width += kPadding * 2.0;
4565fa4ff6aSKarsten Heimrich
4575fa4ff6aSKarsten Heimrich		*height = (fLineFeed * 3.0) + (kPadding * 2.0) + 147.0;
4585fa4ff6aSKarsten Heimrich	} else {
4595fa4ff6aSKarsten Heimrich		*width = max_c(64.0, ceilf(StringWidth(Label())));
460d89b690dSStephan Aßmus		*width = max_c(*width, ceilf(StringWidth(MinLimitLabel()))
461d89b690dSStephan Aßmus			+ ceilf(StringWidth(MaxLimitLabel())) + 10.0);
4625fa4ff6aSKarsten Heimrich		*width += kPadding * 2.0;
4635fa4ff6aSKarsten Heimrich
464d89b690dSStephan Aßmus		*height = 11.0 * CountChannels() + (fLineFeed * 2.0)
465d89b690dSStephan Aßmus			+ (kPadding * 2.0);
4662879eb37SJérôme Duval	}
467625c061aSAxel Dörfler}
468625c061aSAxel Dörfler
469625c061aSAxel Dörfler
470d89b690dSStephan AßmusBHandler*
471d89b690dSStephan AßmusBChannelSlider::ResolveSpecifier(BMessage* message, int32 index,
472d89b690dSStephan Aßmus	BMessage* specifier, int32 form, const char* property)
473625c061aSAxel Dörfler{
474d89b690dSStephan Aßmus	BHandler* target = this;
475016e74b2SStefano Ceccherini	BPropertyInfo propertyInfo(sPropertyInfo);
476d89b690dSStephan Aßmus	if (propertyInfo.FindMatch(message, index, specifier, form,
477d89b690dSStephan Aßmus		property) != B_OK) {
478d89b690dSStephan Aßmus		target = BChannelControl::ResolveSpecifier(message, index, specifier,
479d89b690dSStephan Aßmus			form, property);
480e6753e37SKarsten Heimrich	}
481016e74b2SStefano Ceccherini	return target;
482625c061aSAxel Dörfler}
483625c061aSAxel Dörfler
484625c061aSAxel Dörfler
485625c061aSAxel Dörflerstatus_t
486d89b690dSStephan AßmusBChannelSlider::GetSupportedSuites(BMessage* data)
487625c061aSAxel Dörfler{
4881c3a6ab0SStefano Ceccherini	if (data == NULL)
4891c3a6ab0SStefano Ceccherini		return B_BAD_VALUE;
490e6753e37SKarsten Heimrich
491f4fc3d62SJérôme Duval	status_t err = data->AddString("suites", "suite/vnd.Be-channel-slider");
4921c3a6ab0SStefano Ceccherini
4931c3a6ab0SStefano Ceccherini	BPropertyInfo propInfo(sPropertyInfo);
494f4fc3d62SJérôme Duval	if (err == B_OK)
495f4fc3d62SJérôme Duval		err = data->AddFlat("messages", &propInfo);
496e6753e37SKarsten Heimrich
497f4fc3d62SJérôme Duval	if (err == B_OK)
498f4fc3d62SJérôme Duval		return BChannelControl::GetSupportedSuites(data);
499f4fc3d62SJérôme Duval	return err;
500625c061aSAxel Dörfler}
501625c061aSAxel Dörfler
502625c061aSAxel Dörfler
503625c061aSAxel Dörflervoid
504d89b690dSStephan AßmusBChannelSlider::SetEnabled(bool on)
505d89b690dSStephan Aßmus{
506d89b690dSStephan Aßmus	BChannelControl::SetEnabled(on);
507d89b690dSStephan Aßmus}
508d89b690dSStephan Aßmus
509d89b690dSStephan Aßmus
510d89b690dSStephan Aßmusorientation
511d89b690dSStephan AßmusBChannelSlider::Orientation() const
512d89b690dSStephan Aßmus{
513d89b690dSStephan Aßmus	return fIsVertical ? B_VERTICAL : B_HORIZONTAL;
514d89b690dSStephan Aßmus}
515d89b690dSStephan Aßmus
516d89b690dSStephan Aßmus
517d89b690dSStephan Aßmusvoid
518e724b26fSJohn ScipioneBChannelSlider::SetOrientation(orientation orientation)
519d89b690dSStephan Aßmus{
520d89b690dSStephan Aßmus	bool isVertical = orientation == B_VERTICAL;
521d89b690dSStephan Aßmus	if (isVertical != fIsVertical) {
522d89b690dSStephan Aßmus		fIsVertical = isVertical;
523d89b690dSStephan Aßmus		InvalidateLayout();
524d89b690dSStephan Aßmus		Invalidate(Bounds());
525d89b690dSStephan Aßmus	}
526d89b690dSStephan Aßmus}
527d89b690dSStephan Aßmus
528d89b690dSStephan Aßmus
529d89b690dSStephan Aßmusint32
530d89b690dSStephan AßmusBChannelSlider::MaxChannelCount() const
531d89b690dSStephan Aßmus{
532d89b690dSStephan Aßmus	return 32;
533d89b690dSStephan Aßmus}
534d89b690dSStephan Aßmus
535d89b690dSStephan Aßmus
536d89b690dSStephan Aßmusbool
537d89b690dSStephan AßmusBChannelSlider::SupportsIndividualLimits() const
538d89b690dSStephan Aßmus{
539d89b690dSStephan Aßmus	return false;
540d89b690dSStephan Aßmus}
541d89b690dSStephan Aßmus
542d89b690dSStephan Aßmus
543d89b690dSStephan Aßmusvoid
544d89b690dSStephan AßmusBChannelSlider::DrawChannel(BView* into, int32 channel, BRect area,
545d89b690dSStephan Aßmus	bool pressed)
546625c061aSAxel Dörfler{
5475040785eSStefano Ceccherini	float hCenter = area.Width() / 2;
5485040785eSStefano Ceccherini	float vCenter = area.Height() / 2;
549e6753e37SKarsten Heimrich
5505040785eSStefano Ceccherini	BPoint leftTop;
5515040785eSStefano Ceccherini	BPoint bottomRight;
552d89b690dSStephan Aßmus	if (fIsVertical) {
553347f3fa3SStefano Ceccherini		leftTop.Set(area.left + hCenter, area.top + vCenter);
554d6b77167SStefano Ceccherini		bottomRight.Set(leftTop.x, leftTop.y + ThumbRangeFor(channel));
5555040785eSStefano Ceccherini	} else {
5565040785eSStefano Ceccherini		leftTop.Set(area.left, area.top + vCenter);
5575040785eSStefano Ceccherini		bottomRight.Set(area.left + ThumbRangeFor(channel), leftTop.y);
558e6753e37SKarsten Heimrich	}
559e6753e37SKarsten Heimrich
560e605d526SStefano Ceccherini	DrawGroove(into, channel, leftTop, bottomRight);
561e6753e37SKarsten Heimrich
562b9b67246SStefano Ceccherini	BPoint thumbLocation = leftTop;
563d89b690dSStephan Aßmus	if (fIsVertical)
5645040785eSStefano Ceccherini		thumbLocation.y += ThumbDeltaFor(channel);
565d6b77167SStefano Ceccherini	else
566d6b77167SStefano Ceccherini		thumbLocation.x += ThumbDeltaFor(channel);
567e6753e37SKarsten Heimrich
568b9b67246SStefano Ceccherini	DrawThumb(into, channel, thumbLocation, pressed);
569625c061aSAxel Dörfler}
570625c061aSAxel Dörfler
571625c061aSAxel Dörfler
572625c061aSAxel Dörflervoid
573d89b690dSStephan AßmusBChannelSlider::DrawGroove(BView* into, int32 channel, BPoint leftTop,
574e6753e37SKarsten Heimrich	BPoint bottomRight)
575625c061aSAxel Dörfler{
576859c5ac3SStefano Ceccherini	ASSERT(into != NULL);
577e6753e37SKarsten Heimrich	BRect rect(leftTop, bottomRight);
578e6753e37SKarsten Heimrich
579e716f487SStefano Ceccherini	rect.InsetBy(-2.5, -2.5);
580e716f487SStefano Ceccherini	rect.left = floorf(rect.left);
581e716f487SStefano Ceccherini	rect.top = floorf(rect.top);
582e716f487SStefano Ceccherini	rect.right = floorf(rect.right);
583e716f487SStefano Ceccherini	rect.bottom = floorf(rect.bottom);
584e716f487SStefano Ceccherini	rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
585e716f487SStefano Ceccherini	rgb_color barColor = be_control_look->SliderBarColor(base);
586e716f487SStefano Ceccherini	uint32 flags = 0;
587e716f487SStefano Ceccherini	be_control_look->DrawSliderBar(into, rect, rect, base,
588e716f487SStefano Ceccherini		barColor, flags, Orientation());
589625c061aSAxel Dörfler}
590625c061aSAxel Dörfler
591625c061aSAxel Dörfler
592625c061aSAxel Dörflervoid
593d89b690dSStephan AßmusBChannelSlider::DrawThumb(BView* into, int32 channel, BPoint where,
594d89b690dSStephan Aßmus	bool pressed)
595625c061aSAxel Dörfler{
5961c3a6ab0SStefano Ceccherini	ASSERT(into != NULL);
597e6753e37SKarsten Heimrich
598d89b690dSStephan Aßmus	const BBitmap* thumb = ThumbFor(channel, pressed);
599fd873802SStefano Ceccherini	if (thumb == NULL)
600fd873802SStefano Ceccherini		return;
601fd873802SStefano Ceccherini
6025fa4ff6aSKarsten Heimrich	BRect bitmapBounds(thumb->Bounds());
6035fa4ff6aSKarsten Heimrich	where.x -= bitmapBounds.right / 2.0;
6045fa4ff6aSKarsten Heimrich	where.y -= bitmapBounds.bottom / 2.0;
605e6753e37SKarsten Heimrich
606e716f487SStefano Ceccherini	BRect rect(bitmapBounds.OffsetToCopy(where));
607e716f487SStefano Ceccherini	rect.InsetBy(1, 1);
608e716f487SStefano Ceccherini	rect.left = floorf(rect.left);
609e716f487SStefano Ceccherini	rect.top = floorf(rect.top);
610e716f487SStefano Ceccherini	rect.right = ceilf(rect.right + 0.5);
611e716f487SStefano Ceccherini	rect.bottom = ceilf(rect.bottom + 0.5);
612e716f487SStefano Ceccherini	rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR);
613e716f487SStefano Ceccherini	uint32 flags = 0;
614e716f487SStefano Ceccherini	be_control_look->DrawSliderThumb(into, rect, rect, base,
615e716f487SStefano Ceccherini		flags, Orientation());
616625c061aSAxel Dörfler}
617625c061aSAxel Dörfler
618625c061aSAxel Dörfler
619d89b690dSStephan Aßmusconst BBitmap*
620625c061aSAxel DörflerBChannelSlider::ThumbFor(int32 channel, bool pressed)
621625c061aSAxel Dörfler{
6229b780235SStefano Ceccherini	if (fLeftKnob != NULL)
6239b780235SStefano Ceccherini		return fLeftKnob;
6249b780235SStefano Ceccherini
6259b780235SStefano Ceccherini	if (fIsVertical) {
6269b780235SStefano Ceccherini		fLeftKnob = new (std::nothrow) BBitmap(BRect(0, 0, 11, 14),
6279b780235SStefano Ceccherini			B_CMAP8);
6289b780235SStefano Ceccherini		if (fLeftKnob != NULL) {
6299b780235SStefano Ceccherini			fLeftKnob->SetBits(kVerticalKnobData,
6309b780235SStefano Ceccherini					sizeof(kVerticalKnobData), 0, B_CMAP8);
6319b780235SStefano Ceccherini		}
6329b780235SStefano Ceccherini	} else {
6339b780235SStefano Ceccherini		fLeftKnob = new (std::nothrow) BBitmap(BRect(0, 0, 14, 11),
6349b780235SStefano Ceccherini			B_CMAP8);
6359b780235SStefano Ceccherini		if (fLeftKnob != NULL) {
636d89b690dSStephan Aßmus			fLeftKnob->SetBits(kHorizontalKnobData,
6379b780235SStefano Ceccherini					sizeof(kHorizontalKnobData), 0, B_CMAP8);
638f6fd4d6aSStefano Ceccherini		}
639f6fd4d6aSStefano Ceccherini	}
640e6753e37SKarsten Heimrich
641f6fd4d6aSStefano Ceccherini	return fLeftKnob;
642625c061aSAxel Dörfler}
643625c061aSAxel Dörfler
644625c061aSAxel Dörfler
6451c3a6ab0SStefano CeccheriniBRect
646625c061aSAxel DörflerBChannelSlider::ThumbFrameFor(int32 channel)
647625c061aSAxel Dörfler{
648e6753e37SKarsten Heimrich	_UpdateFontDimens();
649e6753e37SKarsten Heimrich
6505fa4ff6aSKarsten Heimrich	BRect frame(0.0, 0.0, 0.0, 0.0);
651d89b690dSStephan Aßmus	const BBitmap* thumb = ThumbFor(channel, false);
6521c3a6ab0SStefano Ceccherini	if (thumb != NULL) {
6531c3a6ab0SStefano Ceccherini		frame = thumb->Bounds();
654d89b690dSStephan Aßmus		if (fIsVertical) {
6555fa4ff6aSKarsten Heimrich			frame.OffsetBy(channel * frame.Width(), (frame.Height() / 2.0) -
6565fa4ff6aSKarsten Heimrich				(kPadding * 2.0) - 1.0);
6575fa4ff6aSKarsten Heimrich		} else {
658d89b690dSStephan Aßmus			frame.OffsetBy(frame.Width() / 2.0, channel * frame.Height()
659d89b690dSStephan Aßmus				+ 1.0);
6605fa4ff6aSKarsten Heimrich		}
6611c3a6ab0SStefano Ceccherini	}
662e6753e37SKarsten Heimrich	return frame;
663625c061aSAxel Dörfler}
664625c061aSAxel Dörfler
665625c061aSAxel Dörfler
6661c3a6ab0SStefano Ceccherinifloat
667625c061aSAxel DörflerBChannelSlider::ThumbDeltaFor(int32 channel)
668625c061aSAxel Dörfler{
6695fa4ff6aSKarsten Heimrich	float delta = 0.0;
6701c3a6ab0SStefano Ceccherini	if (channel >= 0 && channel < MaxChannelCount()) {
6711c3a6ab0SStefano Ceccherini		float range = ThumbRangeFor(channel);
6721c3a6ab0SStefano Ceccherini		int32 limitRange = MaxLimitList()[channel] - MinLimitList()[channel];
673d89b690dSStephan Aßmus		delta = (ValueList()[channel] - MinLimitList()[channel]) * range
674d89b690dSStephan Aßmus			/ limitRange;
675e6753e37SKarsten Heimrich
676d89b690dSStephan Aßmus		if (fIsVertical)
6771c3a6ab0SStefano Ceccherini			delta = range - delta;
6781c3a6ab0SStefano Ceccherini	}
679e6753e37SKarsten Heimrich
680e6753e37SKarsten Heimrich	return delta;
681625c061aSAxel Dörfler}
682625c061aSAxel Dörfler
683625c061aSAxel Dörfler
6841c3a6ab0SStefano Ceccherinifloat
685625c061aSAxel DörflerBChannelSlider::ThumbRangeFor(int32 channel)
686625c061aSAxel Dörfler{
687e6753e37SKarsten Heimrich	_UpdateFontDimens();
688e6753e37SKarsten Heimrich
689e6753e37SKarsten Heimrich	float range = 0;
6901c3a6ab0SStefano Ceccherini	BRect bounds = Bounds();
6911c3a6ab0SStefano Ceccherini	BRect frame = ThumbFrameFor(channel);
692d89b690dSStephan Aßmus	if (fIsVertical) {
6935fa4ff6aSKarsten Heimrich		// *height = (fLineFeed * 3.0) + (kPadding * 2.0) + 100.0;
6945fa4ff6aSKarsten Heimrich		range = bounds.Height() - frame.Height() - (fLineFeed * 3.0) -
6955fa4ff6aSKarsten Heimrich			(kPadding * 2.0);
6965fa4ff6aSKarsten Heimrich	} else {
6975fa4ff6aSKarsten Heimrich		// *width = some width + kPadding * 2.0;
6985fa4ff6aSKarsten Heimrich		range = bounds.Width() - frame.Width() - (kPadding * 2.0);
6995fa4ff6aSKarsten Heimrich	}
700e6753e37SKarsten Heimrich	return range;
701625c061aSAxel Dörfler}
702625c061aSAxel Dörfler
703625c061aSAxel Dörfler
704d89b690dSStephan Aßmus// #pragma mark -
705d89b690dSStephan Aßmus
706d89b690dSStephan Aßmus
7071c3a6ab0SStefano Ceccherinivoid
708e6753e37SKarsten HeimrichBChannelSlider::_InitData()
709625c061aSAxel Dörfler{
710e6753e37SKarsten Heimrich	_UpdateFontDimens();
711e6753e37SKarsten Heimrich
712422c0791SStefano Ceccherini	fLeftKnob = NULL;
713422c0791SStefano Ceccherini	fMidKnob = NULL;
714422c0791SStefano Ceccherini	fRightKnob = NULL;
715422c0791SStefano Ceccherini	fBacking = NULL;
716422c0791SStefano Ceccherini	fBackingView = NULL;
717d89b690dSStephan Aßmus	fIsVertical = Bounds().Width() / Bounds().Height() < 1;
718422c0791SStefano Ceccherini	fClickDelta = B_ORIGIN;
719e6753e37SKarsten Heimrich
7201c3a6ab0SStefano Ceccherini	fCurrentChannel = -1;
7211c3a6ab0SStefano Ceccherini	fAllChannels = false;
7221c3a6ab0SStefano Ceccherini	fInitialValues = NULL;
723d89b690dSStephan Aßmus	fMinPoint = 0;
7241c3a6ab0SStefano Ceccherini	fFocusChannel = -1;
725625c061aSAxel Dörfler}
726625c061aSAxel Dörfler
727625c061aSAxel Dörfler
7281c3a6ab0SStefano Ceccherinivoid
729310177b4SRene GollentBChannelSlider::_FinishChange(bool update)
730625c061aSAxel Dörfler{
7311c3a6ab0SStefano Ceccherini	if (fInitialValues != NULL) {
732d89b690dSStephan Aßmus		bool* inMask = NULL;
733789b86ecSJérôme Duval		int32 numChannels = CountChannels();
734789b86ecSJérôme Duval		if (!fAllChannels) {
7355fa4ff6aSKarsten Heimrich			inMask = new (std::nothrow) bool[CountChannels()];
7365fa4ff6aSKarsten Heimrich			if (inMask) {
7379b780235SStefano Ceccherini				for (int i = 0; i < numChannels; i++)
7385fa4ff6aSKarsten Heimrich					inMask[i] = false;
7395fa4ff6aSKarsten Heimrich				inMask[fCurrentChannel] = true;
7405fa4ff6aSKarsten Heimrich			}
7411c3a6ab0SStefano Ceccherini		}
742d89b690dSStephan Aßmus		InvokeChannel(update ? ModificationMessage() : NULL, 0, numChannels,
743d89b690dSStephan Aßmus			inMask);
7449b780235SStefano Ceccherini
7459b780235SStefano Ceccherini		delete[] inMask;
7461c3a6ab0SStefano Ceccherini	}
747e6753e37SKarsten Heimrich
748310177b4SRene Gollent	if (!update) {
749310177b4SRene Gollent		SetTracking(false);
750d89b690dSStephan Aßmus		Invalidate();
751310177b4SRene Gollent	}
752625c061aSAxel Dörfler}
753625c061aSAxel Dörfler
754625c061aSAxel Dörfler
7551c3a6ab0SStefano Ceccherinivoid
756e6753e37SKarsten HeimrichBChannelSlider::_UpdateFontDimens()
757625c061aSAxel Dörfler{
7581c3a6ab0SStefano Ceccherini	font_height height;
7591c3a6ab0SStefano Ceccherini	GetFontHeight(&height);
760422c0791SStefano Ceccherini	fBaseLine = height.ascent + height.leading;
761422c0791SStefano Ceccherini	fLineFeed = fBaseLine + height.descent;
762625c061aSAxel Dörfler}
763625c061aSAxel Dörfler
764625c061aSAxel Dörfler
7651c3a6ab0SStefano Ceccherinivoid
766e6753e37SKarsten HeimrichBChannelSlider::_DrawThumbs()
767e6753e37SKarsten Heimrich{
768e605d526SStefano Ceccherini	if (fBacking == NULL) {
769d6b77167SStefano Ceccherini		// This is the idea: we build a bitmap by taking the coordinates
7702879eb37SJérôme Duval		// of the first and last thumb frames (top/left and bottom/right)
771d6b77167SStefano Ceccherini		BRect first = ThumbFrameFor(0);
772d6b77167SStefano Ceccherini		BRect last = ThumbFrameFor(CountChannels() - 1);
7735fa4ff6aSKarsten Heimrich		BRect rect(first.LeftTop(), last.RightBottom());
774e6753e37SKarsten Heimrich
775d89b690dSStephan Aßmus		if (fIsVertical)
7765fa4ff6aSKarsten Heimrich			rect.top -= ThumbRangeFor(0);
777d6b77167SStefano Ceccherini		else
7785fa4ff6aSKarsten Heimrich			rect.right += ThumbRangeFor(0);
7795fa4ff6aSKarsten Heimrich
7805fa4ff6aSKarsten Heimrich		rect.OffsetTo(B_ORIGIN);
7815fa4ff6aSKarsten Heimrich		fBacking = new (std::nothrow) BBitmap(rect, B_RGB32, true);
7825fa4ff6aSKarsten Heimrich		if (fBacking) {
7835fa4ff6aSKarsten Heimrich			fBackingView = new (std::nothrow) BView(rect, "", 0, B_WILL_DRAW);
7845fa4ff6aSKarsten Heimrich			if (fBackingView) {
7855fa4ff6aSKarsten Heimrich				if (fBacking->Lock()) {
7865fa4ff6aSKarsten Heimrich					fBacking->AddChild(fBackingView);
7875fa4ff6aSKarsten Heimrich					fBackingView->SetFontSize(10.0);
788d89b690dSStephan Aßmus					fBackingView->SetLowColor(
789d89b690dSStephan Aßmus						ui_color(B_PANEL_BACKGROUND_COLOR));
790d89b690dSStephan Aßmus					fBackingView->SetViewColor(
791d89b690dSStephan Aßmus						ui_color(B_PANEL_BACKGROUND_COLOR));
7925fa4ff6aSKarsten Heimrich					fBacking->Unlock();
7935fa4ff6aSKarsten Heimrich				}
7945fa4ff6aSKarsten Heimrich			} else {
7955fa4ff6aSKarsten Heimrich				delete fBacking;
7965fa4ff6aSKarsten Heimrich				fBacking = NULL;
7975fa4ff6aSKarsten Heimrich			}
7982879eb37SJérôme Duval		}
799e605d526SStefano Ceccherini	}
800e6753e37SKarsten Heimrich
8015fa4ff6aSKarsten Heimrich	if (fBacking && fBackingView) {
802a20769b3SAdrien Destugues		BPoint drawHere;
803a20769b3SAdrien Destugues
804a20769b3SAdrien Destugues		BRect bounds(fBacking->Bounds());
805a20769b3SAdrien Destugues		drawHere.x = (Bounds().Width() - bounds.Width()) / 2.0;
806a20769b3SAdrien Destugues		drawHere.y = (Bounds().Height() - bounds.Height()) - kPadding
807a20769b3SAdrien Destugues			- fLineFeed;
808a20769b3SAdrien Destugues
8095fa4ff6aSKarsten Heimrich		if (fBacking->Lock()) {
8105fa4ff6aSKarsten Heimrich			// Clear the view's background
8115fa4ff6aSKarsten Heimrich			fBackingView->FillRect(fBackingView->Bounds(), B_SOLID_LOW);
8125fa4ff6aSKarsten Heimrich
8135fa4ff6aSKarsten Heimrich			BRect channelArea;
8145fa4ff6aSKarsten Heimrich			// draw the entire control
8155fa4ff6aSKarsten Heimrich			for (int32 channel = 0; channel < CountChannels(); channel++) {
8165fa4ff6aSKarsten Heimrich				channelArea = ThumbFrameFor(channel);
8175fa4ff6aSKarsten Heimrich				bool pressed = IsTracking()
8185fa4ff6aSKarsten Heimrich					&& (channel == fCurrentChannel || fAllChannels);
8195fa4ff6aSKarsten Heimrich				DrawChannel(fBackingView, channel, channelArea, pressed);
8205fa4ff6aSKarsten Heimrich			}
8215fa4ff6aSKarsten Heimrich
8225fa4ff6aSKarsten Heimrich			// draw some kind of current value tool tip
823d89b690dSStephan Aßmus			if (fCurrentChannel != -1 && fMinPoint != 0) {
8245fa4ff6aSKarsten Heimrich				char valueString[32];
8259be774b5SAlex Smith				snprintf(valueString, 32, "%" B_PRId32,
8269be774b5SAlex Smith					ValueFor(fCurrentChannel));
82701ef8111SAdrien Destugues				SetToolTip(valueString);
82801ef8111SAdrien Destugues				ShowToolTip(ToolTip());
82901ef8111SAdrien Destugues			} else {
83001ef8111SAdrien Destugues				HideToolTip();
8315fa4ff6aSKarsten Heimrich			}
832e6753e37SKarsten Heimrich
8335fa4ff6aSKarsten Heimrich			fBackingView->Sync();
8345fa4ff6aSKarsten Heimrich			fBacking->Unlock();
835bc3465f9SStefano Ceccherini		}
836e6753e37SKarsten Heimrich
8375fa4ff6aSKarsten Heimrich		DrawBitmapAsync(fBacking, drawHere);
838bc3465f9SStefano Ceccherini
839a20769b3SAdrien Destugues		// fClickDelta is used in MouseMoved()
840a20769b3SAdrien Destugues		fClickDelta = drawHere;
841a20769b3SAdrien Destugues	}
842625c061aSAxel Dörfler}
843625c061aSAxel Dörfler
844625c061aSAxel Dörfler
8451c3a6ab0SStefano Ceccherinivoid
846d89b690dSStephan AßmusBChannelSlider::_DrawGrooveFrame(BView* into, const BRect& area)
847625c061aSAxel Dörfler{
8485fa4ff6aSKarsten Heimrich	if (into) {
8495fa4ff6aSKarsten Heimrich		rgb_color oldColor = into->HighColor();
8505fa4ff6aSKarsten Heimrich
8515fa4ff6aSKarsten Heimrich		into->SetHighColor(255, 255, 255);
8525fa4ff6aSKarsten Heimrich		into->StrokeRect(area);
8535fa4ff6aSKarsten Heimrich		into->SetHighColor(tint_color(into->ViewColor(), B_DARKEN_1_TINT));
8545fa4ff6aSKarsten Heimrich		into->StrokeLine(area.LeftTop(), BPoint(area.right, area.top));
8555fa4ff6aSKarsten Heimrich		into->StrokeLine(area.LeftTop(), BPoint(area.left, area.bottom - 1));
8565fa4ff6aSKarsten Heimrich		into->SetHighColor(tint_color(into->ViewColor(), B_DARKEN_2_TINT));
8575fa4ff6aSKarsten Heimrich		into->StrokeLine(BPoint(area.left + 1, area.top + 1),
8585fa4ff6aSKarsten Heimrich			BPoint(area.right - 1, area.top + 1));
8595fa4ff6aSKarsten Heimrich		into->StrokeLine(BPoint(area.left + 1, area.top + 1),
8605fa4ff6aSKarsten Heimrich			BPoint(area.left + 1, area.bottom - 2));
861