SliderThumbElement.cpp [plain text]
#include "config.h"
#include "SliderThumbElement.h"
#include "Event.h"
#include "Frame.h"
#include "HTMLInputElement.h"
#include "HTMLParserIdioms.h"
#include "MouseEvent.h"
#include "RenderSlider.h"
#include "RenderTheme.h"
#include "StepRange.h"
#include <wtf/MathExtras.h>
using namespace std;
namespace WebCore {
class RenderSliderThumb : public RenderBlock {
public:
RenderSliderThumb(Node*);
private:
virtual void layout();
};
RenderSliderThumb::RenderSliderThumb(Node* node)
: RenderBlock(node)
{
}
void RenderSliderThumb::layout()
{
RenderStyle* parentStyle = parent()->style();
if (parentStyle->appearance() == SliderVerticalPart)
style()->setAppearance(SliderThumbVerticalPart);
else if (parentStyle->appearance() == SliderHorizontalPart)
style()->setAppearance(SliderThumbHorizontalPart);
else if (parentStyle->appearance() == MediaSliderPart)
style()->setAppearance(MediaSliderThumbPart);
else if (parentStyle->appearance() == MediaVolumeSliderPart)
style()->setAppearance(MediaVolumeSliderThumbPart);
if (style()->hasAppearance()) {
theme()->adjustSliderThumbSize(this);
}
RenderBlock::layout();
}
void SliderThumbElement::setPositionFromValue()
{
if (renderer())
renderer()->setNeedsLayout(true);
}
RenderObject* SliderThumbElement::createRenderer(RenderArena* arena, RenderStyle*)
{
return new (arena) RenderSliderThumb(this);
}
void SliderThumbElement::dragFrom(const IntPoint& point)
{
setPositionFromPoint(point);
startDragging();
}
void SliderThumbElement::setPositionFromPoint(const IntPoint& point)
{
HTMLInputElement* input = hostInput();
ASSERT(input);
if (!input->renderer() || !renderer())
return;
IntPoint offset = roundedIntPoint(input->renderer()->absoluteToLocal(point, false, true));
RenderStyle* sliderStyle = input->renderer()->style();
bool isVertical = sliderStyle->appearance() == SliderVerticalPart || sliderStyle->appearance() == MediaVolumeSliderPart;
int trackSize;
int position;
int currentPosition;
if (isVertical) {
trackSize = input->renderBox()->contentHeight() - renderBox()->height();
position = offset.y() - renderBox()->height() / 2;
currentPosition = renderBox()->y() - input->renderBox()->contentBoxRect().y();
} else {
trackSize = input->renderBox()->contentWidth() - renderBox()->width();
position = offset.x() - renderBox()->width() / 2;
currentPosition = renderBox()->x() - input->renderBox()->contentBoxRect().x();
}
position = max(0, min(position, trackSize));
if (position == currentPosition)
return;
StepRange range(input);
double fraction = static_cast<double>(position) / trackSize;
if (isVertical)
fraction = 1 - fraction;
double value = range.clampValue(range.valueFromProportion(fraction));
input->setValueFromRenderer(serializeForNumberType(value));
renderer()->setNeedsLayout(true);
input->dispatchFormControlChangeEvent();
}
void SliderThumbElement::startDragging()
{
if (Frame* frame = document()->frame()) {
frame->eventHandler()->setCapturingMouseEventsNode(this);
m_inDragMode = true;
}
}
void SliderThumbElement::stopDragging()
{
if (!m_inDragMode)
return;
if (Frame* frame = document()->frame())
frame->eventHandler()->setCapturingMouseEventsNode(0);
m_inDragMode = false;
if (renderer())
renderer()->setNeedsLayout(true);
}
void SliderThumbElement::defaultEventHandler(Event* event)
{
if (!event->isMouseEvent()) {
HTMLDivElement::defaultEventHandler(event);
return;
}
MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
bool isLeftButton = mouseEvent->button() == LeftButton;
const AtomicString& eventType = event->type();
if (eventType == eventNames().mousedownEvent && isLeftButton) {
startDragging();
return;
} else if (eventType == eventNames().mouseupEvent && isLeftButton) {
stopDragging();
return;
} else if (eventType == eventNames().mousemoveEvent) {
if (m_inDragMode)
setPositionFromPoint(mouseEvent->absoluteLocation());
return;
}
HTMLDivElement::defaultEventHandler(event);
}
void SliderThumbElement::detach()
{
if (m_inDragMode) {
if (Frame* frame = document()->frame())
frame->eventHandler()->setCapturingMouseEventsNode(0);
}
HTMLDivElement::detach();
}
HTMLInputElement* SliderThumbElement::hostInput()
{
ASSERT(parentNode());
return static_cast<HTMLInputElement*>(parentNode()->shadowHost());
}
const AtomicString& SliderThumbElement::shadowPseudoId() const
{
DEFINE_STATIC_LOCAL(AtomicString, sliderThumb, ("-webkit-slider-thumb"));
return sliderThumb;
}
}