Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(395)

Side by Side Diff: Source/core/layout/LayoutMenuList.cpp

Issue 1152623003: Revert of [Reland] Setup LayoutMenuList to not modify layout tree outside style recalc. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Add rebaseline Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/layout/LayoutMenuList.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * This file is part of the select element layoutObject in WebCore. 2 * This file is part of the select element layoutObject in WebCore.
3 * 3 *
4 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
5 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserv ed. 5 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserv ed.
6 * 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo bile.com/) 6 * 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo bile.com/)
7 * 7 *
8 * This library is free software; you can redistribute it and/or 8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public 9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either 10 * License as published by the Free Software Foundation; either
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 49
50 namespace blink { 50 namespace blink {
51 51
52 using namespace HTMLNames; 52 using namespace HTMLNames;
53 53
54 LayoutMenuList::LayoutMenuList(Element* element) 54 LayoutMenuList::LayoutMenuList(Element* element)
55 : LayoutFlexibleBox(element) 55 : LayoutFlexibleBox(element)
56 , m_buttonText(nullptr) 56 , m_buttonText(nullptr)
57 , m_innerBlock(nullptr) 57 , m_innerBlock(nullptr)
58 , m_optionsChanged(true) 58 , m_optionsChanged(true)
59 , m_isEmpty(false)
60 , m_hasUpdatedActiveOption(false)
61 , m_popupIsVisible(false)
62 , m_optionsWidth(0) 59 , m_optionsWidth(0)
63 , m_lastActiveIndex(-1) 60 , m_lastActiveIndex(-1)
61 , m_popupIsVisible(false)
64 , m_indexToSelectOnCancel(-1) 62 , m_indexToSelectOnCancel(-1)
65 { 63 {
66 ASSERT(isHTMLSelectElement(element)); 64 ASSERT(isHTMLSelectElement(element));
67 } 65 }
68 66
69 LayoutMenuList::~LayoutMenuList() 67 LayoutMenuList::~LayoutMenuList()
70 { 68 {
71 ASSERT(!m_popup); 69 ASSERT(!m_popup);
72 } 70 }
73 71
(...skipping 16 matching lines...) Expand all
90 { 88 {
91 if (m_innerBlock) { 89 if (m_innerBlock) {
92 ASSERT(firstChild() == m_innerBlock); 90 ASSERT(firstChild() == m_innerBlock);
93 ASSERT(!m_innerBlock->nextSibling()); 91 ASSERT(!m_innerBlock->nextSibling());
94 return; 92 return;
95 } 93 }
96 94
97 // Create an anonymous block. 95 // Create an anonymous block.
98 ASSERT(!firstChild()); 96 ASSERT(!firstChild());
99 m_innerBlock = createAnonymousBlock(); 97 m_innerBlock = createAnonymousBlock();
100
101 m_buttonText = new LayoutText(&document(), StringImpl::empty());
102 // We need to set the text explicitly though it was specified in the
103 // constructor because LayoutText doesn't refer to the text
104 // specified in the constructor in a case of re-transforming.
105 m_buttonText->setStyle(mutableStyle());
106 m_innerBlock->addChild(m_buttonText);
107
108 adjustInnerStyle(); 98 adjustInnerStyle();
109 LayoutFlexibleBox::addChild(m_innerBlock); 99 LayoutFlexibleBox::addChild(m_innerBlock);
110 } 100 }
111 101
112 void LayoutMenuList::adjustInnerStyle() 102 void LayoutMenuList::adjustInnerStyle()
113 { 103 {
114 ComputedStyle& innerStyle = m_innerBlock->mutableStyleRef(); 104 ComputedStyle& innerStyle = m_innerBlock->mutableStyleRef();
115 innerStyle.setFlexGrow(1); 105 innerStyle.setFlexGrow(1);
116 innerStyle.setFlexShrink(1); 106 innerStyle.setFlexShrink(1);
117 // min-width: 0; is needed for correct shrinking. 107 // min-width: 0; is needed for correct shrinking.
(...skipping 21 matching lines...) Expand all
139 } 129 }
140 } 130 }
141 131
142 inline HTMLSelectElement* LayoutMenuList::selectElement() const 132 inline HTMLSelectElement* LayoutMenuList::selectElement() const
143 { 133 {
144 return toHTMLSelectElement(node()); 134 return toHTMLSelectElement(node());
145 } 135 }
146 136
147 void LayoutMenuList::addChild(LayoutObject* newChild, LayoutObject* beforeChild) 137 void LayoutMenuList::addChild(LayoutObject* newChild, LayoutObject* beforeChild)
148 { 138 {
139 createInnerBlock();
149 m_innerBlock->addChild(newChild, beforeChild); 140 m_innerBlock->addChild(newChild, beforeChild);
150 ASSERT(m_innerBlock == firstChild()); 141 ASSERT(m_innerBlock == firstChild());
151 142
152 if (AXObjectCache* cache = document().existingAXObjectCache()) 143 if (AXObjectCache* cache = document().existingAXObjectCache())
153 cache->childrenChanged(this); 144 cache->childrenChanged(this);
154 } 145 }
155 146
156 void LayoutMenuList::removeChild(LayoutObject* oldChild) 147 void LayoutMenuList::removeChild(LayoutObject* oldChild)
157 { 148 {
158 if (oldChild == m_innerBlock || !m_innerBlock) { 149 if (oldChild == m_innerBlock || !m_innerBlock) {
159 LayoutFlexibleBox::removeChild(oldChild); 150 LayoutFlexibleBox::removeChild(oldChild);
160 m_innerBlock = nullptr; 151 m_innerBlock = nullptr;
161 } else { 152 } else {
162 m_innerBlock->removeChild(oldChild); 153 m_innerBlock->removeChild(oldChild);
163 } 154 }
164 } 155 }
165 156
166 void LayoutMenuList::styleDidChange(StyleDifference diff, const ComputedStyle* o ldStyle) 157 void LayoutMenuList::styleDidChange(StyleDifference diff, const ComputedStyle* o ldStyle)
167 { 158 {
168 LayoutBlock::styleDidChange(diff, oldStyle); 159 LayoutBlock::styleDidChange(diff, oldStyle);
169 160
170 if (!m_innerBlock) 161 if (m_buttonText)
171 createInnerBlock(); 162 m_buttonText->setStyle(mutableStyle());
172 163 if (m_innerBlock) // LayoutBlock handled updating the anonymous block's styl e.
173 m_buttonText->setStyle(mutableStyle()); 164 adjustInnerStyle();
174 adjustInnerStyle();
175 165
176 bool fontChanged = !oldStyle || oldStyle->font() != style()->font(); 166 bool fontChanged = !oldStyle || oldStyle->font() != style()->font();
177 if (fontChanged) 167 if (fontChanged)
178 updateOptionsWidth(); 168 updateOptionsWidth();
179 } 169 }
180 170
181 void LayoutMenuList::updateOptionsWidth() 171 void LayoutMenuList::updateOptionsWidth()
182 { 172 {
183 float maxOptionWidth = 0; 173 float maxOptionWidth = 0;
184 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& listItems = selectE lement()->listItems(); 174 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& listItems = selectE lement()->listItems();
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 } 280 }
291 281
292 setText(text.stripWhiteSpace()); 282 setText(text.stripWhiteSpace());
293 283
294 didUpdateActiveOption(optionIndex); 284 didUpdateActiveOption(optionIndex);
295 } 285 }
296 286
297 void LayoutMenuList::setText(const String& s) 287 void LayoutMenuList::setText(const String& s)
298 { 288 {
299 if (s.isEmpty()) { 289 if (s.isEmpty()) {
300 // FIXME: This is a hack. We need the select to have the same baseline p ositioning as 290 if (!m_buttonText || !m_buttonText->isBR()) {
301 // any surrounding text. Wihtout any content, we align the bottom of the select to the bottom 291 // FIXME: We should not modify the structure of the layout tree
302 // of the text. With content (In this case the faked " ") we correctly a lign the middle of 292 // during layout. crbug.com/370462
303 // the select to the middle of the text. It should be possible to remove this, just set 293 DeprecatedDisableModifyLayoutTreeStructureAsserts disabler;
304 // s.impl() into the text and have things align correctly ... crbug.com /485982 294 if (m_buttonText)
305 m_isEmpty = true; 295 m_buttonText->destroy();
306 m_buttonText->setText(StringImpl::create(" ", 1), true); 296 m_buttonText = new LayoutBR(&document());
297 m_buttonText->setStyle(mutableStyle());
298 addChild(m_buttonText);
299 }
307 } else { 300 } else {
308 m_isEmpty = false; 301 if (m_buttonText && !m_buttonText->isBR()) {
309 m_buttonText->setText(s.impl(), true); 302 m_buttonText->setText(s.impl(), true);
303 } else {
304 // FIXME: We should not modify the structure of the layout tree
305 // during layout. crbug.com/370462
306 DeprecatedDisableModifyLayoutTreeStructureAsserts disabler;
307 if (m_buttonText)
308 m_buttonText->destroy();
309 m_buttonText = new LayoutText(&document(), s.impl());
310 m_buttonText->setStyle(mutableStyle());
311 // We need to set the text explicitly though it was specified in the
312 // constructor because LayoutText doesn't refer to the text
313 // specified in the constructor in a case of re-transforming.
314 m_buttonText->setText(s.impl(), true);
315 addChild(m_buttonText);
316 }
317 adjustInnerStyle();
310 } 318 }
311 adjustInnerStyle();
312 } 319 }
313 320
314 String LayoutMenuList::text() const 321 String LayoutMenuList::text() const
315 { 322 {
316 return m_buttonText && !m_isEmpty ? m_buttonText->text() : String(); 323 return m_buttonText ? m_buttonText->text() : String();
317 } 324 }
318 325
319 LayoutRect LayoutMenuList::controlClipRect(const LayoutPoint& additionalOffset) const 326 LayoutRect LayoutMenuList::controlClipRect(const LayoutPoint& additionalOffset) const
320 { 327 {
321 // Clip to the intersection of the content box and the content box for the i nner box 328 // Clip to the intersection of the content box and the content box for the i nner box
322 // This will leave room for the arrows which sit in the inner box padding, 329 // This will leave room for the arrows which sit in the inner box padding,
323 // and if the inner box ever spills out of the outer box, that will get clip ped too. 330 // and if the inner box ever spills out of the outer box, that will get clip ped too.
324 LayoutRect outerBox = contentBoxRect(); 331 LayoutRect outerBox = contentBoxRect();
325 outerBox.moveBy(additionalOffset); 332 outerBox.moveBy(additionalOffset);
326 333
(...skipping 12 matching lines...) Expand all
339 } 346 }
340 347
341 void LayoutMenuList::showPopup() 348 void LayoutMenuList::showPopup()
342 { 349 {
343 if (m_popupIsVisible) 350 if (m_popupIsVisible)
344 return; 351 return;
345 352
346 if (document().frameHost()->chrome().hasOpenedPopup()) 353 if (document().frameHost()->chrome().hasOpenedPopup())
347 return; 354 return;
348 355
356 // Create m_innerBlock here so it ends up as the first child.
357 // This is important because otherwise we might try to create m_innerBlock
358 // inside the showPopup call and it would fail.
359 createInnerBlock();
349 if (!m_popup) 360 if (!m_popup)
350 m_popup = document().frameHost()->chrome().createPopupMenu(*document().f rame(), this); 361 m_popup = document().frameHost()->chrome().createPopupMenu(*document().f rame(), this);
351 m_popupIsVisible = true; 362 m_popupIsVisible = true;
352 363
353 FloatQuad quad(localToAbsoluteQuad(FloatQuad(borderBoundingBox()))); 364 FloatQuad quad(localToAbsoluteQuad(FloatQuad(borderBoundingBox())));
354 IntSize size = pixelSnappedIntRect(frameRect()).size(); 365 IntSize size = pixelSnappedIntRect(frameRect()).size();
355 HTMLSelectElement* select = selectElement(); 366 HTMLSelectElement* select = selectElement();
356 m_popup->show(quad, size, select->optionToListIndex(select->selectedIndex()) ); 367 m_popup->show(quad, size, select->optionToListIndex(select->selectedIndex()) );
357 if (AXObjectCache* cache = document().existingAXObjectCache()) 368 if (AXObjectCache* cache = document().existingAXObjectCache())
358 cache->didShowMenuListPopup(this); 369 cache->didShowMenuListPopup(this);
370
359 } 371 }
360 372
361 void LayoutMenuList::hidePopup() 373 void LayoutMenuList::hidePopup()
362 { 374 {
363 if (m_popup) 375 if (m_popup)
364 m_popup->hide(); 376 m_popup->hide();
365 } 377 }
366 378
367 void LayoutMenuList::valueChanged(unsigned listIndex, bool fireOnChange) 379 void LayoutMenuList::valueChanged(unsigned listIndex, bool fireOnChange)
368 { 380 {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 return; 428 return;
417 429
418 if (m_lastActiveIndex == optionIndex) 430 if (m_lastActiveIndex == optionIndex)
419 return; 431 return;
420 m_lastActiveIndex = optionIndex; 432 m_lastActiveIndex = optionIndex;
421 433
422 HTMLSelectElement* select = selectElement(); 434 HTMLSelectElement* select = selectElement();
423 int listIndex = select->optionToListIndex(optionIndex); 435 int listIndex = select->optionToListIndex(optionIndex);
424 if (listIndex < 0 || listIndex >= static_cast<int>(select->listItems().size( ))) 436 if (listIndex < 0 || listIndex >= static_cast<int>(select->listItems().size( )))
425 return; 437 return;
426
427 // We skip sending accessiblity notifications for the very first option, oth erwise
428 // we get extra focus and select events that are undesired.
429 if (!m_hasUpdatedActiveOption) {
430 m_hasUpdatedActiveOption = true;
431 return;
432 }
433
434 document().existingAXObjectCache()->handleUpdateActiveMenuOption(this, optio nIndex); 438 document().existingAXObjectCache()->handleUpdateActiveMenuOption(this, optio nIndex);
435 } 439 }
436 440
437 String LayoutMenuList::itemText(unsigned listIndex) const 441 String LayoutMenuList::itemText(unsigned listIndex) const
438 { 442 {
439 HTMLSelectElement* select = selectElement(); 443 HTMLSelectElement* select = selectElement();
440 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& listItems = select- >listItems(); 444 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement>>& listItems = select- >listItems();
441 if (listIndex >= listItems.size()) 445 if (listIndex >= listItems.size())
442 return String(); 446 return String();
443 447
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 HTMLElement* element = listItems[listIndex]; 623 HTMLElement* element = listItems[listIndex];
620 return isHTMLOptionElement(*element) && toHTMLOptionElement(*element).select ed(); 624 return isHTMLOptionElement(*element) && toHTMLOptionElement(*element).select ed();
621 } 625 }
622 626
623 void LayoutMenuList::provisionalSelectionChanged(unsigned listIndex) 627 void LayoutMenuList::provisionalSelectionChanged(unsigned listIndex)
624 { 628 {
625 setIndexToSelectOnCancel(listIndex); 629 setIndexToSelectOnCancel(listIndex);
626 } 630 }
627 631
628 } // namespace blink 632 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/layout/LayoutMenuList.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698