blob: cfa7cba6c8334b60c619c6d644e4d219421d8abf [file] [log] [blame]
/*
* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
*/
#include "config.h"
#if ENABLE(METER_TAG)
#include "RenderMeter.h"
#include "HTMLMeterElement.h"
#include "HTMLNames.h"
#include "RenderTheme.h"
#include "ShadowElement.h"
using namespace std;
namespace WebCore {
using namespace HTMLNames;
RenderMeter::RenderMeter(HTMLMeterElement* element)
: RenderIndicator(element)
{
}
RenderMeter::~RenderMeter()
{
if (m_valuePart)
m_valuePart->detach();
if (m_barPart)
m_barPart->detach();
}
void RenderMeter::calcWidth()
{
RenderBox::calcWidth();
setWidth(theme()->meterSizeForBounds(this, frameRect()).width());
}
void RenderMeter::calcHeight()
{
RenderBox::calcHeight();
setHeight(theme()->meterSizeForBounds(this, frameRect()).height());
}
void RenderMeter::layoutParts()
{
// We refresh shadow node here because the state can depend
// on the frame size of this render object.
updatePartsState();
if (m_valuePart)
m_valuePart->layoutAsPart(valuePartRect());
if (m_barPart)
m_barPart->layoutAsPart(barPartRect());
}
bool RenderMeter::shouldHaveParts() const
{
bool hasTheme = theme()->supportsMeter(style()->appearance(), isHorizontal());
if (!hasTheme)
return true;
bool shadowsHaveStyle = ShadowBlockElement::partShouldHaveStyle(this, barPseudoId()) || ShadowBlockElement::partShouldHaveStyle(this, valuePseudoId());
if (shadowsHaveStyle)
return true;
return false;
}
double RenderMeter::valueRatio() const
{
HTMLMeterElement* element = static_cast<HTMLMeterElement*>(node());
double min = element->min();
double max = element->max();
double value = element->value();
if (max <= min)
return 0;
return (value - min) / (max - min);
}
IntRect RenderMeter::barPartRect() const
{
return IntRect(borderLeft() + paddingLeft(), borderTop() + paddingTop(), lround(width() - borderLeft() - paddingLeft() - borderRight() - paddingRight()), height() - borderTop() - paddingTop() - borderBottom() - paddingBottom());
}
IntRect RenderMeter::valuePartRect() const
{
IntRect rect = barPartRect();
if (rect.height() <= rect.width()) {
int width = static_cast<int>(rect.width()*valueRatio());
if (style()->direction() == RTL) {
rect.setX(rect.x() + (rect.width() - width));
rect.setWidth(width);
} else
rect.setWidth(width);
} else {
int height = static_cast<int>(rect.height()*valueRatio());
rect.setY(rect.y() + (rect.height() - height));
rect.setHeight(height);
}
return rect;
}
bool RenderMeter::isHorizontal() const
{
IntRect rect = barPartRect();
return rect.height() <= rect.width();
}
PseudoId RenderMeter::valuePseudoId() const
{
HTMLMeterElement* element = static_cast<HTMLMeterElement*>(node());
if (isHorizontal()) {
switch (element->gaugeRegion()) {
case HTMLMeterElement::GaugeRegionOptimum:
return METER_HORIZONTAL_OPTIMUM;
case HTMLMeterElement::GaugeRegionSuboptimal:
return METER_HORIZONTAL_SUBOPTIMAL;
case HTMLMeterElement::GaugeRegionEvenLessGood:
return METER_HORIZONTAL_EVEN_LESS_GOOD;
}
} else {
switch (element->gaugeRegion()) {
case HTMLMeterElement::GaugeRegionOptimum:
return METER_VERTICAL_OPTIMUM;
case HTMLMeterElement::GaugeRegionSuboptimal:
return METER_VERTICAL_SUBOPTIMAL;
case HTMLMeterElement::GaugeRegionEvenLessGood:
return METER_VERTICAL_EVEN_LESS_GOOD;
}
}
ASSERT_NOT_REACHED();
return NOPSEUDO;
}
PseudoId RenderMeter::barPseudoId() const
{
return isHorizontal() ? METER_HORIZONTAL_BAR : METER_VERTICAL_BAR;
}
void RenderMeter::updatePartsState()
{
if (shouldHaveParts() && !m_barPart) {
ASSERT(!m_valuePart);
m_barPart = ShadowBlockElement::createForPart(this->node(), barPseudoId());
addChild(m_barPart->renderer());
m_valuePart = ShadowBlockElement::createForPart(this->node(), valuePseudoId());
addChild(m_valuePart->renderer());
} else if (!shouldHaveParts() && m_barPart) {
ASSERT(m_valuePart);
m_barPart->detach();
m_barPart = 0;
m_valuePart->detach();
m_valuePart = 0;
}
if (m_barPart) {
ASSERT(m_valuePart);
m_barPart->updateStyleForPart(barPseudoId());
m_valuePart->updateStyleForPart(valuePseudoId());
}
}
} // namespace WebCore
#endif