diff -r 000000000000 -r 4f2f89ce4247 WebCore/rendering/RenderMeter.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebCore/rendering/RenderMeter.cpp Fri Sep 17 09:02:29 2010 +0300 @@ -0,0 +1,186 @@ +/* + * 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(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(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(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(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