⛏️ index : haiku.git

/*
 * Copyright 2006-2010 Stephan Aßmus <superstippi@gmx.de>
 * All rights reserved. Distributed under the terms of the MIT License.
 */


#include "SeekSlider.h"

#include <stdio.h>
#include <string.h>

#include <ControlLook.h>
#include <Region.h>
#include <Shape.h>


static const rgb_color kThumbRed = (rgb_color){ 255, 52, 52, 255 };


SeekSlider::SeekSlider(const char* name, BMessage* message, BMessage* hoverMessage,
		int32 minValue, int32 maxValue)
	:
	BSlider(name, NULL, NULL, minValue, maxValue, B_HORIZONTAL,
		B_TRIANGLE_THUMB),
	fHoverMessage(hoverMessage),
	fTracking(false),
	fLastTrackTime(0),
	fDisabledString(""),
	fScale(0.0f)
{
	BFont font(be_plain_font);
	font.SetSize(font.Size() * 0.75f);
	SetFont(&font);
	SetSymbolScale(1.0);
	rgb_color fillColor = tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
		B_DARKEN_3_TINT);
	UseFillColor(true, &fillColor);
	SetModificationMessage(message);
}


SeekSlider::~SeekSlider()
{
}


status_t
SeekSlider::Invoke(BMessage* message)
{
	fLastTrackTime = system_time();
	return BSlider::Invoke(message);
}


BRect
SeekSlider::ThumbFrame() const
{
	BRect frame = BSlider::ThumbFrame();

	float center = (frame.left + frame.right) / 2.0f;
	float height = ceilf(frame.Height() * fScale);
	float width = ceilf(frame.Width() * fScale);

	frame.left = floorf(center - width / 2) + 1;
	frame.right = frame.left + width;
	frame.bottom = frame.top + height;

	return frame;
}


void
SeekSlider::DrawBar()
{
	BSlider::DrawBar();
	if (IsEnabled())
		return;

	BRect r(BarFrame());
	font_height fh;
	GetFontHeight(&fh);
	float width = ceilf(StringWidth(fDisabledString.String()));
	BPoint textPos;
	textPos.x = r.left + (r.Width() - width) / 2.0;
	textPos.y = (r.top + r.bottom - ceilf(fh.ascent + fh.descent)) / 2.0
		+ ceilf(fh.ascent);

	SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR),
		B_DARKEN_3_TINT));
	SetDrawingMode(B_OP_OVER);
	DrawString(fDisabledString.String(), textPos);
}


void
SeekSlider::DrawThumb()
{
	if (!IsEnabled())
		return;

	BRect frame = ThumbFrame();
	be_control_look->DrawSliderTriangle(this, frame, frame, kThumbRed, 0,
		B_HORIZONTAL);
}


void
SeekSlider::MouseDown(BPoint where)
{
	if (IsEnabled())
		fTracking = true;
	BSlider::MouseDown(where);
}


void
SeekSlider::MouseUp(BPoint where)
{
	fTracking = false;
	BSlider::MouseUp(where);
}


void
SeekSlider::MouseMoved(BPoint point, uint32 transit, const BMessage* dragMessage)
{
	if (fHoverMessage != NULL) {
		fHoverMessage->SetInt32("value", ValueForPoint(point));
		BControl::Invoke(fHoverMessage);
	}
	BSlider::MouseMoved(point, transit, dragMessage);
}


void
SeekSlider::GetPreferredSize(float* _width, float* _height)
{
	BSlider::GetPreferredSize(_width, _height);
	if (_width != NULL) {
		float minWidth = 15.0 + StringWidth(fDisabledString.String()) + 15.0;
		*_width = max_c(*_width, minWidth);
	}
	if (_height != NULL) {
		BRect unscaledThumbFrame = BSlider::ThumbFrame();
		BRect scaledThumbFrame = ThumbFrame();
		*_height += scaledThumbFrame.Height() - unscaledThumbFrame.Height();
	}
}


BSize
SeekSlider::MinSize()
{
	BSize size = BSlider::MinSize();

	BRect unscaledThumbFrame = BSlider::ThumbFrame();
	BRect scaledThumbFrame = ThumbFrame();
	size.height += scaledThumbFrame.Height() - unscaledThumbFrame.Height();

	return size;
}


BSize
SeekSlider::MaxSize()
{
	BSize size = BSlider::MaxSize();

	BRect unscaledThumbFrame = BSlider::ThumbFrame();
	BRect scaledThumbFrame = ThumbFrame();
	size.height += scaledThumbFrame.Height() - unscaledThumbFrame.Height();

	return size;
}


bool
SeekSlider::IsTracking() const
{
	if (fTracking)
		return true;
	return system_time() - fLastTrackTime < 250000;
}


void
SeekSlider::SetDisabledString(const char* string)
{
	if (string == NULL)
		string = "";

	if (fDisabledString == string)
		return;

	fDisabledString = string;

	if (!IsEnabled())
		Invalidate();
}


void
SeekSlider::SetSymbolScale(float scale)
{
	if (scale == fScale)
		return;

	fScale = scale;
	SetBarThickness(fScale * 15.0);
	InvalidateLayout();
}