• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
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 "RenderSlider.h"
23 
24 #include "CSSPropertyNames.h"
25 #include "CSSStyleSelector.h"
26 #include "Document.h"
27 #include "Event.h"
28 #include "EventHandler.h"
29 #include "EventNames.h"
30 #include "Frame.h"
31 #include "HTMLInputElement.h"
32 #include "HTMLNames.h"
33 #include "HTMLParserIdioms.h"
34 #include "MediaControlElements.h"
35 #include "MouseEvent.h"
36 #include "Node.h"
37 #include "RenderLayer.h"
38 #include "RenderTheme.h"
39 #include "RenderView.h"
40 #include "ShadowElement.h"
41 #include "SliderThumbElement.h"
42 #include "StepRange.h"
43 #include <wtf/MathExtras.h>
44 
45 using std::min;
46 
47 namespace WebCore {
48 
49 static const int defaultTrackLength = 129;
50 
51 // Returns a value between 0 and 1.
sliderPosition(HTMLInputElement * element)52 static double sliderPosition(HTMLInputElement* element)
53 {
54     StepRange range(element);
55     return range.proportionFromValue(range.valueFromElement(element));
56 }
57 
RenderSlider(HTMLInputElement * element)58 RenderSlider::RenderSlider(HTMLInputElement* element)
59     : RenderBlock(element)
60 {
61 }
62 
~RenderSlider()63 RenderSlider::~RenderSlider()
64 {
65 }
66 
baselinePosition(FontBaseline,bool,LineDirectionMode,LinePositionMode) const67 int RenderSlider::baselinePosition(FontBaseline, bool /*firstLine*/, LineDirectionMode, LinePositionMode) const
68 {
69     // FIXME: Patch this function for writing-mode.
70     return height() + marginTop();
71 }
72 
computePreferredLogicalWidths()73 void RenderSlider::computePreferredLogicalWidths()
74 {
75     m_minPreferredLogicalWidth = 0;
76     m_maxPreferredLogicalWidth = 0;
77 
78     if (style()->width().isFixed() && style()->width().value() > 0)
79         m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = computeContentBoxLogicalWidth(style()->width().value());
80     else
81         m_maxPreferredLogicalWidth = defaultTrackLength * style()->effectiveZoom();
82 
83     if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
84         m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->minWidth().value()));
85         m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->minWidth().value()));
86     } else if (style()->width().isPercent() || (style()->width().isAuto() && style()->height().isPercent()))
87         m_minPreferredLogicalWidth = 0;
88     else
89         m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth;
90 
91     if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) {
92         m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->maxWidth().value()));
93         m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->maxWidth().value()));
94     }
95 
96     int toAdd = borderAndPaddingWidth();
97     m_minPreferredLogicalWidth += toAdd;
98     m_maxPreferredLogicalWidth += toAdd;
99 
100     setPreferredLogicalWidthsDirty(false);
101 }
102 
thumbRect()103 IntRect RenderSlider::thumbRect()
104 {
105     SliderThumbElement* thumbElement = shadowSliderThumb();
106     if (!thumbElement)
107         return IntRect();
108 
109     IntRect thumbRect;
110     RenderBox* thumb = toRenderBox(thumbElement->renderer());
111 
112     thumbRect.setWidth(thumb->style()->width().calcMinValue(contentWidth()));
113     thumbRect.setHeight(thumb->style()->height().calcMinValue(contentHeight()));
114 
115     double fraction = sliderPosition(static_cast<HTMLInputElement*>(node()));
116     IntRect contentRect = contentBoxRect();
117     if (style()->appearance() == SliderVerticalPart || style()->appearance() == MediaVolumeSliderPart) {
118         thumbRect.setX(contentRect.x() + (contentRect.width() - thumbRect.width()) / 2);
119         thumbRect.setY(contentRect.y() + static_cast<int>(nextafter((contentRect.height() - thumbRect.height()) + 1, 0) * (1 - fraction)));
120     } else {
121         thumbRect.setX(contentRect.x() + static_cast<int>(nextafter((contentRect.width() - thumbRect.width()) + 1, 0) * fraction));
122         thumbRect.setY(contentRect.y() + (contentRect.height() - thumbRect.height()) / 2);
123     }
124 
125     return thumbRect;
126 }
127 
layout()128 void RenderSlider::layout()
129 {
130     ASSERT(needsLayout());
131 
132     SliderThumbElement* thumbElement = shadowSliderThumb();
133     RenderBox* thumb = thumbElement ? toRenderBox(thumbElement->renderer()) : 0;
134 
135     IntSize baseSize(borderAndPaddingWidth(), borderAndPaddingHeight());
136 
137     if (thumb) {
138         // Allow the theme to set the size of the thumb.
139         if (thumb->style()->hasAppearance()) {
140             // FIXME: This should pass the style, not the renderer, to the theme.
141             theme()->adjustSliderThumbSize(thumb);
142         }
143 
144         baseSize.expand(thumb->style()->width().calcMinValue(0), thumb->style()->height().calcMinValue(0));
145     }
146 
147     LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
148 
149     IntSize oldSize = size();
150 
151     setSize(baseSize);
152     computeLogicalWidth();
153     computeLogicalHeight();
154     updateLayerTransform();
155 
156     if (thumb) {
157         if (oldSize != size())
158             thumb->setChildNeedsLayout(true, false);
159 
160         LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), style()->isFlippedBlocksWritingMode());
161 
162         IntRect oldThumbRect = thumb->frameRect();
163 
164         thumb->layoutIfNeeded();
165 
166         IntRect rect = thumbRect();
167         thumb->setFrameRect(rect);
168         if (thumb->checkForRepaintDuringLayout())
169             thumb->repaintDuringLayoutIfMoved(oldThumbRect);
170 
171         statePusher.pop();
172         addOverflowFromChild(thumb);
173     }
174 
175     repainter.repaintAfterLayout();
176 
177     setNeedsLayout(false);
178 }
179 
shadowSliderThumb() const180 SliderThumbElement* RenderSlider::shadowSliderThumb() const
181 {
182     Node* shadow = static_cast<Element*>(node())->shadowRoot();
183     return shadow ? toSliderThumbElement(shadow->firstChild()) : 0;
184 }
185 
inDragMode() const186 bool RenderSlider::inDragMode() const
187 {
188     SliderThumbElement* thumbElement = shadowSliderThumb();
189     return thumbElement && thumbElement->inDragMode();
190 }
191 
192 } // namespace WebCore
193