18febec3981085191ab70c061f19936291864c8e
[WebKit-https.git] / WebKit / WebView.subproj / WebDynamicScrollBarsView.m
1 //
2 //  WebDynamicScrollBarsView.m
3 //  WebKit
4 //
5 //  Created by John Sullivan on Tue Jan 22 2002.
6 //  Copyright (c) 2001, 2002 Apple Computer, Inc. All rights reserved.
7 //
8
9 #import <WebKit/WebDynamicScrollBarsView.h>
10
11 #import <WebKit/WebDocument.h>
12
13 @implementation WebDynamicScrollBarsView
14
15 - (void)setSuppressLayout: (BOOL)flag;
16 {
17     suppressLayout = flag;
18 }
19
20 - (void)setScrollBarsSuppressed:(BOOL)suppressed repaintOnUnsuppress:(BOOL)repaint
21 {
22     suppressScrollers = suppressed;
23     if (suppressed || repaint) {
24         [[self verticalScroller] setNeedsDisplay: !suppressed];
25         [[self horizontalScroller] setNeedsDisplay: !suppressed];
26     }
27 }
28
29 - (void)updateScrollers
30 {
31     // We need to do the work below twice in the case where a scroll bar disappears,
32     // making the second layout have a wider width than the first. Doing it more than
33     // twice would indicate some kind of infinite loop, so we do it at most twice.
34     // It's quite efficient to do this work twice in the normal case, so we don't bother
35     // trying to figure out of the second pass is needed or not.
36     
37     int pass;
38     BOOL hasVerticalScroller = [self hasVerticalScroller];
39     BOOL hasHorizontalScroller = [self hasHorizontalScroller];
40     BOOL oldHasVertical = hasVerticalScroller;
41     BOOL oldHasHorizontal = hasHorizontalScroller;
42
43     for (pass = 0; pass < 2; pass++) {
44         BOOL scrollsVertically;
45         BOOL scrollsHorizontally;
46
47         if (!suppressLayout && !suppressScrollers &&
48             (hScroll == WebCoreScrollBarAuto || vScroll == WebCoreScrollBarAuto))
49         {
50             // Do a layout if pending, before checking if scrollbars are needed.
51             // This fixes 2969367, although may introduce a slowdown in live resize performance.
52             NSView *documentView = [self documentView];
53             if ((hasVerticalScroller != oldHasVertical ||
54                 hasHorizontalScroller != oldHasHorizontal || [documentView inLiveResize]) && [documentView conformsToProtocol:@protocol(WebDocumentView)]) {
55                 [(id <WebDocumentView>)documentView setNeedsLayout: YES];
56                 [(id <WebDocumentView>)documentView layout];
57             }
58             
59             NSSize documentSize = [documentView frame].size;
60             NSSize frameSize = [self frame].size;
61             
62             scrollsVertically = (vScroll == WebCoreScrollBarAlwaysOn) ||
63                 (vScroll == WebCoreScrollBarAuto && documentSize.height > frameSize.height);
64             if (scrollsVertically)
65                 scrollsHorizontally = (hScroll == WebCoreScrollBarAlwaysOn) ||
66                     (hScroll == WebCoreScrollBarAuto && documentSize.width + [NSScroller scrollerWidth] > frameSize.width);
67             else {
68                 scrollsHorizontally = (hScroll == WebCoreScrollBarAlwaysOn) ||
69                     (hScroll == WebCoreScrollBarAuto && documentSize.width > frameSize.width);
70                 if (scrollsHorizontally)
71                     scrollsVertically = (vScroll == WebCoreScrollBarAlwaysOn) ||
72                         (vScroll == WebCoreScrollBarAuto && documentSize.height + [NSScroller scrollerWidth] > frameSize.height);
73             }
74         }
75         else {
76             scrollsHorizontally = (hScroll == WebCoreScrollBarAuto) ? hasHorizontalScroller : (hScroll == WebCoreScrollBarAlwaysOn);
77             scrollsVertically = (vScroll == WebCoreScrollBarAuto) ? hasVerticalScroller : (vScroll == WebCoreScrollBarAlwaysOn);
78         }
79         
80         if (hasVerticalScroller != scrollsVertically) {
81             [self setHasVerticalScroller:scrollsVertically];
82             hasVerticalScroller = scrollsVertically;
83         }
84
85         if (hasHorizontalScroller != scrollsHorizontally) {
86             [self setHasHorizontalScroller:scrollsHorizontally];
87             hasHorizontalScroller = scrollsHorizontally;
88         }
89     }
90
91     if (suppressScrollers) {
92         [[self verticalScroller] setNeedsDisplay: NO];
93         [[self horizontalScroller] setNeedsDisplay: NO];
94     }
95 }
96
97 // Make the horizontal and vertical scroll bars come and go as needed.
98 - (void)reflectScrolledClipView:(NSClipView *)clipView
99 {
100     if (clipView == [self contentView]) {
101         // FIXME: This hack here prevents infinite recursion that takes place when we
102         // gyrate between having a vertical scroller and not having one. A reproducible
103         // case is clicking on the "the Policy Routing text" link at
104         // http://www.linuxpowered.com/archive/howto/Net-HOWTO-8.html.
105         // The underlying cause is some problem in the NSText machinery, but I was not
106         // able to pin it down.
107         if (!inUpdateScrollers && [[NSGraphicsContext currentContext] isDrawingToScreen]) {
108             inUpdateScrollers = YES;
109             [self updateScrollers];
110             inUpdateScrollers = NO;
111         }
112     }
113     [super reflectScrolledClipView:clipView];
114
115     // Validate the scrollers if they're being suppressed.
116     if (suppressScrollers) {
117         [[self verticalScroller] setNeedsDisplay: NO];
118         [[self horizontalScroller] setNeedsDisplay: NO];
119     }
120 }
121
122 - (void)setAllowsScrolling:(BOOL)flag
123 {
124     hScroll = vScroll = (flag ? WebCoreScrollBarAuto : WebCoreScrollBarAlwaysOff);
125     [self updateScrollers];
126 }
127
128 - (BOOL)allowsScrolling
129 {
130     return hScroll != WebCoreScrollBarAlwaysOff && vScroll != WebCoreScrollBarAlwaysOff;
131 }
132
133 - (void)setAllowsHorizontalScrolling:(BOOL)flag
134 {
135     hScroll = (flag ? WebCoreScrollBarAuto : WebCoreScrollBarAlwaysOff);
136     [self updateScrollers];
137 }
138
139 - (void)setAllowsVerticalScrolling:(BOOL)flag
140 {
141     vScroll = (flag ? WebCoreScrollBarAuto : WebCoreScrollBarAlwaysOff);
142     [self updateScrollers];
143 }
144
145 - (BOOL)allowsHorizontalScrolling
146 {
147     return hScroll != WebCoreScrollBarAlwaysOff;
148 }
149
150 - (BOOL)allowsVerticalScrolling
151 {
152     return vScroll != WebCoreScrollBarAlwaysOff;
153 }
154
155 -(WebCoreScrollBarMode)horizontalScrollingMode
156 {
157     return hScroll;
158 }
159
160 -(WebCoreScrollBarMode)verticalScrollingMode
161 {
162     return vScroll;
163 }
164
165 - (void)setHorizontalScrollingMode:(WebCoreScrollBarMode)mode
166 {
167     if (mode == hScroll)
168         return;
169     hScroll = mode;
170     [self updateScrollers];
171 }
172
173 - (void)setVerticalScrollingMode:(WebCoreScrollBarMode)mode
174 {
175     if (mode == vScroll)
176         return;
177     vScroll = mode;
178     [self updateScrollers];
179 }
180
181 - (void)setScrollingMode:(WebCoreScrollBarMode)mode
182 {
183     if (mode == vScroll && mode == hScroll)
184         return;
185     vScroll = hScroll = mode;
186     [self updateScrollers];
187 }
188 @end