~ubuntu-branches/ubuntu/maverick/webkit/maverick

« back to all changes in this revision

Viewing changes to WebCore/rendering/RenderListBox.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Mike Hommey
  • Date: 2007-08-19 15:54:12 UTC
  • Revision ID: james.westby@ubuntu.com-20070819155412-uxxg1h9plpghmtbi
Tags: upstream-0~svn25144
ImportĀ upstreamĀ versionĀ 0~svn25144

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is part of the select element renderer in WebCore.
 
3
 *
 
4
 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
 
5
 *
 
6
 * Redistribution and use in source and binary forms, with or without
 
7
 * modification, are permitted provided that the following conditions
 
8
 * are met:
 
9
 *
 
10
 * 1.  Redistributions of source code must retain the above copyright
 
11
 *     notice, this list of conditions and the following disclaimer. 
 
12
 * 2.  Redistributions in binary form must reproduce the above copyright
 
13
 *     notice, this list of conditions and the following disclaimer in the
 
14
 *     documentation and/or other materials provided with the distribution. 
 
15
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 
16
 *     its contributors may be used to endorse or promote products derived
 
17
 *     from this software without specific prior written permission. 
 
18
 *
 
19
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 
20
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 
21
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
22
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 
23
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 
24
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
25
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 
26
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
27
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 
28
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
29
 */
 
30
 
 
31
#include "config.h"
 
32
#include "RenderListBox.h"
 
33
 
 
34
#include "Document.h"
 
35
#include "EventHandler.h"
 
36
#include "EventNames.h"
 
37
#include "Frame.h"
 
38
#include "FrameView.h"
 
39
#include "GraphicsContext.h"
 
40
#include "HTMLNames.h"
 
41
#include "HTMLOptGroupElement.h"
 
42
#include "HTMLOptionElement.h"
 
43
#include "HTMLSelectElement.h"
 
44
#include "HitTestResult.h"
 
45
#include "PlatformScrollBar.h" 
 
46
#include "RenderTheme.h"
 
47
#include "RenderView.h"
 
48
#include "TextStyle.h"
 
49
#include <math.h>
 
50
 
 
51
using namespace std;
 
