1 /* 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 #include "platform/scroll/ScrollbarThemeMacOverlayAPI.h" 33 34 #include "platform/graphics/GraphicsContext.h" 35 #include "platform/graphics/GraphicsContextStateSaver.h" 36 #include "platform/mac/LocalCurrentGraphicsContext.h" 37 #include "platform/mac/NSScrollerImpDetails.h" 38 #include "platform/scroll/ScrollbarThemeClient.h" 39 40 namespace blink { 41 42 typedef HashMap<ScrollbarThemeClient*, RetainPtr<ScrollbarPainter> > ScrollbarPainterMap; 43 44 static ScrollbarPainterMap* scrollbarPainterMap() 45 { 46 static ScrollbarPainterMap* map = new ScrollbarPainterMap; 47 return map; 48 } 49 50 static bool supportsExpandedScrollbars() 51 { 52 // FIXME: This is temporary until all platforms that support ScrollbarPainter support this part of the API. 53 static bool globalSupportsExpandedScrollbars = [NSClassFromString(@"NSScrollerImp") instancesRespondToSelector:@selector(setExpanded:)]; 54 return globalSupportsExpandedScrollbars; 55 } 56 57 void ScrollbarThemeMacOverlayAPI::registerScrollbar(ScrollbarThemeClient* scrollbar) 58 { 59 ScrollbarThemeMacCommon::registerScrollbar(scrollbar); 60 61 bool isHorizontal = scrollbar->orientation() == HorizontalScrollbar; 62 ScrollbarPainter scrollbarPainter = [NSClassFromString(@"NSScrollerImp") scrollerImpWithStyle:recommendedScrollerStyle() controlSize:(NSControlSize)scrollbar->controlSize() horizontal:isHorizontal replacingScrollerImp:nil]; 63 scrollbarPainterMap()->add(scrollbar, scrollbarPainter); 64 updateEnabledState(scrollbar); 65 updateScrollbarOverlayStyle(scrollbar); 66 } 67 68 void ScrollbarThemeMacOverlayAPI::unregisterScrollbar(ScrollbarThemeClient* scrollbar) 69 { 70 scrollbarPainterMap()->remove(scrollbar); 71 72 ScrollbarThemeMacCommon::unregisterScrollbar(scrollbar); 73 } 74 75 void ScrollbarThemeMacOverlayAPI::setNewPainterForScrollbar(ScrollbarThemeClient* scrollbar, ScrollbarPainter newPainter) 76 { 77 scrollbarPainterMap()->set(scrollbar, newPainter); 78 updateEnabledState(scrollbar); 79 updateScrollbarOverlayStyle(scrollbar); 80 } 81 82 ScrollbarPainter ScrollbarThemeMacOverlayAPI::painterForScrollbar(ScrollbarThemeClient* scrollbar) 83 { 84 return scrollbarPainterMap()->get(scrollbar).get(); 85 } 86 87 void ScrollbarThemeMacOverlayAPI::paintTrackBackground(GraphicsContext* context, ScrollbarThemeClient* scrollbar, const IntRect& rect) { 88 ASSERT(isOverlayAPIAvailable()); 89 90 GraphicsContextStateSaver stateSaver(*context); 91 context->translate(rect.x(), rect.y()); 92 LocalCurrentGraphicsContext localContext(context, IntRect(IntPoint(), rect.size())); 93 94 CGRect frameRect = scrollbar->frameRect(); 95 ScrollbarPainter scrollbarPainter = painterForScrollbar(scrollbar); 96 [scrollbarPainter setEnabled:scrollbar->enabled()]; 97 [scrollbarPainter setBoundsSize: NSSizeFromCGSize(frameRect.size)]; 98 99 NSRect trackRect = NSMakeRect(0, 0, frameRect.size.width, frameRect.size.height); 100 [scrollbarPainter drawKnobSlotInRect:trackRect highlight:NO]; 101 } 102 103 void ScrollbarThemeMacOverlayAPI::paintThumb(GraphicsContext* context, ScrollbarThemeClient* scrollbar, const IntRect& rect) { 104 ASSERT(isOverlayAPIAvailable()); 105 106 GraphicsContextStateSaver stateSaver(*context); 107 context->translate(rect.x(), rect.y()); 108 LocalCurrentGraphicsContext localContext(context, IntRect(IntPoint(), rect.size())); 109 110 ScrollbarPainter scrollbarPainter = painterForScrollbar(scrollbar); 111 [scrollbarPainter setEnabled:scrollbar->enabled()]; 112 [scrollbarPainter setBoundsSize:NSSizeFromCGSize(rect.size())]; 113 [scrollbarPainter setDoubleValue:0]; 114 [scrollbarPainter setKnobProportion:1]; 115 if (scrollbar->enabled()) 116 [scrollbarPainter drawKnob]; 117 118 // If this state is not set, then moving the cursor over the scrollbar area will only cause the 119 // scrollbar to engorge when moved over the top of the scrollbar area. 120 [scrollbarPainter setBoundsSize: NSSizeFromCGSize(scrollbar->frameRect().size())]; 121 } 122 123 int ScrollbarThemeMacOverlayAPI::scrollbarThickness(ScrollbarControlSize controlSize) 124 { 125 ScrollbarPainter scrollbarPainter = [NSClassFromString(@"NSScrollerImp") scrollerImpWithStyle:recommendedScrollerStyle() controlSize:controlSize horizontal:NO replacingScrollerImp:nil]; 126 if (supportsExpandedScrollbars()) 127 [scrollbarPainter setExpanded:YES]; 128 return [scrollbarPainter trackBoxWidth]; 129 } 130 131 bool ScrollbarThemeMacOverlayAPI::usesOverlayScrollbars() const 132 { 133 return recommendedScrollerStyle() == NSScrollerStyleOverlay; 134 } 135 136 void ScrollbarThemeMacOverlayAPI::updateScrollbarOverlayStyle(ScrollbarThemeClient* scrollbar) 137 { 138 ScrollbarPainter painter = painterForScrollbar(scrollbar); 139 switch (scrollbar->scrollbarOverlayStyle()) { 140 case ScrollbarOverlayStyleDefault: 141 [painter setKnobStyle:NSScrollerKnobStyleDefault]; 142 break; 143 case ScrollbarOverlayStyleDark: 144 [painter setKnobStyle:NSScrollerKnobStyleDark]; 145 break; 146 case ScrollbarOverlayStyleLight: 147 [painter setKnobStyle:NSScrollerKnobStyleLight]; 148 break; 149 } 150 } 151 152 ScrollbarButtonsPlacement ScrollbarThemeMacOverlayAPI::buttonsPlacement() const 153 { 154 return ScrollbarButtonsNone; 155 } 156 157 bool ScrollbarThemeMacOverlayAPI::hasThumb(ScrollbarThemeClient* scrollbar) 158 { 159 ScrollbarPainter painter = painterForScrollbar(scrollbar); 160 int minLengthForThumb = [painter knobMinLength] + [painter trackOverlapEndInset] + [painter knobOverlapEndInset] 161 + 2 * ([painter trackEndInset] + [painter knobEndInset]); 162 return scrollbar->enabled() && (scrollbar->orientation() == HorizontalScrollbar ? 163 scrollbar->width() : 164 scrollbar->height()) >= minLengthForThumb; 165 } 166 167 IntRect ScrollbarThemeMacOverlayAPI::backButtonRect(ScrollbarThemeClient* scrollbar, ScrollbarPart part, bool painting) 168 { 169 ASSERT(buttonsPlacement() == ScrollbarButtonsNone); 170 return IntRect(); 171 } 172 173 IntRect ScrollbarThemeMacOverlayAPI::forwardButtonRect(ScrollbarThemeClient* scrollbar, ScrollbarPart part, bool painting) 174 { 175 ASSERT(buttonsPlacement() == ScrollbarButtonsNone); 176 return IntRect(); 177 } 178 179 IntRect ScrollbarThemeMacOverlayAPI::trackRect(ScrollbarThemeClient* scrollbar, bool painting) 180 { 181 ASSERT(!hasButtons(scrollbar)); 182 return scrollbar->frameRect(); 183 } 184 185 int ScrollbarThemeMacOverlayAPI::minimumThumbLength(ScrollbarThemeClient* scrollbar) 186 { 187 return [painterForScrollbar(scrollbar) knobMinLength]; 188 } 189 190 void ScrollbarThemeMacOverlayAPI::updateEnabledState(ScrollbarThemeClient* scrollbar) 191 { 192 [painterForScrollbar(scrollbar) setEnabled:scrollbar->enabled()]; 193 } 194 195 } // namespace blink 196