ScrollViewWin.cpp 7.28 KB
Newer Older
1
2
/*
 * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
3
 * Copyright (C) 2006 Justin Haygood <jhaygood@spsu.edu>.
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#include "config.h"
#include "ScrollView.h"
29
30

#include <algorithm>
31
32
#include "FloatRect.h"
#include "IntRect.h"
33
34
#include <windows.h>

35
36
using namespace std;

37
38
namespace WebCore {

39
40
41
42
43
44
45
46
47
class ScrollView::ScrollViewPrivate {
public:
    ScrollViewPrivate()
        : hasStaticBackground(false)
        , suppressScrollBars(false)
        , vScrollBarMode(ScrollBarAuto)
        , hScrollBarMode(ScrollBarAuto)
    {
    }
mjs's avatar
mjs committed
48
    IntSize scrollOffset;
49
50
51
52
53
54
55
56
57
58
59
60
61
    IntSize contentsSize;
    bool hasStaticBackground;
    bool suppressScrollBars;
    ScrollBarMode vScrollBarMode;
    ScrollBarMode hScrollBarMode;
};

ScrollView::ScrollView()
    : m_data(new ScrollViewPrivate())
{
}

ScrollView::~ScrollView()
62
{
63
64
65
66
67
    delete m_data;
}

void ScrollView::updateContents(const IntRect& updateRect, bool now)
{
68
    IntRect adjustedDirtyRect(updateRect);
mjs's avatar
mjs committed
69
    adjustedDirtyRect.move(-m_data->scrollOffset);
70
71
72

    RECT dirtyRect = RECT(adjustedDirtyRect);
#if PAINT_FLASHING_DEBUG
ggaren's avatar
ggaren committed
73
    HDC dc = GetDC(containingWindow());
74
    FillRect(dc, &dirtyRect, (HBRUSH)GetStockObject(BLACK_BRUSH));
ggaren's avatar
ggaren committed
75
    ReleaseDC(containingWindow(), dc);
76
77
#endif

ggaren's avatar
ggaren committed
78
    InvalidateRect(containingWindow(), &dirtyRect, true);
79
    if (now)
ggaren's avatar
ggaren committed
80
        UpdateWindow(containingWindow());
81
82
}

83
84
85
int ScrollView::visibleWidth() const
{
    RECT bounds;
ggaren's avatar
ggaren committed
86
    GetClientRect(containingWindow(), &bounds);
87
88
89
90
91
92
    return (bounds.right - bounds.left);
}

int ScrollView::visibleHeight() const
{
    RECT bounds;
ggaren's avatar
ggaren committed
93
    GetClientRect(containingWindow(), &bounds);
94
95
96
    return (bounds.bottom - bounds.top);
}

97
98
99
FloatRect ScrollView::visibleContentRect() const
{
    RECT bounds;
ggaren's avatar
ggaren committed
100
    GetClientRect(containingWindow(), &bounds);
101
    FloatRect contentRect = bounds;
mjs's avatar
mjs committed
102
    contentRect.move(m_data->scrollOffset);
103
104
105
    return contentRect;
}

106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
void ScrollView::setContentsPos(int newX, int newY)
{
    int dx = newX - contentsX();
    int dy = newY - contentsY();
    scrollBy(dx, dy);
}

void ScrollView::resizeContents(int w,int h)
{
    IntSize newSize(w,h);
    if (m_data->contentsSize != newSize) {
        m_data->contentsSize = newSize;
        updateScrollBars();
    }    
}

int ScrollView::contentsX() const
{
mjs's avatar
mjs committed
124
    return scrollOffset().width();
125
126
127
128
}

int ScrollView::contentsY() const
{
mjs's avatar
mjs committed
129
    return scrollOffset().height();
130
131
132
133
134
135
136
137
138
139
140
141
}

int ScrollView::contentsWidth() const
{
    return m_data->contentsSize.width();
}

int ScrollView::contentsHeight() const
{
    return m_data->contentsSize.height();
}

142
IntPoint ScrollView::convertToContainingWindow(const IntPoint& point) const
143
{
adele's avatar
adele committed
144
    return point - scrollOffset();
145
146
}

147
IntPoint ScrollView::convertFromContainingWindow(const IntPoint& point) const
148
{
adele's avatar
adele committed
149
    return point + scrollOffset();
150
151
}

152
IntSize ScrollView::scrollOffset() const
153
{
mjs's avatar
mjs committed
154
    return m_data->scrollOffset;
155
156
}

mjs's avatar
mjs committed
157
IntSize ScrollView::maximumScroll() const
158
{
mjs's avatar
mjs committed
159
160
161
    IntSize delta = m_data->contentsSize - m_data->scrollOffset;
    delta.clampNegativeToZero();
    return delta;
162
163
164
165
}

void ScrollView::scrollBy(int dx, int dy)
{
mjs's avatar
mjs committed
166
167
    IntSize scrollOffset = m_data->scrollOffset;
    IntSize maxScroll = maximumScroll();
168
    IntSize newScrollOffset = scrollOffset + IntSize(dx, dy);
mjs's avatar
mjs committed
169
170
    newScrollOffset.clampNegativeToZero();

171
    if (newScrollOffset != scrollOffset) {
mjs's avatar
mjs committed
172
        m_data->scrollOffset = newScrollOffset;
173
174
        updateScrollBars();
        // ScrollBar updates can fail, so we check the final delta before scrolling
mjs's avatar
mjs committed
175
176
        IntSize scrollDelta = m_data->scrollOffset - scrollOffset;
        if (scrollDelta == IntSize())
177
178
179
            return;
        if (!m_data->hasStaticBackground)
            // FIXME: This could be made more efficient by passing a valid clip rect for only the document content.
ggaren's avatar
ggaren committed
180
            ScrollWindowEx(containingWindow(), -scrollDelta.width(), -scrollDelta.height(), 0, 0, 0, 0, SW_INVALIDATE);
181
        else
ggaren's avatar
ggaren committed
182
            InvalidateRect(containingWindow(), 0, true);
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
    }
}

WebCore::ScrollBarMode ScrollView::hScrollBarMode() const
{
    return m_data->hScrollBarMode;
}

WebCore::ScrollBarMode ScrollView::vScrollBarMode() const
{
    return m_data->vScrollBarMode;
}

void ScrollView::suppressScrollBars(bool suppressed, bool repaintOnSuppress)
{
    m_data->suppressScrollBars = suppressed;
    if (repaintOnSuppress)
        updateScrollBars();
}

void ScrollView::setHScrollBarMode(ScrollBarMode newMode)
{
    if (m_data->hScrollBarMode != newMode) {
        m_data->hScrollBarMode = newMode;
        updateScrollBars();
    }
}

void ScrollView::setVScrollBarMode(ScrollBarMode newMode)
{
    if (m_data->vScrollBarMode != newMode) {
        m_data->vScrollBarMode = newMode;
        updateScrollBars();
    }
}

void ScrollView::setScrollBarsMode(ScrollBarMode newMode)
{
    m_data->hScrollBarMode = m_data->vScrollBarMode = newMode;
    updateScrollBars();
}

void ScrollView::setStaticBackground(bool flag)
{
    m_data->hasStaticBackground = flag;
}

int ScrollView::updateScrollInfo(short type, int current, int max, int pageSize)
{
    SCROLLINFO si;
    si.cbSize = sizeof(si);
    si.fMask  = SIF_RANGE | SIF_PAGE | SIF_POS;
    si.nMin   = 0;
    si.nMax   = max;
    si.nPage  = pageSize;
    si.nPos   = current;
ggaren's avatar
ggaren committed
239
240
    SetScrollInfo(containingWindow(), type, &si, TRUE);
    GetScrollInfo(containingWindow(), type, &si);
241
242
243
244
245
    return si.nPos;
}

void ScrollView::updateScrollBars()
{ 
246
247
    IntSize maxScrollPosition(contentsWidth(), contentsHeight());
    IntSize scroll = scrollOffset().shrunkTo(maxScrollPosition);
mjs's avatar
mjs committed
248
    scroll.clampNegativeToZero();
249

mjs's avatar
mjs committed
250
251
252
    m_data->scrollOffset = 
        IntSize(updateScrollInfo(SB_HORZ, scroll.width(), contentsWidth() - 1, width()),
                updateScrollInfo(SB_VERT, scroll.height(), contentsHeight() - 1, height()));
253
254

    if (m_data->hScrollBarMode != ScrollBarAuto || m_data->suppressScrollBars)
ggaren's avatar
ggaren committed
255
        ShowScrollBar(containingWindow(), SB_HORZ, (m_data->hScrollBarMode != ScrollBarAlwaysOff) && !m_data->suppressScrollBars);
256
    if (m_data->vScrollBarMode != ScrollBarAuto || m_data->suppressScrollBars)
ggaren's avatar
ggaren committed
257
        ShowScrollBar(containingWindow(), SB_VERT, (m_data->vScrollBarMode != ScrollBarAlwaysOff) && !m_data->suppressScrollBars);
258
259
260
}

}