root/src/apps/mediaplayer/interface/SeekSlider.cpp
/*
 * 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();
}