Replace WTF::move with WTFMove
[WebKit-https.git] / Source / WebCore / html / HTMLDetailsElement.cpp
1 /*
2  * Copyright (C) 2010, 2011 Nokia Corporation and/or its subsidiary(-ies)
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  *
19  */
20
21 #include "config.h"
22 #include "HTMLDetailsElement.h"
23
24 #if ENABLE(DETAILS_ELEMENT)
25 #include "AXObjectCache.h"
26 #include "ElementIterator.h"
27 #include "HTMLSlotElement.h"
28 #include "HTMLSummaryElement.h"
29 #include "LocalizedStrings.h"
30 #include "MouseEvent.h"
31 #include "RenderBlockFlow.h"
32 #include "ShadowRoot.h"
33 #include "SlotAssignment.h"
34 #include "Text.h"
35 #include <wtf/NeverDestroyed.h>
36
37 namespace WebCore {
38
39 using namespace HTMLNames;
40
41 static const AtomicString& summarySlotName()
42 {
43     static NeverDestroyed<AtomicString> summarySlot("summarySlot");
44     return summarySlot;
45 }
46
47 static AtomicString slotNameFunction(const Node& child)
48 {
49     auto& parent = *child.parentNode();
50     ASSERT(is<HTMLDetailsElement>(parent));
51     auto& details = downcast<HTMLDetailsElement>(parent);
52
53     // The first summary child gets assigned to the summary slot.
54     if (is<HTMLSummaryElement>(child)) {
55         if (&child == childrenOfType<HTMLSummaryElement>(details).first())
56             return summarySlotName();
57     }
58     // Everything else is assigned to the default slot if details is open.
59     if (details.isOpen())
60         return SlotAssignment::defaultSlotName();
61
62     // Otherwise don't render the content.
63     return nullAtom;
64 };
65
66 Ref<HTMLDetailsElement> HTMLDetailsElement::create(const QualifiedName& tagName, Document& document)
67 {
68     auto details = adoptRef(*new HTMLDetailsElement(tagName, document));
69     details->addShadowRoot(ShadowRoot::create(document, std::make_unique<SlotAssignment>(slotNameFunction)));
70     return details;
71 }
72
73 HTMLDetailsElement::HTMLDetailsElement(const QualifiedName& tagName, Document& document)
74     : HTMLElement(tagName, document)
75 {
76     ASSERT(hasTagName(detailsTag));
77 }
78
79 RenderPtr<RenderElement> HTMLDetailsElement::createElementRenderer(Ref<RenderStyle>&& style, const RenderTreePosition&)
80 {
81     return createRenderer<RenderBlockFlow>(*this, WTFMove(style));
82 }
83
84 void HTMLDetailsElement::didAddUserAgentShadowRoot(ShadowRoot* root)
85 {
86     auto summarySlot = HTMLSlotElement::create(slotTag, document());
87     summarySlot->setAttribute(nameAttr, summarySlotName());
88     m_summarySlot = summarySlot.ptr();
89
90     auto defaultSummary = HTMLSummaryElement::create(summaryTag, document());
91     defaultSummary->appendChild(Text::create(document(), defaultDetailsSummaryText()), ASSERT_NO_EXCEPTION);
92     m_defaultSummary = defaultSummary.ptr();
93
94     summarySlot->appendChild(WTFMove(defaultSummary));
95     root->appendChild(WTFMove(summarySlot));
96
97     auto defaultSlot = HTMLSlotElement::create(slotTag, document());
98     root->appendChild(WTFMove(defaultSlot));
99 }
100
101 bool HTMLDetailsElement::isActiveSummary(const HTMLSummaryElement& summary) const
102 {
103     if (!m_summarySlot->assignedNodes())
104         return &summary == m_defaultSummary;
105
106     auto* slot = shadowRoot()->findAssignedSlot(summary);
107     if (!slot)
108         return false;
109     return slot == m_summarySlot;
110 }
111
112 void HTMLDetailsElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
113 {
114     if (name == openAttr) {
115         bool oldValue = m_isOpen;
116         m_isOpen = !value.isNull();
117         if (oldValue != m_isOpen)
118             shadowRoot()->invalidateSlotAssignments();
119     } else
120         HTMLElement::parseAttribute(name, value);
121 }
122
123
124 void HTMLDetailsElement::toggleOpen()
125 {
126     setAttribute(openAttr, m_isOpen ? nullAtom : emptyAtom);
127
128     // We need to post to the document because toggling this element will delete it.
129     if (AXObjectCache* cache = document().existingAXObjectCache())
130         cache->postNotification(nullptr, &document(), AXObjectCache::AXExpandedChanged);
131 }
132
133 }
134
135 #endif