tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

HTMLMeterElement.cpp (7917B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "HTMLMeterElement.h"
      8 
      9 #include "mozilla/dom/HTMLMeterElementBinding.h"
     10 
     11 NS_IMPL_NS_NEW_HTML_ELEMENT(Meter)
     12 
     13 namespace mozilla::dom {
     14 
     15 static const double kDefaultValue = 0.0;
     16 static const double kDefaultMin = 0.0;
     17 static const double kDefaultMax = 1.0;
     18 
     19 HTMLMeterElement::HTMLMeterElement(
     20    already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
     21    : nsGenericHTMLElement(std::move(aNodeInfo)) {}
     22 
     23 HTMLMeterElement::~HTMLMeterElement() = default;
     24 
     25 NS_IMPL_ELEMENT_CLONE(HTMLMeterElement)
     26 
     27 static bool IsInterestingAttr(int32_t aNamespaceID, nsAtom* aAttribute) {
     28  if (aNamespaceID != kNameSpaceID_None) {
     29    return false;
     30  }
     31  return aAttribute == nsGkAtoms::value || aAttribute == nsGkAtoms::max ||
     32         aAttribute == nsGkAtoms::min || aAttribute == nsGkAtoms::low ||
     33         aAttribute == nsGkAtoms::high || aAttribute == nsGkAtoms::optimum;
     34 }
     35 
     36 bool HTMLMeterElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
     37                                      const nsAString& aValue,
     38                                      nsIPrincipal* aMaybeScriptedPrincipal,
     39                                      nsAttrValue& aResult) {
     40  if (IsInterestingAttr(aNamespaceID, aAttribute)) {
     41    return aResult.ParseDoubleValue(aValue);
     42  }
     43  return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
     44                                              aMaybeScriptedPrincipal, aResult);
     45 }
     46 
     47 void HTMLMeterElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
     48                                    const nsAttrValue* aValue,
     49                                    const nsAttrValue* aOldValue,
     50                                    nsIPrincipal* aSubjectPrincipal,
     51                                    bool aNotify) {
     52  if (IsInterestingAttr(aNameSpaceID, aName)) {
     53    UpdateOptimumState(aNotify);
     54  }
     55  nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue, aOldValue,
     56                                     aSubjectPrincipal, aNotify);
     57 }
     58 
     59 void HTMLMeterElement::UpdateOptimumState(bool aNotify) {
     60  AutoStateChangeNotifier notifier(*this, aNotify);
     61  RemoveStatesSilently(ElementState::METER_OPTIMUM_STATES);
     62  AddStatesSilently(GetOptimumState());
     63 }
     64 
     65 double HTMLMeterElement::Min() const {
     66  /**
     67   * If the attribute min is defined, the minimum is this value.
     68   * Otherwise, the minimum is the default value.
     69   */
     70  const nsAttrValue* attrMin = mAttrs.GetAttr(nsGkAtoms::min);
     71  if (attrMin && attrMin->Type() == nsAttrValue::eDoubleValue) {
     72    return attrMin->GetDoubleValue();
     73  }
     74  return kDefaultMin;
     75 }
     76 
     77 double HTMLMeterElement::Max() const {
     78  /**
     79   * If the attribute max is defined, the maximum is this value.
     80   * Otherwise, the maximum is the default value.
     81   * If the maximum value is less than the minimum value,
     82   * the maximum value is the same as the minimum value.
     83   */
     84  double max;
     85 
     86  const nsAttrValue* attrMax = mAttrs.GetAttr(nsGkAtoms::max);
     87  if (attrMax && attrMax->Type() == nsAttrValue::eDoubleValue) {
     88    max = attrMax->GetDoubleValue();
     89  } else {
     90    max = kDefaultMax;
     91  }
     92 
     93  return std::max(max, Min());
     94 }
     95 
     96 double HTMLMeterElement::Value() const {
     97  /**
     98   * If the attribute value is defined, the actual value is this value.
     99   * Otherwise, the actual value is the default value.
    100   * If the actual value is less than the minimum value,
    101   * the actual value is the same as the minimum value.
    102   * If the actual value is greater than the maximum value,
    103   * the actual value is the same as the maximum value.
    104   */
    105  double value;
    106 
    107  const nsAttrValue* attrValue = mAttrs.GetAttr(nsGkAtoms::value);
    108  if (attrValue && attrValue->Type() == nsAttrValue::eDoubleValue) {
    109    value = attrValue->GetDoubleValue();
    110  } else {
    111    value = kDefaultValue;
    112  }
    113 
    114  double min = Min();
    115 
    116  if (value <= min) {
    117    return min;
    118  }
    119 
    120  return std::min(value, Max());
    121 }
    122 
    123 double HTMLMeterElement::Position() const {
    124  const double max = Max();
    125  const double min = Min();
    126  const double value = Value();
    127 
    128  double range = max - min;
    129  return range != 0.0 ? (value - min) / range : 1.0;
    130 }
    131 
    132 double HTMLMeterElement::Low() const {
    133  /**
    134   * If the low value is defined, the low value is this value.
    135   * Otherwise, the low value is the minimum value.
    136   * If the low value is less than the minimum value,
    137   * the low value is the same as the minimum value.
    138   * If the low value is greater than the maximum value,
    139   * the low value is the same as the maximum value.
    140   */
    141 
    142  double min = Min();
    143 
    144  const nsAttrValue* attrLow = mAttrs.GetAttr(nsGkAtoms::low);
    145  if (!attrLow || attrLow->Type() != nsAttrValue::eDoubleValue) {
    146    return min;
    147  }
    148 
    149  double low = attrLow->GetDoubleValue();
    150 
    151  if (low <= min) {
    152    return min;
    153  }
    154 
    155  return std::min(low, Max());
    156 }
    157 
    158 double HTMLMeterElement::High() const {
    159  /**
    160   * If the high value is defined, the high value is this value.
    161   * Otherwise, the high value is the maximum value.
    162   * If the high value is less than the low value,
    163   * the high value is the same as the low value.
    164   * If the high value is greater than the maximum value,
    165   * the high value is the same as the maximum value.
    166   */
    167 
    168  double max = Max();
    169 
    170  const nsAttrValue* attrHigh = mAttrs.GetAttr(nsGkAtoms::high);
    171  if (!attrHigh || attrHigh->Type() != nsAttrValue::eDoubleValue) {
    172    return max;
    173  }
    174 
    175  double high = attrHigh->GetDoubleValue();
    176 
    177  if (high >= max) {
    178    return max;
    179  }
    180 
    181  return std::max(high, Low());
    182 }
    183 
    184 double HTMLMeterElement::Optimum() const {
    185  /**
    186   * If the optimum value is defined, the optimum value is this value.
    187   * Otherwise, the optimum value is the midpoint between
    188   * the minimum value and the maximum value :
    189   * min + (max - min)/2 = (min + max)/2
    190   * If the optimum value is less than the minimum value,
    191   * the optimum value is the same as the minimum value.
    192   * If the optimum value is greater than the maximum value,
    193   * the optimum value is the same as the maximum value.
    194   */
    195 
    196  double max = Max();
    197 
    198  double min = Min();
    199 
    200  const nsAttrValue* attrOptimum = mAttrs.GetAttr(nsGkAtoms::optimum);
    201  if (!attrOptimum || attrOptimum->Type() != nsAttrValue::eDoubleValue) {
    202    return (min + max) / 2.0;
    203  }
    204 
    205  double optimum = attrOptimum->GetDoubleValue();
    206 
    207  if (optimum <= min) {
    208    return min;
    209  }
    210 
    211  return std::min(optimum, max);
    212 }
    213 
    214 ElementState HTMLMeterElement::GetOptimumState() const {
    215  /*
    216   * If the optimum value is in [minimum, low[,
    217   *     return if the value is in optimal, suboptimal or sub-suboptimal region
    218   *
    219   * If the optimum value is in [low, high],
    220   *     return if the value is in optimal or suboptimal region
    221   *
    222   * If the optimum value is in ]high, maximum],
    223   *     return if the value is in optimal, suboptimal or sub-suboptimal region
    224   */
    225  double value = Value();
    226  double low = Low();
    227  double high = High();
    228  double optimum = Optimum();
    229 
    230  if (optimum < low) {
    231    if (value < low) {
    232      return ElementState::OPTIMUM;
    233    }
    234    if (value <= high) {
    235      return ElementState::SUB_OPTIMUM;
    236    }
    237    return ElementState::SUB_SUB_OPTIMUM;
    238  }
    239  if (optimum > high) {
    240    if (value > high) {
    241      return ElementState::OPTIMUM;
    242    }
    243    if (value >= low) {
    244      return ElementState::SUB_OPTIMUM;
    245    }
    246    return ElementState::SUB_SUB_OPTIMUM;
    247  }
    248  // optimum in [low, high]
    249  if (value >= low && value <= high) {
    250    return ElementState::OPTIMUM;
    251  }
    252  return ElementState::SUB_OPTIMUM;
    253 }
    254 
    255 JSObject* HTMLMeterElement::WrapNode(JSContext* aCx,
    256                                     JS::Handle<JSObject*> aGivenProto) {
    257  return HTMLMeterElement_Binding::Wrap(aCx, this, aGivenProto);
    258 }
    259 
    260 }  // namespace mozilla::dom