From cad810f21b803229eb11403f9209855525a25d57 Mon Sep 17 00:00:00 2001 From: Steve Block Date: Fri, 6 May 2011 11:45:16 +0100 Subject: Merge WebKit at r75315: Initial merge by git. Change-Id: I570314b346ce101c935ed22a626b48c2af266b84 --- Source/WebCore/rendering/RenderMeter.cpp | 261 +++++++++++++++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100644 Source/WebCore/rendering/RenderMeter.cpp (limited to 'Source/WebCore/rendering/RenderMeter.cpp') diff --git a/Source/WebCore/rendering/RenderMeter.cpp b/Source/WebCore/rendering/RenderMeter.cpp new file mode 100644 index 0000000..6439651 --- /dev/null +++ b/Source/WebCore/rendering/RenderMeter.cpp @@ -0,0 +1,261 @@ +/* + * 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; + +class MeterPartElement : public ShadowBlockElement { +public: + static PassRefPtr createForPart(HTMLElement*, PseudoId); + + void hide(); + void restoreVisibility(); + + virtual void updateStyleForPart(PseudoId); + +private: + MeterPartElement(HTMLElement*); + void saveVisibility(); + + EVisibility m_originalVisibility; +}; + +MeterPartElement::MeterPartElement(HTMLElement* shadowParent) + : ShadowBlockElement(shadowParent) +{ +} + +PassRefPtr MeterPartElement::createForPart(HTMLElement* shadowParent, PseudoId pseudoId) +{ + RefPtr ret = adoptRef(new MeterPartElement(shadowParent)); + ret->initAsPart(pseudoId); + ret->saveVisibility(); + return ret; +} + +void MeterPartElement::hide() +{ + if (renderer()) + renderer()->style()->setVisibility(HIDDEN); +} + +void MeterPartElement::restoreVisibility() +{ + if (renderer()) + renderer()->style()->setVisibility(m_originalVisibility); +} + +void MeterPartElement::updateStyleForPart(PseudoId pseudoId) +{ + if (renderer()->style()->styleType() == pseudoId) + return; + + ShadowBlockElement::updateStyleForPart(pseudoId); + saveVisibility(); +} + +void MeterPartElement::saveVisibility() +{ + m_originalVisibility = renderer()->style()->visibility(); +} + +RenderMeter::RenderMeter(HTMLMeterElement* element) + : RenderIndicator(element) +{ +} + +RenderMeter::~RenderMeter() +{ + if (shadowAttached()) { + m_verticalValuePart->detach(); + m_verticalBarPart->detach(); + m_horizontalValuePart->detach(); + m_horizontalBarPart->detach(); + } +} + +PassRefPtr RenderMeter::createPart(PseudoId pseudoId) +{ + RefPtr element = MeterPartElement::createForPart(static_cast(node()), pseudoId); + if (element->renderer()) + addChild(element->renderer()); + return element; +} + +void RenderMeter::updateFromElement() +{ + if (!shadowAttached()) { + m_horizontalBarPart = createPart(barPseudoId(HORIZONTAL)); + m_horizontalValuePart = createPart(valuePseudoId(HORIZONTAL)); + m_verticalBarPart = createPart(barPseudoId(VERTICAL)); + m_verticalValuePart = createPart(valuePseudoId(VERTICAL)); + } + + m_horizontalBarPart->updateStyleForPart(barPseudoId(HORIZONTAL)); + m_horizontalValuePart->updateStyleForPart(valuePseudoId(HORIZONTAL)); + m_verticalBarPart->updateStyleForPart(barPseudoId(VERTICAL)); + m_verticalValuePart->updateStyleForPart(valuePseudoId(VERTICAL)); + RenderIndicator::updateFromElement(); +} + +void RenderMeter::computeLogicalWidth() +{ + RenderBox::computeLogicalWidth(); + setWidth(theme()->meterSizeForBounds(this, frameRect()).width()); +} + +void RenderMeter::computeLogicalHeight() +{ + RenderBox::computeLogicalHeight(); + setHeight(theme()->meterSizeForBounds(this, frameRect()).height()); +} + +void RenderMeter::layoutParts() +{ + m_horizontalBarPart->layoutAsPart(barPartRect()); + m_horizontalValuePart->layoutAsPart(valuePartRect(HORIZONTAL)); + m_verticalBarPart->layoutAsPart(barPartRect()); + m_verticalValuePart->layoutAsPart(valuePartRect(VERTICAL)); + + if (shouldHaveParts()) { + if (HORIZONTAL == orientation()) { + m_verticalBarPart->hide(); + m_verticalValuePart->hide(); + m_horizontalBarPart->restoreVisibility(); + m_horizontalValuePart->restoreVisibility(); + } else { + m_verticalBarPart->restoreVisibility(); + m_verticalValuePart->restoreVisibility(); + m_horizontalBarPart->hide(); + m_horizontalValuePart->hide(); + } + } else { + m_verticalBarPart->hide(); + m_verticalValuePart->hide(); + m_horizontalBarPart->hide(); + m_horizontalValuePart->hide(); + } +} + +bool RenderMeter::shouldHaveParts() const +{ + EBoxOrient currentOrientation = orientation(); + bool hasTheme = theme()->supportsMeter(style()->appearance(), HORIZONTAL == currentOrientation); + if (!hasTheme) + return true; + bool shadowsHaveStyle = ShadowBlockElement::partShouldHaveStyle(this, barPseudoId(currentOrientation)) || ShadowBlockElement::partShouldHaveStyle(this, valuePseudoId(currentOrientation)); + 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(EBoxOrient asOrientation) const +{ + IntRect rect = barPartRect(); + + if (HORIZONTAL == asOrientation) { + int width = static_cast(rect.width()*valueRatio()); + if (!style()->isLeftToRightDirection()) { + 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; +} + +EBoxOrient RenderMeter::orientation() const +{ + IntRect rect = barPartRect(); + return rect.height() <= rect.width() ? HORIZONTAL : VERTICAL; +} + +PseudoId RenderMeter::valuePseudoId(EBoxOrient asOrientation) const +{ + HTMLMeterElement* element = static_cast(node()); + + if (HORIZONTAL == asOrientation) { + 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(EBoxOrient asOrientation) const +{ + return HORIZONTAL == asOrientation ? METER_HORIZONTAL_BAR : METER_VERTICAL_BAR; +} + +} // namespace WebCore + +#endif -- cgit v1.1