52
 
 
53
namespace WebCore {
 
54
 
 
55
using namespace EventNames;
 
56
using namespace HTMLNames;
 
57
 
 
58
const int rowSpacing = 1;
 
59
 
 
60
const int optionsSpacingHorizontal = 2;
 
61
 
 
62
const int minSize = 4;
 
63
const int maxDefaultSize = 10;
 
64
 
 
65
// FIXME: This hardcoded baselineAdjustment is what we used to do for the old
 
66
// widget, but I'm not sure this is right for the new control.
 
67
const int baselineAdjustment = 7;
 
68
 
 
69
RenderListBox::RenderListBox(HTMLSelectElement* element)
 
70
    : RenderBlock(element)
 
71
    , m_optionsChanged(true)
 
72
    , m_scrollToRevealSelectionAfterLayout(false)
 
73
    , m_inAutoscroll(false)
 
74
    , m_optionsWidth(0)
 
75
    , m_indexOffset(0)
 
76
{
 
77
}
 
78
 
 
79
RenderListBox::~RenderListBox()
 
80
{
 
81
    if (m_vBar && m_vBar->isWidget())
 
82
        if (FrameView* view = node()->document()->view())
 
83
            view->removeChild(static_cast<PlatformScrollbar*>(m_vBar.get()));
 
84
}
 
85
 
 
86
void RenderListBox::setStyle(RenderStyle* style)
 
87
{
 
88
    RenderBlock::setStyle(style);
 
89
    setReplaced(isInline());
 
90
}
 
91
 
 
92
void RenderListBox::updateFromElement()
 
93
{
 
94
    if (m_optionsChanged) {
 
95
        const Vector<HTMLElement*>& listItems = static_cast<HTMLSelectElement*>(node())->listItems();
 
96
        int size = numItems();
 
97
        
 
98
        float width = 0;
 
99
        TextStyle textStyle(0, 0, 0, false, false, false, false);
 
100
        for (int i = 0; i < size; ++i) {
 
101
            HTMLElement* element = listItems[i];
 
102
            String text;
 
103
            Font itemFont = style()->font();
 
104
            if (element->hasTagName(optionTag))
 
105
                text = static_cast<HTMLOptionElement*>(element)->optionText();
 
106
            else if (element->hasTagName(optgroupTag)) {
 
107
                text = static_cast<HTMLOptGroupElement*>(element)->groupLabelText();
 
108
                FontDescription d = itemFont.fontDescription();
 
109
                d.setBold(true);
 
110
                itemFont = Font(d, itemFont.letterSpacing(), itemFont.wordSpacing());
 
111
                itemFont.update();
 
112
            }
 
113
                
 
114
            if (!text.isEmpty()) {
 
115
                float textWidth = itemFont.floatWidth(TextRun(text.impl()), textStyle);
 
116
                width = max(width, textWidth);
 
117
            }
 
118
        }
 
119
        m_optionsWidth = static_cast<int>(ceilf(width));
 
120
        m_optionsChanged = false;
 
121
        
 
122
        if (!m_vBar && Scrollbar::hasPlatformScrollbars())
 
123
            if (FrameView* view = node()->document()->view()) {
 
124
                RefPtr<PlatformScrollbar> widget = new PlatformScrollbar(this, VerticalScrollbar, SmallScrollbar);
 
125
                view->addChild(widget.get());
 
126
                m_vBar = widget.release();
 
127
            }
 
128
        
 
129
        setNeedsLayoutAndPrefWidthsRecalc();
 
130
    }
 
131
}
 
132
 
 
133
void RenderListBox::selectionChanged()
 
134
{
 
135
    repaint();
 
136
    if (!m_inAutoscroll) {
 
137
        if (m_optionsChanged || needsLayout())
 
138
            m_scrollToRevealSelectionAfterLayout = true;
 
139
        else
 
140
            scrollToRevealSelection();
 
141
    }
 
142
}
 
143
 
 
144
void RenderListBox::layout()
 
145
{
 
146
    RenderBlock::layout();
 
147
    if (m_scrollToRevealSelectionAfterLayout)
 
148
        scrollToRevealSelection();
 
149
}
 
150
 
 
151
void RenderListBox::scrollToRevealSelection()
 
152
{    
 
153
    HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
 
154
 
 
155
    m_scrollToRevealSelectionAfterLayout = false;
 
156
 
 
157
    int firstIndex = select->activeSelectionStartListIndex();
 
158
    if (firstIndex >= 0 && !listIndexIsVisible(select->activeSelectionEndListIndex()))
 
159
        scrollToRevealElementAtListIndex(firstIndex);
 
160
}
 
161
 
 
162
void RenderListBox::calcPrefWidths()
 
163
{
 
164
    ASSERT(!m_optionsChanged);
 
165
 
 
166
    m_minPrefWidth = 0;
 
167
    m_maxPrefWidth = 0;
 
168
 
 
169
    if (style()->width().isFixed() && style()->width().value() > 0)
 
170
        m_minPrefWidth = m_maxPrefWidth = calcContentBoxWidth(style()->width().value());
 
171
    else {
 
172
        m_maxPrefWidth = m_optionsWidth + 2 * optionsSpacingHorizontal;
 
173
        if (m_vBar)
 
174
            m_maxPrefWidth += m_vBar->width();
 
175
    }
 
176
 
 
177
    if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
 
178
        m_maxPrefWidth = max(m_maxPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
 
179
        m_minPrefWidth = max(m_minPrefWidth, calcContentBoxWidth(style()->minWidth().value()));
 
180
    } else if (style()->width().isPercent() || (style()->width().isAuto() && style()->height().isPercent()))
 
181
        m_minPrefWidth = 0;
 
182
    else
 
183
        m_minPrefWidth = m_maxPrefWidth;
 
184
 
 
185
    if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) {
 
186
        m_maxPrefWidth = min(m_maxPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
 
187
        m_minPrefWidth = min(m_minPrefWidth, calcContentBoxWidth(style()->maxWidth().value()));
 
188
    }
 
189
 
 
190
    int toAdd = paddingLeft() + paddingRight() + borderLeft() + borderRight();
 
191
    m_minPrefWidth += toAdd;
 
192
    m_maxPrefWidth += toAdd;
 
193
                                
 
194
    setPrefWidthsDirty(false);
 
195
}
 
196
 
 
197
int RenderListBox::size() const
 
198
{
 
199
    int specifiedSize = static_cast<HTMLSelectElement*>(node())->size();
 
200
    if (specifiedSize > 1)
 
201
        return max(minSize, specifiedSize);
 
202
    return min(max(minSize, numItems()), maxDefaultSize);
 
203
}
 
204
 
 
205
int RenderListBox::numVisibleItems() const
 
206
{
 
207
    // Only count fully visible rows. But don't return 0 even if only part of a row shows.
 
208
    return max(1, (contentHeight() + rowSpacing) / itemHeight());
 
209
}
 
210
 
 
211
int RenderListBox::numItems() const
 
212
{
 
213
    return static_cast<HTMLSelectElement*>(node())->listItems().size();
 
214
}
 
215
 
 
216
int RenderListBox::listHeight() const
 
217
{
 
218
    return itemHeight() * numItems() - rowSpacing;
 
219
}
 
220
 
 
221
void RenderListBox::calcHeight()
 
222
{
 
223
    int toAdd = paddingTop() + paddingBottom() + borderTop() + borderBottom();
 
224
 
 
225
    int itemHeight = RenderListBox::itemHeight();
 
226
    m_height = itemHeight * size() - rowSpacing + toAdd;
 
227
    
 
228
    RenderBlock::calcHeight();
 
229
    
 
230
    if (m_vBar) {
 
231
        m_vBar->setEnabled(numVisibleItems() < numItems());
 
232
        m_vBar->setSteps(1, min(1, numVisibleItems() - 1), itemHeight);
 
233
        m_vBar->setProportion(numVisibleItems(), numItems());
 
234
    }
 
235
}
 
236
 
 
237
short RenderListBox::baselinePosition(bool b, bool isRootLineBox) const
 
238
{
 
239
    return height() + marginTop() + marginBottom() - baselineAdjustment;
 
240
}
 
241
 
 
242
IntRect RenderListBox::itemBoundingBoxRect(int tx, int ty, int index)
 
243
{
 
244
    return IntRect(tx + borderLeft() + paddingLeft(),
 
245
                   ty + borderTop() + paddingTop() + itemHeight() * (index - m_indexOffset),
 
246
                   contentWidth(), itemHeight());
 
247
}
 
248
    
 
249
void RenderListBox::paintObject(PaintInfo& paintInfo, int tx, int ty)
 
250
{
 
251
    if (style()->visibility() != VISIBLE)
 
252
        return;
 
253
    
 
254
    int listItemsSize = numItems();
 
255
 
 
256
    if (paintInfo.phase == PaintPhaseForeground) {
 
257
        int index = m_indexOffset;
 
258
        while (index < listItemsSize && index <= m_indexOffset + numVisibleItems()) {
 
259
            paintItemForeground(paintInfo, tx, ty, index);
 
260
            index++;
 
261
        }
 
262
    }
 
263
 
 
264
    // Paint the children.
 
265
    RenderBlock::paintObject(paintInfo, tx, ty);
 
266
 
 
267
    if (paintInfo.phase == PaintPhaseBlockBackground)
 
268
        paintScrollbar(paintInfo);
 
269
    else if (paintInfo.phase == PaintPhaseChildBlockBackground || paintInfo.phase == PaintPhaseChildBlockBackgrounds) {
 
270
        int index = m_indexOffset;
 
271
        while (index < listItemsSize && index <= m_indexOffset + numVisibleItems()) {
 
272
            paintItemBackground(paintInfo, tx, ty, index);
 
273
            index++;
 
274
        }
 
275
    }
 
276
}
 
277
 
 
278
void RenderListBox::paintScrollbar(PaintInfo& paintInfo)
 
279
{
 
280
    if (m_vBar) {
 
281
        IntRect absBounds = absoluteBoundingBoxRect();
 
282
        IntRect scrollRect(absBounds.right() - borderRight() - m_vBar->width(),
 
283
                           absBounds.y() + borderTop(),
 
284
                           m_vBar->width(),
 
285
                           absBounds.height() - (borderTop() + borderBottom()));
 
286
        m_vBar->setRect(scrollRect);
 
287
        m_vBar->paint(paintInfo.context, scrollRect);
 
288
    }
 
289
}
 
290
 
 
291
void RenderListBox::paintItemForeground(PaintInfo& paintInfo, int tx, int ty, int listIndex)
 
292
{
 
293
    HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
 
294
    const Vector<HTMLElement*>& listItems = select->listItems();
 
295
    HTMLElement* element = listItems[listIndex];
 
296
 
 
297
    String itemText;
 
298
    if (element->hasTagName(optionTag))
 
299
        itemText = static_cast<HTMLOptionElement*>(element)->optionText();
 
300
    else if (element->hasTagName(optgroupTag))
 
301
        itemText = static_cast<HTMLOptGroupElement*>(element)->groupLabelText();
 
302
       
 
303
    // Determine where the item text should be placed
 
304
    IntRect r = itemBoundingBoxRect(tx, ty, listIndex);
 
305
    r.move(optionsSpacingHorizontal, style()->font().ascent());
 
306
 
 
307
    RenderStyle* itemStyle = element->renderStyle();
 
308
    if (!itemStyle)
 
309
        itemStyle = style();
 
310
    
 
311
    Color textColor = element->renderStyle() ? element->renderStyle()->color() : style()->color();
 
312
    if (element->hasTagName(optionTag) && static_cast<HTMLOptionElement*>(element)->selected()) {
 
313
        if (document()->frame()->isActive() && document()->focusedNode() == node())
 
314
            textColor = theme()->activeListBoxSelectionForegroundColor();
 
315
        // Honor the foreground color for disabled items
 
316
        else if (!element->disabled())
 
317
            textColor = theme()->inactiveListBoxSelectionForegroundColor();
 
318
    }
 
319
 
 
320
    paintInfo.context->setFillColor(textColor);
 
321
 
 
322
    Font itemFont = style()->font();
 
323
    if (element->hasTagName(optgroupTag)) {
 
324
        FontDescription d = itemFont.fontDescription();
 
325
        d.setBold(true);
 
326
        itemFont = Font(d, itemFont.letterSpacing(), itemFont.wordSpacing());
 
327
        itemFont.update();
 
328
    }
 
329
    paintInfo.context->setFont(itemFont);
 
330
    
 
331
    unsigned length = itemText.length();
 
332
    const UChar* string = itemText.characters();
 
333
    TextStyle textStyle(0, 0, 0, itemStyle->direction() == RTL, itemStyle->unicodeBidi() == Override, false, false);
 
334
    TextRun textRun(string, length);
 
335
 
 
336
    // Draw the item text
 
337
    if (itemStyle->visibility() != HIDDEN)
 
338
        paintInfo.context->drawBidiText(textRun, r.location(), textStyle);
 
339
}
 
340
 
 
341
void RenderListBox::paintItemBackground(PaintInfo& paintInfo, int tx, int ty, int listIndex)
 
342
{
 
343
    HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
 
344
    const Vector<HTMLElement*>& listItems = select->listItems();
 
345
    HTMLElement* element = listItems[listIndex];
 
346
 
 
347
    Color backColor;
 
348
    if (element->hasTagName(optionTag) && static_cast<HTMLOptionElement*>(element)->selected()) {
 
349
        if (document()->frame()->isActive() && document()->focusedNode() == node())
 
350
            backColor = theme()->activeListBoxSelectionBackgroundColor();
 
351
        else
 
352
            backColor = theme()->inactiveListBoxSelectionBackgroundColor();
 
353
    } else
 
354
        backColor = element->renderStyle() ? element->renderStyle()->backgroundColor() : style()->backgroundColor();
 
355
 
 
356
    // Draw the background for this list box item
 
357
    if (!element->renderStyle() || element->renderStyle()->visibility() != HIDDEN) {
 
358
        IntRect itemRect = itemBoundingBoxRect(tx, ty, listIndex);
 
359
        itemRect.intersect(controlClipRect(tx, ty));
 
360
        paintInfo.context->fillRect(itemRect, backColor);
 
361
    }
 
362
}
 
363
 
 
364
bool RenderListBox::isPointInOverflowControl(HitTestResult& result, int _x, int _y, int _tx, int _ty)
 
365
{
 
366
    if (!m_vBar)
 
367
        return false;
 
368
 
 
369
    IntRect vertRect(_tx + width() - borderRight() - m_vBar->width(),
 
370
                   _ty + borderTop() - borderTopExtra(),
 
371
                   m_vBar->width(),
 
372
                   height() + borderTopExtra() + borderBottomExtra() - borderTop() - borderBottom());
 
373
 
 
374
    if (vertRect.contains(_x, _y)) {
 
375
        result.setScrollbar(m_vBar->isWidget() ? static_cast<PlatformScrollbar*>(m_vBar.get()) : 0);
 
376
        return true;
 
377
    }
 
378
    return false;
 
379
}
 
380
 
 
381
int RenderListBox::listIndexAtOffset(int offsetX, int offsetY)
 
382
{
 
383
    if (!numItems())
 
384
        return -1;
 
385
 
 
386
    if (offsetY < borderTop() + paddingTop() || offsetY > height() - paddingBottom() - borderBottom())
 
387
        return -1;
 
388
 
 
389
    int scrollbarWidth = m_vBar ? m_vBar->width() : 0;
 
390
    if (offsetX < borderLeft() + paddingLeft() || offsetX > width() - borderRight() - paddingRight() - scrollbarWidth)
 
391
        return -1;
 
392
 
 
393
    int newOffset = (offsetY - borderTop() - paddingTop()) / itemHeight() + m_indexOffset;
 
394
    return newOffset < numItems() ? newOffset : -1;
 
395
}
 
396
 
 
397
void RenderListBox::autoscroll()
 
398
{
 
399
    IntPoint pos = document()->frame()->view()->windowToContents(document()->frame()->eventHandler()->currentMousePosition());
 
400
 
 
401
    int rx = 0;
 
402
    int ry = 0;
 
403
    absolutePosition(rx, ry);
 
404
    int offsetX = pos.x() - rx;
 
405
    int offsetY = pos.y() - ry;
 
406
    
 
407
    int endIndex = -1;
 
408
    int rows = numVisibleItems();
 
409
    int offset = m_indexOffset;
 
410
    if (offsetY < borderTop() + paddingTop() && scrollToRevealElementAtListIndex(offset - 1))
 
411
        endIndex = offset - 1;
 
412
    else if (offsetY > height() - paddingBottom() - borderBottom() && scrollToRevealElementAtListIndex(offset + rows))
 
413
        endIndex = offset + rows - 1;
 
414
    else
 
415
        endIndex = listIndexAtOffset(offsetX, offsetY);
 
416
 
 
417
    if (endIndex >= 0) {
 
418
        HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
 
419
        m_inAutoscroll = true;
 
420
        if (!select->multiple())
 
421
            select->setActiveSelectionAnchorIndex(endIndex);
 
422
        select->setActiveSelectionEndIndex(endIndex);
 
423
        select->updateListBoxSelection(!select->multiple());
 
424
        m_inAutoscroll = false;
 
425
    }
 
426
}
 
427
 
 
428
void RenderListBox::stopAutoscroll()
 
429
{
 
430
    static_cast<HTMLSelectElement*>(node())->listBoxOnChange();
 
431
}
 
432
 
 
433
bool RenderListBox::scrollToRevealElementAtListIndex(int index)
 
434
{
 
435
    if (index < 0 || index >= numItems() || listIndexIsVisible(index))
 
436
        return false;
 
437
 
 
438
    int newOffset;
 
439
    if (index < m_indexOffset)
 
440
        newOffset = index;
 
441
    else
 
442
        newOffset = index - numVisibleItems() + 1;
 
443
 
 
444
    m_indexOffset = newOffset;
 
445
    if (m_vBar)
 
446
        m_vBar->setValue(m_indexOffset);
 
447
 
 
448
    return true;
 
449
}
 
450
 
 
451
bool RenderListBox::listIndexIsVisible(int index)
 
452
{    
 
453
    return index >= m_indexOffset && index < m_indexOffset + numVisibleItems();
 
454
}
 
455
 
 
456
bool RenderListBox::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
 
457
{
 
458
    return m_vBar && m_vBar->scroll(direction, granularity, multiplier);
 
459
}
 
460
 
 
461
void RenderListBox::valueChanged(unsigned listIndex)
 
462
{
 
463
    HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
 
464
    select->setSelectedIndex(select->listToOptionIndex(listIndex));
 
465
    select->onChange();
 
466
}
 
467
 
 
468
void RenderListBox::valueChanged(Scrollbar*)
 
469
{
 
470
    int newOffset = m_vBar->value();
 
471
    if (newOffset != m_indexOffset) {
 
472
        m_indexOffset = newOffset;
 
473
        repaint();
 
474
        // Fire the scroll DOM event.
 
475
        EventTargetNodeCast(node())->dispatchHTMLEvent(scrollEvent, true, false);
 
476
    }
 
477
}
 
478
 
 
479
int RenderListBox::itemHeight() const
 
480
{
 
481
    return style()->font().height() + rowSpacing;
 
482
}
 
483
 
 
484
int RenderListBox::verticalScrollbarWidth() const
 
485
{
 
486
    return m_vBar ? m_vBar->width() : 0;
 
487
}
 
488
 
 
489
// FIXME: We ignore padding in the vertical direction as far as these values are concerned, since that's
 
490
// how the control currently paints.
 
491
int RenderListBox::scrollWidth() const
 
492
{
 
493
    // There is no horizontal scrolling allowed.
 
494
    return clientWidth();
 
495
}
 
496
 
 
497
int RenderListBox::scrollHeight() const
 
498
{
 
499
    return max(clientHeight(), listHeight());
 
500
}
 
501
 
 
502
int RenderListBox::scrollLeft() const
 
503
{
 
504
    return 0;
 
505
}
 
506
 
 
507
void RenderListBox::setScrollLeft(int)
 
508
{
 
509
}
 
510
 
 
511
int RenderListBox::scrollTop() const
 
512
{
 
513
    return m_indexOffset * itemHeight();
 
514
}
 
515
 
 
516
void RenderListBox::setScrollTop(int newTop)
 
517
{
 
518
    // Determine an index and scroll to it.    
 
519
    int index = newTop / itemHeight();
 
520
    if (index < 0 || index >= numItems() || index == m_indexOffset)
 
521
        return;
 
522
    m_indexOffset = index;
 
523
    if (m_vBar)
 
524
        m_vBar->setValue(index);
 
525
}
 
526
 
 
527
IntRect RenderListBox::controlClipRect(int tx, int ty) const
 
528
{
 
529
    IntRect clipRect = contentBox();
 
530
    clipRect.move(tx, ty);
 
531
    return clipRect;
 
532
}
 
533
 
 
534
IntRect RenderListBox::windowClipRect() const
 
535
{
 
536
    FrameView* frameView = view()->frameView();
 
537
    if (!frameView)
 
538
        return IntRect();
 
539
 
 
540
    return frameView->windowClipRectForLayer(enclosingLayer(), true);
 
541
}
 
542
 
 
543
bool RenderListBox::isScrollable() const
 
544
{
 
545
    if (numVisibleItems() < numItems())
 
546
        return true;
 
547
    return RenderObject::isScrollable();
 
548
}
 
549
 
 
550
} // namespace WebCore