bool FrameworkElementViewManager::UpdateProperty()

in vnext/Microsoft.ReactNative/Views/FrameworkElementViewManager.cpp [121:455]


bool FrameworkElementViewManager::UpdateProperty(
    ShadowNodeBase *nodeToUpdate,
    const std::string &propertyName,
    const winrt::Microsoft::ReactNative::JSValue &propertyValue) {
  auto element(nodeToUpdate->GetView().as<xaml::FrameworkElement>());
  if (element != nullptr) {
    if (propertyName == "opacity") {
      if (propertyValue.Type() == winrt::Microsoft::ReactNative::JSValueType::Double ||
          propertyValue.Type() == winrt::Microsoft::ReactNative::JSValueType::Int64) {
        double opacity = propertyValue.AsDouble();
        if (opacity >= 0 && opacity <= 1)
          element.Opacity(opacity);
        // else
        // TODO report error
      } else if (propertyValue.IsNull()) {
        element.ClearValue(xaml::UIElement::OpacityProperty());
      }
    } else if (propertyName == "transform") {
      if (element.try_as<xaml::IUIElement10>()) // Works on 19H1+
      {
        if (propertyValue.Type() == winrt::Microsoft::ReactNative::JSValueType::Array) {
          assert(propertyValue.AsArray().size() == 16);
          winrt::Windows::Foundation::Numerics::float4x4 transformMatrix;
          transformMatrix.m11 = static_cast<float>(propertyValue[0].AsDouble());
          transformMatrix.m12 = static_cast<float>(propertyValue[1].AsDouble());
          transformMatrix.m13 = static_cast<float>(propertyValue[2].AsDouble());
          transformMatrix.m14 = static_cast<float>(propertyValue[3].AsDouble());
          transformMatrix.m21 = static_cast<float>(propertyValue[4].AsDouble());
          transformMatrix.m22 = static_cast<float>(propertyValue[5].AsDouble());
          transformMatrix.m23 = static_cast<float>(propertyValue[6].AsDouble());
          transformMatrix.m24 = static_cast<float>(propertyValue[7].AsDouble());
          transformMatrix.m31 = static_cast<float>(propertyValue[8].AsDouble());
          transformMatrix.m32 = static_cast<float>(propertyValue[9].AsDouble());
          transformMatrix.m33 = static_cast<float>(propertyValue[10].AsDouble());
          transformMatrix.m34 = static_cast<float>(propertyValue[11].AsDouble());
          transformMatrix.m41 = static_cast<float>(propertyValue[12].AsDouble());
          transformMatrix.m42 = static_cast<float>(propertyValue[13].AsDouble());
          transformMatrix.m43 = static_cast<float>(propertyValue[14].AsDouble());
          transformMatrix.m44 = static_cast<float>(propertyValue[15].AsDouble());

          if (!element.IsLoaded()) {
            element.Loaded([=](auto sender, auto &&) -> auto {
              ApplyTransformMatrix(sender.as<xaml::UIElement>(), nodeToUpdate, transformMatrix);
            });
          } else {
            ApplyTransformMatrix(element, nodeToUpdate, transformMatrix);
          }
        } else if (propertyValue.IsNull()) {
          element.TransformMatrix(winrt::Windows::Foundation::Numerics::float4x4::identity());
        }
      } else {
        cdebug << "[Dim down] " << propertyName << "\n";
      }
    } else if (propertyName == "accessibilityHint") {
      if (propertyValue.Type() == winrt::Microsoft::ReactNative::JSValueType::String) {
        auto value = asHstring(propertyValue);
        auto boxedValue = winrt::Windows::Foundation::PropertyValue::CreateString(value);

        element.SetValue(xaml::Automation::AutomationProperties::HelpTextProperty(), boxedValue);
      } else if (propertyValue.IsNull()) {
        element.ClearValue(xaml::Automation::AutomationProperties::HelpTextProperty());
      }
    } else if (propertyName == "accessibilityLabel") {
      if (propertyValue.Type() == winrt::Microsoft::ReactNative::JSValueType::String) {
        auto value = asHstring(propertyValue);
        auto boxedValue = winrt::Windows::Foundation::PropertyValue::CreateString(value);

        element.SetValue(xaml::Automation::AutomationProperties::NameProperty(), boxedValue);
      } else if (propertyValue.IsNull()) {
        element.ClearValue(xaml::Automation::AutomationProperties::NameProperty());
      }
      AnnounceLiveRegionChangedIfNeeded(element);
    } else if (propertyName == "accessible") {
      if (propertyValue.Type() == winrt::Microsoft::ReactNative::JSValueType::Boolean) {
        if (propertyValue.AsBoolean()) {
          xaml::Automation::AutomationProperties::SetAccessibilityView(element, winrt::AccessibilityView::Content);
        } else {
          xaml::Automation::AutomationProperties::SetAccessibilityView(element, winrt::AccessibilityView::Raw);
        }
      } else if (propertyValue.IsNull()) {
        element.ClearValue(xaml::Automation::AutomationProperties::AccessibilityViewProperty());
      }
    } else if (propertyName == "accessibilityLiveRegion") {
      if (propertyValue.Type() == winrt::Microsoft::ReactNative::JSValueType::String) {
        auto value = propertyValue.AsString();

        auto liveSetting = winrt::AutomationLiveSetting::Off;

        if (value == "polite") {
          liveSetting = winrt::AutomationLiveSetting::Polite;
        } else if (value == "assertive") {
          liveSetting = winrt::AutomationLiveSetting::Assertive;
        }

        element.SetValue(xaml::Automation::AutomationProperties::LiveSettingProperty(), winrt::box_value(liveSetting));
      } else if (propertyValue.IsNull()) {
        element.ClearValue(xaml::Automation::AutomationProperties::LiveSettingProperty());
      }
      AnnounceLiveRegionChangedIfNeeded(element);
    } else if (propertyName == "accessibilityPosInSet") {
      if (propertyValue.Type() == winrt::Microsoft::ReactNative::JSValueType::Double ||
          propertyValue.Type() == winrt::Microsoft::ReactNative::JSValueType::Int64) {
        auto value = static_cast<int>(propertyValue.AsDouble());
        auto boxedValue = winrt::Windows::Foundation::PropertyValue::CreateInt32(value);

        element.SetValue(xaml::Automation::AutomationProperties::PositionInSetProperty(), boxedValue);
      } else if (propertyValue.IsNull()) {
        element.ClearValue(xaml::Automation::AutomationProperties::PositionInSetProperty());
      }
    } else if (propertyName == "accessibilitySetSize") {
      if (propertyValue.Type() == winrt::Microsoft::ReactNative::JSValueType::Double ||
          propertyValue.Type() == winrt::Microsoft::ReactNative::JSValueType::Int64) {
        auto value = static_cast<int>(propertyValue.AsDouble());
        auto boxedValue = winrt::Windows::Foundation::PropertyValue::CreateInt32(value);

        element.SetValue(xaml::Automation::AutomationProperties::SizeOfSetProperty(), boxedValue);
      } else if (propertyValue.IsNull()) {
        element.ClearValue(xaml::Automation::AutomationProperties::SizeOfSetProperty());
      }
    } else if (propertyName == "accessibilityRole") {
      if (propertyValue.Type() == winrt::Microsoft::ReactNative::JSValueType::String) {
        const std::string &role = propertyValue.AsString();
        if (role == "none")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::None);
        else if (role == "button")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::Button);
        else if (role == "link")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::Link);
        else if (role == "search")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::Search);
        else if (role == "image")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::Image);
        else if (role == "keyboardkey")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::KeyboardKey);
        else if (role == "text")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::Text);
        else if (role == "adjustable")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::Adjustable);
        else if (role == "imagebutton")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::ImageButton);
        else if (role == "header")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::Header);
        else if (role == "summary")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::Summary);
        else if (role == "alert")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::Alert);
        else if (role == "checkbox")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::CheckBox);
        else if (role == "combobox")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::ComboBox);
        else if (role == "menu")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::Menu);
        else if (role == "menubar")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::MenuBar);
        else if (role == "menuitem")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::MenuItem);
        else if (role == "progressbar")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::ProgressBar);
        else if (role == "radio")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::Radio);
        else if (role == "radiogroup")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::RadioGroup);
        else if (role == "scrollbar")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::ScrollBar);
        else if (role == "spinbutton")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::SpinButton);
        else if (role == "switch")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::Switch);
        else if (role == "tab")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::Tab);
        else if (role == "tablist")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::TabList);
        else if (role == "timer")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::Timer);
        else if (role == "togglebutton")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::ToggleButton);
        else if (role == "toolbar")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::ToolBar);
        else if (role == "list")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::List);
        else if (role == "listitem")
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::ListItem);
        else
          DynamicAutomationProperties::SetAccessibilityRole(
              element, winrt::Microsoft::ReactNative::AccessibilityRoles::Unknown);
      } else if (propertyValue.IsNull()) {
        element.ClearValue(DynamicAutomationProperties::AccessibilityRoleProperty());
      }
    } else if (propertyName == "accessibilityState") {
      bool states[static_cast<int32_t>(winrt::Microsoft::ReactNative::AccessibilityStates::CountStates)] = {};

      if (propertyValue.Type() == winrt::Microsoft::ReactNative::JSValueType::Object) {
        for (const auto &pair : propertyValue.AsObject()) {
          const std::string &innerName = pair.first;
          const auto &innerValue = pair.second;

          if (innerName == "selected")
            states[static_cast<int32_t>(winrt::Microsoft::ReactNative::AccessibilityStates::Selected)] =
                innerValue.AsBoolean();
          else if (innerName == "disabled")
            states[static_cast<int32_t>(winrt::Microsoft::ReactNative::AccessibilityStates::Disabled)] =
                innerValue.AsBoolean();
          else if (innerName == "checked") {
            states[static_cast<int32_t>(winrt::Microsoft::ReactNative::AccessibilityStates::Checked)] =
                innerValue.Type() == winrt::Microsoft::ReactNative::JSValueType::Boolean && innerValue.AsBoolean();
            states[static_cast<int32_t>(winrt::Microsoft::ReactNative::AccessibilityStates::Unchecked)] =
                innerValue.Type() == winrt::Microsoft::ReactNative::JSValueType::Boolean && !innerValue.AsBoolean();
            // If the state is "mixed" we'll just set both Checked and Unchecked to false,
            // then later in the IToggleProvider implementation it will return the Intermediate state
            // due to both being set to false (see  DynamicAutomationPeer::ToggleState()).
          } else if (innerName == "busy")
            states[static_cast<int32_t>(winrt::Microsoft::ReactNative::AccessibilityStates::Busy)] =
                !innerValue.IsNull() && innerValue.AsBoolean();
          else if (innerName == "expanded") {
            states[static_cast<int32_t>(winrt::Microsoft::ReactNative::AccessibilityStates::Expanded)] =
                !innerValue.IsNull() && innerValue.AsBoolean();
            states[static_cast<int32_t>(winrt::Microsoft::ReactNative::AccessibilityStates::Collapsed)] =
                innerValue.IsNull() || !innerValue.AsBoolean();
          }
        }
      }

      DynamicAutomationProperties::SetAccessibilityStateSelected(
          element, states[static_cast<int32_t>(winrt::Microsoft::ReactNative::AccessibilityStates::Selected)]);
      DynamicAutomationProperties::SetAccessibilityStateDisabled(
          element, states[static_cast<int32_t>(winrt::Microsoft::ReactNative::AccessibilityStates::Disabled)]);
      DynamicAutomationProperties::SetAccessibilityStateChecked(
          element, states[static_cast<int32_t>(winrt::Microsoft::ReactNative::AccessibilityStates::Checked)]);
      DynamicAutomationProperties::SetAccessibilityStateUnchecked(
          element, states[static_cast<int32_t>(winrt::Microsoft::ReactNative::AccessibilityStates::Unchecked)]);
      DynamicAutomationProperties::SetAccessibilityStateBusy(
          element, states[static_cast<int32_t>(winrt::Microsoft::ReactNative::AccessibilityStates::Busy)]);
      DynamicAutomationProperties::SetAccessibilityStateExpanded(
          element, states[static_cast<int32_t>(winrt::Microsoft::ReactNative::AccessibilityStates::Expanded)]);
      DynamicAutomationProperties::SetAccessibilityStateCollapsed(
          element, states[static_cast<int32_t>(winrt::Microsoft::ReactNative::AccessibilityStates::Collapsed)]);
    } else if (propertyName == "accessibilityValue") {
      if (propertyValue.Type() == winrt::Microsoft::ReactNative::JSValueType::Object) {
        for (const auto &pair : propertyValue.AsObject()) {
          const std::string &innerName = pair.first;
          const auto &innerValue = pair.second;

          if (innerName == "min" &&
              (innerValue.Type() == winrt::Microsoft::ReactNative::JSValueType::Double ||
               innerValue.Type() == winrt::Microsoft::ReactNative::JSValueType::Int64)) {
            DynamicAutomationProperties::SetAccessibilityValueMin(element, innerValue.AsDouble());
          } else if (
              innerName == "max" && innerValue.Type() == winrt::Microsoft::ReactNative::JSValueType::Double ||
              innerValue.Type() == winrt::Microsoft::ReactNative::JSValueType::Int64) {
            DynamicAutomationProperties::SetAccessibilityValueMax(element, innerValue.AsDouble());
          } else if (
              innerName == "now" && innerValue.Type() == winrt::Microsoft::ReactNative::JSValueType::Double ||
              innerValue.Type() == winrt::Microsoft::ReactNative::JSValueType::Int64) {
            DynamicAutomationProperties::SetAccessibilityValueNow(element, innerValue.AsDouble());
          } else if (innerName == "text" && innerValue.Type() == winrt::Microsoft::ReactNative::JSValueType::String) {
            auto value = asHstring(innerValue);
            DynamicAutomationProperties::SetAccessibilityValueText(element, value);
          }
        }
      }
    } else if (propertyName == "testID") {
      if (propertyValue.Type() == winrt::Microsoft::ReactNative::JSValueType::String) {
        auto value = asHstring(propertyValue);
        auto boxedValue = winrt::Windows::Foundation::PropertyValue::CreateString(value);

        element.SetValue(xaml::Automation::AutomationProperties::AutomationIdProperty(), boxedValue);
      } else if (propertyValue.IsNull()) {
        element.ClearValue(xaml::Automation::AutomationProperties::AutomationIdProperty());
      }
    } else if (propertyName == "tooltip") {
      if (propertyValue.Type() == winrt::Microsoft::ReactNative::JSValueType::String) {
        winrt::ToolTipService::SetToolTip(element, winrt::box_value(asHstring(propertyValue)));
      }
    } else if (propertyName == "zIndex") {
      if (propertyValue.Type() == winrt::Microsoft::ReactNative::JSValueType::Double ||
          propertyValue.Type() == winrt::Microsoft::ReactNative::JSValueType::Int64) {
        auto value = static_cast<int>(propertyValue.AsDouble());
        auto boxedValue = winrt::Windows::Foundation::PropertyValue::CreateInt32(value);

        element.SetValue(winrt::Canvas::ZIndexProperty(), boxedValue);
      } else if (propertyValue.IsNull()) {
        element.ClearValue(winrt::Canvas::ZIndexProperty());
      }
    } else if (TryUpdateFlowDirection(element, propertyName, propertyValue)) {
    } else if (propertyName == "accessibilityActions") {
      auto value = json_type_traits<winrt::IVector<winrt::Microsoft::ReactNative::AccessibilityAction>>::parseJson(
          propertyValue);
      DynamicAutomationProperties::SetAccessibilityActions(element, value);
    } else if (propertyName == "display") {
      if (propertyValue.Type() == winrt::Microsoft::ReactNative::JSValueType::String) {
        auto value = propertyValue.AsString();
        if (value == "none") {
          element.Visibility(xaml::Visibility::Collapsed);
        } else {
          element.Visibility(xaml::Visibility::Visible);
        }
      } else if (propertyValue.IsNull()) {
        element.ClearValue(xaml::UIElement::VisibilityProperty());
      }
    } else {
      return Super::UpdateProperty(nodeToUpdate, propertyName, propertyValue);
    }
  }
  return true;
}