DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Header

Mercurial (c68fe15a81fc)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "nsColorControlFrame.h"

#include "nsContentCreatorFunctions.h"
#include "nsContentUtils.h"
#include "nsCSSPseudoElements.h"
#include "nsCheckboxRadioFrame.h"
#include "nsGkAtoms.h"
#include "nsIFormControl.h"
#include "mozilla/PresShell.h"
#include "mozilla/dom/HTMLInputElement.h"
#include "mozilla/dom/Document.h"

using namespace mozilla;
using mozilla::dom::CallerType;
using mozilla::dom::Document;
using mozilla::dom::Element;
using mozilla::dom::HTMLInputElement;

nsColorControlFrame::nsColorControlFrame(ComputedStyle* aStyle,
                                         nsPresContext* aPresContext)
    : nsHTMLButtonControlFrame(aStyle, aPresContext, kClassID) {}

nsIFrame* NS_NewColorControlFrame(PresShell* aPresShell,
                                  ComputedStyle* aStyle) {
  return new (aPresShell)
      nsColorControlFrame(aStyle, aPresShell->GetPresContext());
}

NS_IMPL_FRAMEARENA_HELPERS(nsColorControlFrame)

NS_QUERYFRAME_HEAD(nsColorControlFrame)
  NS_QUERYFRAME_ENTRY(nsColorControlFrame)
  NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
NS_QUERYFRAME_TAIL_INHERITING(nsHTMLButtonControlFrame)

void nsColorControlFrame::DestroyFrom(nsIFrame* aDestructRoot,
                                      PostDestroyData& aPostDestroyData) {
  nsCheckboxRadioFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), false);
  aPostDestroyData.AddAnonymousContent(mColorContent.forget());
  nsHTMLButtonControlFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
}

#ifdef DEBUG_FRAME_DUMP
nsresult nsColorControlFrame::GetFrameName(nsAString& aResult) const {
  return MakeFrameName(NS_LITERAL_STRING("ColorControl"), aResult);
}
#endif

// Create the color area for the button.
// The frame will be generated by the frame constructor.
nsresult nsColorControlFrame::CreateAnonymousContent(
    nsTArray<ContentInfo>& aElements) {
  RefPtr<Document> doc = mContent->GetComposedDoc();
  mColorContent = doc->CreateHTMLElement(nsGkAtoms::div);
  mColorContent->SetPseudoElementType(PseudoStyleType::mozColorSwatch);

  // Mark the element to be native anonymous before setting any attributes.
  mColorContent->SetIsNativeAnonymousRoot();

  nsresult rv = UpdateColor();
  NS_ENSURE_SUCCESS(rv, rv);

  // XXX(Bug 1631371) Check if this should use a fallible operation as it
  // pretended earlier.
  aElements.AppendElement(mColorContent);

  return NS_OK;
}

void nsColorControlFrame::AppendAnonymousContentTo(
    nsTArray<nsIContent*>& aElements, uint32_t aFilter) {
  if (mColorContent) {
    aElements.AppendElement(mColorContent);
  }
}

nsresult nsColorControlFrame::UpdateColor() {
  // Get the color from the "value" property of our content; it will return the
  // default color (through the sanitization algorithm) if the value is empty.
  nsAutoString color;
  HTMLInputElement* elt = HTMLInputElement::FromNode(mContent);
  elt->GetValue(color, CallerType::System);

  if (color.IsEmpty()) {
    // OK, there is one case the color string might be empty -- if our content
    // is still being created, i.e. if it has mDoneCreating==false.  In that
    // case, we simply do nothing, because we'll be called again with a complete
    // content node before we ever reflow or paint. Specifically: we can expect
    // that HTMLInputElement::DoneCreatingElement() will set mDoneCreating to
    // true (which enables sanitization) and then it'll call SetValueInternal(),
    // which produces a nonempty color (via sanitization), and then it'll call
    // this function here, and we'll get the nonempty default color.
    MOZ_ASSERT(HasAnyStateBits(NS_FRAME_FIRST_REFLOW),
               "Content node's GetValue() should return a valid color string "
               "by the time we've been reflowed (the default color, in case "
               "no valid color is set)");
    return NS_OK;
  }

  // Set the background-color CSS property of the swatch element to this color.
  return mColorContent->SetAttr(kNameSpaceID_None, nsGkAtoms::style,
                                NS_LITERAL_STRING("background-color:") + color,
                                /* aNotify */ true);
}

nsresult nsColorControlFrame::AttributeChanged(int32_t aNameSpaceID,
                                               nsAtom* aAttribute,
                                               int32_t aModType) {
  NS_ASSERTION(mColorContent, "The color div must exist");

  // If the value attribute is set, update the color box, but only if we're
  // still a color control, which might not be the case if the type attribute
  // was removed/changed.
  nsCOMPtr<nsIFormControl> fctrl = do_QueryInterface(GetContent());
  if (fctrl->ControlType() == NS_FORM_INPUT_COLOR &&
      aNameSpaceID == kNameSpaceID_None && nsGkAtoms::value == aAttribute) {
    UpdateColor();
  }
  return nsHTMLButtonControlFrame::AttributeChanged(aNameSpaceID, aAttribute,
                                                    aModType);
}

nsContainerFrame* nsColorControlFrame::GetContentInsertionFrame() {
  return this;
}