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/. */
7 #include "nsColorControlFrame.h"
9 #include "nsContentCreatorFunctions.h"
10 #include "nsContentUtils.h"
11 #include "nsCSSPseudoElements.h"
12 #include "nsGkAtoms.h"
13 #include "nsIFormControl.h"
14 #include "mozilla/PresShell.h"
15 #include "mozilla/dom/HTMLInputElement.h"
16 #include "mozilla/dom/Document.h"
18 using namespace mozilla
;
19 using mozilla::dom::CallerType
;
20 using mozilla::dom::Document
;
21 using mozilla::dom::Element
;
22 using mozilla::dom::HTMLInputElement
;
24 nsColorControlFrame::nsColorControlFrame(ComputedStyle
* aStyle
,
25 nsPresContext
* aPresContext
)
26 : nsHTMLButtonControlFrame(aStyle
, aPresContext
, kClassID
) {}
28 nsIFrame
* NS_NewColorControlFrame(PresShell
* aPresShell
,
29 ComputedStyle
* aStyle
) {
30 return new (aPresShell
)
31 nsColorControlFrame(aStyle
, aPresShell
->GetPresContext());
34 NS_IMPL_FRAMEARENA_HELPERS(nsColorControlFrame
)
36 NS_QUERYFRAME_HEAD(nsColorControlFrame
)
37 NS_QUERYFRAME_ENTRY(nsColorControlFrame
)
38 NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator
)
39 NS_QUERYFRAME_TAIL_INHERITING(nsHTMLButtonControlFrame
)
41 void nsColorControlFrame::Destroy(DestroyContext
& aContext
) {
42 aContext
.AddAnonymousContent(mColorContent
.forget());
43 nsHTMLButtonControlFrame::Destroy(aContext
);
46 #ifdef DEBUG_FRAME_DUMP
47 nsresult
nsColorControlFrame::GetFrameName(nsAString
& aResult
) const {
48 return MakeFrameName(u
"ColorControl"_ns
, aResult
);
52 // Create the color area for the button.
53 // The frame will be generated by the frame constructor.
54 nsresult
nsColorControlFrame::CreateAnonymousContent(
55 nsTArray
<ContentInfo
>& aElements
) {
56 RefPtr
<Document
> doc
= mContent
->GetComposedDoc();
57 mColorContent
= doc
->CreateHTMLElement(nsGkAtoms::div
);
58 mColorContent
->SetPseudoElementType(PseudoStyleType::mozColorSwatch
);
60 // Mark the element to be native anonymous before setting any attributes.
61 mColorContent
->SetIsNativeAnonymousRoot();
63 nsresult rv
= UpdateColor();
64 NS_ENSURE_SUCCESS(rv
, rv
);
66 // XXX(Bug 1631371) Check if this should use a fallible operation as it
68 aElements
.AppendElement(mColorContent
);
73 void nsColorControlFrame::AppendAnonymousContentTo(
74 nsTArray
<nsIContent
*>& aElements
, uint32_t aFilter
) {
76 aElements
.AppendElement(mColorContent
);
80 nsresult
nsColorControlFrame::UpdateColor() {
81 // Get the color from the "value" property of our content; it will return the
82 // default color (through the sanitization algorithm) if the value is empty.
84 HTMLInputElement
* elt
= HTMLInputElement::FromNode(mContent
);
85 elt
->GetValue(color
, CallerType::System
);
87 if (color
.IsEmpty()) {
88 // OK, there is one case the color string might be empty -- if our content
89 // is still being created, i.e. if it has mDoneCreating==false. In that
90 // case, we simply do nothing, because we'll be called again with a complete
91 // content node before we ever reflow or paint. Specifically: we can expect
92 // that HTMLInputElement::DoneCreatingElement() will set mDoneCreating to
93 // true (which enables sanitization) and then it'll call SetValueInternal(),
94 // which produces a nonempty color (via sanitization), and then it'll call
95 // this function here, and we'll get the nonempty default color.
96 MOZ_ASSERT(HasAnyStateBits(NS_FRAME_FIRST_REFLOW
),
97 "Content node's GetValue() should return a valid color string "
98 "by the time we've been reflowed (the default color, in case "
99 "no valid color is set)");
103 // Set the background-color CSS property of the swatch element to this color.
104 return mColorContent
->SetAttr(kNameSpaceID_None
, nsGkAtoms::style
,
105 u
"background-color:"_ns
+ color
,
109 nsresult
nsColorControlFrame::AttributeChanged(int32_t aNameSpaceID
,
112 NS_ASSERTION(mColorContent
, "The color div must exist");
114 // If the value attribute is set, update the color box, but only if we're
115 // still a color control, which might not be the case if the type attribute
116 // was removed/changed.
117 nsCOMPtr
<nsIFormControl
> fctrl
= do_QueryInterface(GetContent());
118 if (fctrl
->ControlType() == FormControlType::InputColor
&&
119 aNameSpaceID
== kNameSpaceID_None
&& nsGkAtoms::value
== aAttribute
) {
122 return nsHTMLButtonControlFrame::AttributeChanged(aNameSpaceID
, aAttribute
,
126 nsContainerFrame
* nsColorControlFrame::GetContentInsertionFrame() {