void ScrollbarTheme::splitTrack(const ScrollbarThemeClient& scrollbar, const IntRect& unconstrainedTrackRect, IntRect& beforeThumbRect, IntRect& thumbRect, IntRect& afterThumbRect) { // This function won't even get called unless we're big enough to have some // combination of these three rects where at least one of them is non-empty. IntRect trackRect = constrainTrackRectToTrackPieces(scrollbar, unconstrainedTrackRect); int thumbPos = thumbPosition(scrollbar); if (scrollbar.orientation() == HorizontalScrollbar) { thumbRect = IntRect(trackRect.x() + thumbPos, trackRect.y(), thumbLength(scrollbar), scrollbar.height()); beforeThumbRect = IntRect(trackRect.x(), trackRect.y(), thumbPos + thumbRect.width() / 2, trackRect.height()); afterThumbRect = IntRect(trackRect.x() + beforeThumbRect.width(), trackRect.y(), trackRect.maxX() - beforeThumbRect.maxX(), trackRect.height()); } else { thumbRect = IntRect(trackRect.x(), trackRect.y() + thumbPos, scrollbar.width(), thumbLength(scrollbar)); beforeThumbRect = IntRect(trackRect.x(), trackRect.y(), trackRect.width(), thumbPos + thumbRect.height() / 2); afterThumbRect = IntRect(trackRect.x(), trackRect.y() + beforeThumbRect.height(), trackRect.width(), trackRect.maxY() - beforeThumbRect.maxY()); } }
int ScrollbarTheme::trackPosition(const ScrollbarThemeClient& scrollbar) { IntRect constrainedTrackRect = constrainTrackRectToTrackPieces(scrollbar, trackRect(scrollbar)); return (scrollbar.orientation() == HorizontalScrollbar) ? constrainedTrackRect.x() - scrollbar.x() : constrainedTrackRect.y() - scrollbar.y(); }
void ScrollbarThemeOverlay::paintThumb(GraphicsContext& context, const ScrollbarThemeClient& scrollbar, const IntRect& rect) { if (DrawingRecorder::useCachedDrawingIfPossible(context, scrollbar, DisplayItem::ScrollbarThumb)) return; DrawingRecorder recorder(context, scrollbar, DisplayItem::ScrollbarThumb, rect); IntRect thumbRect = rect; if (scrollbar.orientation() == HorizontalScrollbar) { thumbRect.setHeight(thumbRect.height() - m_scrollbarMargin); } else { thumbRect.setWidth(thumbRect.width() - m_scrollbarMargin); if (scrollbar.isLeftSideVerticalScrollbar()) thumbRect.setX(thumbRect.x() + m_scrollbarMargin); } if (m_useSolidColor) { context.fillRect(thumbRect, m_color); return; } WebThemeEngine::State state = WebThemeEngine::StateNormal; if (scrollbar.pressedPart() == ThumbPart) state = WebThemeEngine::StatePressed; else if (scrollbar.hoveredPart() == ThumbPart) state = WebThemeEngine::StateHover; WebCanvas* canvas = context.canvas(); WebThemeEngine::Part part = WebThemeEngine::PartScrollbarHorizontalThumb; if (scrollbar.orientation() == VerticalScrollbar) part = WebThemeEngine::PartScrollbarVerticalThumb; Platform::current()->themeEngine()->paint(canvas, part, state, WebRect(rect), 0); }
IntRect ScrollbarThemeOverlay::trackRect(const ScrollbarThemeClient& scrollbar, bool) { IntRect rect = scrollbar.frameRect(); if (scrollbar.orientation() == HorizontalScrollbar) rect.inflateX(-m_scrollbarMargin); else rect.inflateY(-m_scrollbarMargin); return rect; }
bool ScrollbarTheme::shouldSnapBackToDragOrigin( const ScrollbarThemeClient& scrollbar, const PlatformMouseEvent& evt) { IntPoint mousePosition = scrollbar.convertFromRootFrame(evt.position()); mousePosition.move(scrollbar.x(), scrollbar.y()); return Platform::current()->scrollbarBehavior()->shouldSnapBackToDragOrigin( mousePosition, trackRect(scrollbar), scrollbar.orientation() == HorizontalScrollbar); }
int ScrollbarThemeOverlay::thumbPosition(const ScrollbarThemeClient& scrollbar) { if (!scrollbar.totalSize()) return 0; int trackLen = trackLength(scrollbar); float proportion = static_cast<float>(scrollbar.currentPos()) / scrollbar.totalSize(); return round(proportion * trackLen); }
IntRect ScrollbarThemeAura::backButtonRect( const ScrollbarThemeClient& scrollbar, ScrollbarPart part, bool) { // Windows and Linux just have single arrows. if (part == BackButtonEndPart) return IntRect(); IntSize size = buttonSize(scrollbar); return IntRect(scrollbar.x(), scrollbar.y(), size.width(), size.height()); }
IntSize ScrollbarThemeAura::buttonSize(const ScrollbarThemeClient& scrollbar) { if (scrollbar.orientation() == VerticalScrollbar) { IntSize size = Platform::current()->themeEngine()->getSize(WebThemeEngine::PartScrollbarUpArrow); return IntSize(size.width(), scrollbar.height() < 2 * size.height() ? scrollbar.height() / 2 : size.height()); } // HorizontalScrollbar IntSize size = Platform::current()->themeEngine()->getSize(WebThemeEngine::PartScrollbarLeftArrow); return IntSize(scrollbar.width() < 2 * size.width() ? scrollbar.width() / 2 : size.width(), size.height()); }
int ScrollbarThemeOverlay::thumbLength(const ScrollbarThemeClient& scrollbar) { int trackLen = trackLength(scrollbar); if (!scrollbar.totalSize()) return trackLen; float proportion = static_cast<float>(scrollbar.visibleSize()) / scrollbar.totalSize(); int length = round(proportion * trackLen); int minLen = std::min(minimumThumbLength(scrollbar), trackLen); length = clampTo(length, minLen, trackLen); return length; }
int ScrollbarTheme::thumbPosition(const ScrollbarThemeClient& scrollbar, float scrollPosition) { if (scrollbar.enabled()) { float size = scrollbar.totalSize() - scrollbar.visibleSize(); // Avoid doing a floating point divide by zero and return 1 when // usedTotalSize == visibleSize. if (!size) return 0; float pos = std::max(0.0f, scrollPosition) * (trackLength(scrollbar) - thumbLength(scrollbar)) / size; return (pos < 1 && pos > 0) ? 1 : pos; } return 0; }
int ScrollbarTheme::trackLength(const ScrollbarThemeClient& scrollbar) { IntRect constrainedTrackRect = constrainTrackRectToTrackPieces(scrollbar, trackRect(scrollbar)); return (scrollbar.orientation() == HorizontalScrollbar) ? constrainedTrackRect.width() : constrainedTrackRect.height(); }
void ScrollbarThemeAura::paintThumb(GraphicsContext& gc, const ScrollbarThemeClient& scrollbar, const IntRect& rect) { if (DrawingRecorder::useCachedDrawingIfPossible(gc, scrollbar, DisplayItem::ScrollbarThumb)) return; DrawingRecorder recorder(gc, scrollbar, DisplayItem::ScrollbarThumb, rect); WebThemeEngine::State state; WebCanvas* canvas = gc.canvas(); if (scrollbar.pressedPart() == ThumbPart) state = WebThemeEngine::StatePressed; else if (scrollbar.hoveredPart() == ThumbPart) state = WebThemeEngine::StateHover; else state = WebThemeEngine::StateNormal; Platform::current()->themeEngine()->paint(canvas, scrollbar.orientation() == HorizontalScrollbar ? WebThemeEngine::PartScrollbarHorizontalThumb : WebThemeEngine::PartScrollbarVerticalThumb, state, WebRect(rect), 0); }
void ScrollbarThemeMock::paintTrackBackground(GraphicsContext& context, const ScrollbarThemeClient& scrollbar, const IntRect& trackRect) { if (DrawingRecorder::useCachedDrawingIfPossible(context, scrollbar, DisplayItem::ScrollbarTrackBackground)) return; DrawingRecorder recorder(context, scrollbar, DisplayItem::ScrollbarTrackBackground, trackRect); context.fillRect(trackRect, scrollbar.enabled() ? Color::lightGray : Color(0xFFE0E0E0)); }
int ScrollbarTheme::thumbLength(const ScrollbarThemeClient& scrollbar) { if (!scrollbar.enabled()) return 0; float overhang = fabsf(scrollbar.elasticOverscroll()); float proportion = 0.0f; float totalSize = scrollbar.totalSize(); if (totalSize > 0.0f) { proportion = (scrollbar.visibleSize() - overhang) / totalSize; } int trackLen = trackLength(scrollbar); int length = round(proportion * trackLen); length = std::max(length, minimumThumbLength(scrollbar)); if (length > trackLen) length = 0; // Once the thumb is below the track length, it just goes away // (to make more room for the track). return length; }
ScrollbarPart ScrollbarTheme::hitTest(const ScrollbarThemeClient& scrollbar, const IntPoint& positionInRootFrame) { ScrollbarPart result = NoPart; if (!scrollbar.enabled()) return result; IntPoint testPosition = scrollbar.convertFromRootFrame(positionInRootFrame); testPosition.move(scrollbar.x(), scrollbar.y()); if (!scrollbar.frameRect().contains(testPosition)) return NoPart; result = ScrollbarBGPart; IntRect track = trackRect(scrollbar); if (track.contains(testPosition)) { IntRect beforeThumbRect; IntRect thumbRect; IntRect afterThumbRect; splitTrack(scrollbar, track, beforeThumbRect, thumbRect, afterThumbRect); if (thumbRect.contains(testPosition)) result = ThumbPart; else if (beforeThumbRect.contains(testPosition)) result = BackTrackPart; else if (afterThumbRect.contains(testPosition)) result = ForwardTrackPart; else result = TrackBGPart; } else if (backButtonRect(scrollbar, BackButtonStartPart) .contains(testPosition)) { result = BackButtonStartPart; } else if (backButtonRect(scrollbar, BackButtonEndPart) .contains(testPosition)) { result = BackButtonEndPart; } else if (forwardButtonRect(scrollbar, ForwardButtonStartPart) .contains(testPosition)) { result = ForwardButtonStartPart; } else if (forwardButtonRect(scrollbar, ForwardButtonEndPart) .contains(testPosition)) { result = ForwardButtonEndPart; } return result; }
int ScrollbarThemeAura::minimumThumbLength(const ScrollbarThemeClient& scrollbar) { if (scrollbar.orientation() == VerticalScrollbar) { IntSize size = Platform::current()->themeEngine()->getSize(WebThemeEngine::PartScrollbarVerticalThumb); return size.height(); } IntSize size = Platform::current()->themeEngine()->getSize(WebThemeEngine::PartScrollbarHorizontalThumb); return size.width(); }
void ScrollbarThemeAura::paintButton(GraphicsContext& gc, const ScrollbarThemeClient& scrollbar, const IntRect& rect, ScrollbarPart part) { DisplayItem::Type displayItemType = buttonPartToDisplayItemType(part); if (DrawingRecorder::useCachedDrawingIfPossible(gc, scrollbar, displayItemType)) return; PartPaintingParams params = buttonPartPaintingParams(scrollbar, scrollbar.currentPos(), part); if (!params.shouldPaint) return; DrawingRecorder recorder(gc, scrollbar, displayItemType, rect); Platform::current()->themeEngine()->paint(gc.canvas(), params.part, params.state, WebRect(rect), 0); }
void ScrollbarThemeMock::paintThumb(GraphicsContext& context, const ScrollbarThemeClient& scrollbar, const IntRect& thumbRect) { if (!scrollbar.enabled()) return; if (DrawingRecorder::useCachedDrawingIfPossible(context, scrollbar, DisplayItem::ScrollbarThumb)) return; DrawingRecorder recorder(context, scrollbar, DisplayItem::ScrollbarThumb, thumbRect); context.fillRect(thumbRect, Color::darkGray); }
void ScrollbarThemeAura::paintTrackPiece(GraphicsContext& gc, const ScrollbarThemeClient& scrollbar, const IntRect& rect, ScrollbarPart partType) { DisplayItem::Type displayItemType = trackPiecePartToDisplayItemType(partType); if (DrawingRecorder::useCachedDrawingIfPossible(gc, scrollbar, displayItemType)) return; DrawingRecorder recorder(gc, scrollbar, displayItemType, rect); WebThemeEngine::State state = scrollbar.hoveredPart() == partType ? WebThemeEngine::StateHover : WebThemeEngine::StateNormal; if (useMockTheme() && !scrollbar.enabled()) state = WebThemeEngine::StateDisabled; IntRect alignRect = trackRect(scrollbar, false); WebThemeEngine::ExtraParams extraParams; extraParams.scrollbarTrack.isBack = (partType == BackTrackPart); extraParams.scrollbarTrack.trackX = alignRect.x(); extraParams.scrollbarTrack.trackY = alignRect.y(); extraParams.scrollbarTrack.trackWidth = alignRect.width(); extraParams.scrollbarTrack.trackHeight = alignRect.height(); Platform::current()->themeEngine()->paint(gc.canvas(), scrollbar.orientation() == HorizontalScrollbar ? WebThemeEngine::PartScrollbarHorizontalTrack : WebThemeEngine::PartScrollbarVerticalTrack, state, WebRect(rect), &extraParams); }
IntSize ScrollbarThemeAura::buttonSize(const ScrollbarThemeClient& scrollbar) { if (!hasScrollbarButtons(scrollbar.orientation())) return IntSize(0, 0); if (scrollbar.orientation() == VerticalScrollbar) { int squareSize = scrollbar.width(); return IntSize(squareSize, scrollbar.height() < 2 * squareSize ? scrollbar.height() / 2 : squareSize); } // HorizontalScrollbar int squareSize = scrollbar.height(); return IntSize( scrollbar.width() < 2 * squareSize ? scrollbar.width() / 2 : squareSize, squareSize); }
IntRect ScrollbarThemeAura::forwardButtonRect( const ScrollbarThemeClient& scrollbar, ScrollbarPart part, bool) { // Windows and Linux just have single arrows. if (part == ForwardButtonStartPart) return IntRect(); IntSize size = buttonSize(scrollbar); int x, y; if (scrollbar.orientation() == HorizontalScrollbar) { x = scrollbar.x() + scrollbar.width() - size.width(); y = scrollbar.y(); } else { x = scrollbar.x(); y = scrollbar.y() + scrollbar.height() - size.height(); } return IntRect(x, y, size.width(), size.height()); }
IntRect ScrollbarThemeAura::trackRect(const ScrollbarThemeClient& scrollbar, bool) { // The track occupies all space between the two buttons. IntSize bs = buttonSize(scrollbar); if (scrollbar.orientation() == HorizontalScrollbar) { if (scrollbar.width() <= 2 * bs.width()) return IntRect(); return IntRect(scrollbar.x() + bs.width(), scrollbar.y(), scrollbar.width() - 2 * bs.width(), scrollbar.height()); } if (scrollbar.height() <= 2 * bs.height()) return IntRect(); return IntRect(scrollbar.x(), scrollbar.y() + bs.height(), scrollbar.width(), scrollbar.height() - 2 * bs.height()); }
IntRect ScrollbarThemeMock::trackRect(const ScrollbarThemeClient& scrollbar, bool) { return scrollbar.frameRect(); }
int ScrollbarTheme::thumbThickness(const ScrollbarThemeClient& scrollbar) { IntRect track = trackRect(scrollbar); return scrollbar.orientation() == HorizontalScrollbar ? track.height() : track.width(); }
int ScrollbarTheme::minimumThumbLength(const ScrollbarThemeClient& scrollbar) { return scrollbarThickness(scrollbar.controlSize()); }