nsColorControlFrame.cpp (4426B)
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 "nsColorControlFrame.h" 8 9 #include "mozilla/PresShell.h" 10 #include "mozilla/dom/Document.h" 11 #include "mozilla/dom/HTMLInputElement.h" 12 #include "nsContentCreatorFunctions.h" 13 #include "nsContentUtils.h" 14 #include "nsGkAtoms.h" 15 #include "nsIFormControl.h" 16 17 using namespace mozilla; 18 using mozilla::dom::CallerType; 19 using mozilla::dom::HTMLInputElement; 20 21 nsColorControlFrame::nsColorControlFrame(ComputedStyle* aStyle, 22 nsPresContext* aPresContext) 23 : ButtonControlFrame(aStyle, aPresContext, kClassID) {} 24 25 nsIFrame* NS_NewColorControlFrame(PresShell* aPresShell, 26 ComputedStyle* aStyle) { 27 return new (aPresShell) 28 nsColorControlFrame(aStyle, aPresShell->GetPresContext()); 29 } 30 31 NS_IMPL_FRAMEARENA_HELPERS(nsColorControlFrame) 32 33 NS_QUERYFRAME_HEAD(nsColorControlFrame) 34 NS_QUERYFRAME_ENTRY(nsColorControlFrame) 35 NS_QUERYFRAME_TAIL_INHERITING(ButtonControlFrame) 36 37 void nsColorControlFrame::Destroy(DestroyContext& aContext) { 38 aContext.AddAnonymousContent(mColorContent.forget()); 39 ButtonControlFrame::Destroy(aContext); 40 } 41 42 // Create the color area for the button. 43 // The frame will be generated by the frame constructor. 44 nsresult nsColorControlFrame::CreateAnonymousContent( 45 nsTArray<ContentInfo>& aElements) { 46 mColorContent = mContent->OwnerDoc()->CreateHTMLElement(nsGkAtoms::div); 47 mColorContent->SetPseudoElementType(PseudoStyleType::mozColorSwatch); 48 // Mark the element to be native anonymous before setting any attributes. 49 mColorContent->SetIsNativeAnonymousRoot(); 50 UpdateColor(); 51 aElements.AppendElement(mColorContent); 52 return NS_OK; 53 } 54 55 void nsColorControlFrame::AppendAnonymousContentTo( 56 nsTArray<nsIContent*>& aElements, uint32_t aFilter) { 57 if (mColorContent) { 58 aElements.AppendElement(mColorContent); 59 } 60 } 61 62 void nsColorControlFrame::UpdateColor() { 63 // Get the color from the "value" property of our content; it will return the 64 // default color (through the sanitization algorithm) if the value is empty. 65 nsAutoString color; 66 auto* elt = HTMLInputElement::FromNode(mContent); 67 elt->GetValue(color, CallerType::System); 68 69 if (color.IsEmpty()) { 70 // OK, there is one case the color string might be empty -- if our content 71 // is still being created, i.e. if it has mDoneCreating==false. In that 72 // case, we simply do nothing, because we'll be called again with a complete 73 // content node before we ever reflow or paint. Specifically: we can expect 74 // that HTMLInputElement::DoneCreatingElement() will set mDoneCreating to 75 // true (which enables sanitization) and then it'll call SetValueInternal(), 76 // which produces a nonempty color (via sanitization), and then it'll call 77 // this function here, and we'll get the nonempty default color. 78 MOZ_ASSERT(HasAnyStateBits(NS_FRAME_FIRST_REFLOW), 79 "Content node's GetValue() should return a valid color string " 80 "by the time we've been reflowed (the default color, in case " 81 "no valid color is set)"); 82 return; 83 } 84 85 // Set the background-color CSS property of the swatch element to this color. 86 mColorContent->SetAttr(kNameSpaceID_None, nsGkAtoms::style, 87 u"background-color:"_ns + color, 88 /* aNotify */ true); 89 } 90 91 nsresult nsColorControlFrame::AttributeChanged(int32_t aNameSpaceID, 92 nsAtom* aAttribute, 93 AttrModType aModType) { 94 NS_ASSERTION(mColorContent, "The color div must exist"); 95 96 // If the value attribute is set, update the color box, but only if we're 97 // still a color control, which might not be the case if the type attribute 98 // was removed/changed. 99 if (nsIFormControl::FromNode(GetContent())->ControlType() == 100 FormControlType::InputColor && 101 aNameSpaceID == kNameSpaceID_None && nsGkAtoms::value == aAttribute) { 102 UpdateColor(); 103 } 104 return ButtonControlFrame::AttributeChanged(aNameSpaceID, aAttribute, 105 aModType); 106 }