ScrollbarThemeGtk.cpp [plain text]
#include "config.h"
#include "ScrollbarThemeGtk.h"
#include "PlatformMouseEvent.h"
#include "RenderThemeGtk.h"
#include "ScrollView.h"
#include "Scrollbar.h"
namespace WebCore {
static HashSet<Scrollbar*>* gScrollbars;
ScrollbarTheme* ScrollbarTheme::nativeTheme()
{
static ScrollbarThemeGtk theme;
return &theme;
}
ScrollbarThemeGtk::~ScrollbarThemeGtk()
{
}
void ScrollbarThemeGtk::registerScrollbar(Scrollbar* scrollbar)
{
if (!gScrollbars)
gScrollbars = new HashSet<Scrollbar*>;
gScrollbars->add(scrollbar);
}
void ScrollbarThemeGtk::unregisterScrollbar(Scrollbar* scrollbar)
{
gScrollbars->remove(scrollbar);
if (gScrollbars->isEmpty()) {
delete gScrollbars;
gScrollbars = 0;
}
}
void ScrollbarThemeGtk::updateScrollbarsFrameThickness()
{
if (!gScrollbars)
return;
HashSet<Scrollbar*>::iterator end = gScrollbars->end();
for (HashSet<Scrollbar*>::iterator it = gScrollbars->begin(); it != end; ++it) {
Scrollbar* scrollbar = (*it);
if (!scrollbar->parent() || !scrollbar->parent()->parent())
return;
int thickness = scrollbarThickness(scrollbar->controlSize());
if (scrollbar->orientation() == HorizontalScrollbar)
scrollbar->setFrameRect(IntRect(0, scrollbar->parent()->height() - thickness, scrollbar->width(), thickness));
else
scrollbar->setFrameRect(IntRect(scrollbar->parent()->width() - thickness, 0, thickness, scrollbar->height()));
}
}
bool ScrollbarThemeGtk::hasThumb(Scrollbar* scrollbar)
{
return thumbLength(scrollbar) > 0;
}
IntRect ScrollbarThemeGtk::backButtonRect(Scrollbar* scrollbar, ScrollbarPart part, bool)
{
if (part == BackButtonEndPart && !m_hasBackButtonEndPart)
return IntRect();
int x = scrollbar->x() + m_troughBorderWidth;
int y = scrollbar->y() + m_troughBorderWidth;
IntSize size = buttonSize(scrollbar);
if (part == BackButtonStartPart)
return IntRect(x, y, size.width(), size.height());
if (scrollbar->orientation() == HorizontalScrollbar)
return IntRect(scrollbar->x() + scrollbar->width() - m_troughBorderWidth - (2 * size.width()), y, size.width(), size.height());
return IntRect(x, scrollbar->y() + scrollbar->height() - m_troughBorderWidth - (2 * size.height()), size.width(), size.height());
}
IntRect ScrollbarThemeGtk::forwardButtonRect(Scrollbar* scrollbar, ScrollbarPart part, bool)
{
if (part == ForwardButtonStartPart && !m_hasForwardButtonStartPart)
return IntRect();
IntSize size = buttonSize(scrollbar);
if (scrollbar->orientation() == HorizontalScrollbar) {
int y = scrollbar->y() + m_troughBorderWidth;
if (part == ForwardButtonEndPart)
return IntRect(scrollbar->x() + scrollbar->width() - size.width() - m_troughBorderWidth, y, size.width(), size.height());
return IntRect(scrollbar->x() + m_troughBorderWidth + size.width(), y, size.width(), size.height());
}
int x = scrollbar->x() + m_troughBorderWidth;
if (part == ForwardButtonEndPart)
return IntRect(x, scrollbar->y() + scrollbar->height() - size.height() - m_troughBorderWidth, size.width(), size.height());
return IntRect(x, scrollbar->y() + m_troughBorderWidth + size.height(), size.width(), size.height());
}
IntRect ScrollbarThemeGtk::trackRect(Scrollbar* scrollbar, bool)
{
int movementAxisPadding = m_troughBorderWidth + m_stepperSize + m_stepperSpacing;
int thickness = scrollbarThickness(scrollbar->controlSize());
int alternateButtonOffset = 0;
int alternateButtonWidth = 0;
if (m_hasForwardButtonStartPart) {
alternateButtonOffset += m_stepperSize;
alternateButtonWidth += m_stepperSize;
}
if (m_hasBackButtonEndPart)
alternateButtonWidth += m_stepperSize;
if (scrollbar->orientation() == HorizontalScrollbar) {
if (scrollbar->width() < 2 * thickness)
return IntRect();
return IntRect(scrollbar->x() + movementAxisPadding + alternateButtonOffset, scrollbar->y(),
scrollbar->width() - (2 * movementAxisPadding) - alternateButtonWidth, thickness);
}
if (scrollbar->height() < 2 * thickness)
return IntRect();
return IntRect(scrollbar->x(), scrollbar->y() + movementAxisPadding + alternateButtonOffset,
thickness, scrollbar->height() - (2 * movementAxisPadding) - alternateButtonWidth);
}
IntRect ScrollbarThemeGtk::thumbRect(Scrollbar* scrollbar, const IntRect& unconstrainedTrackRect)
{
IntRect trackRect = constrainTrackRectToTrackPieces(scrollbar, unconstrainedTrackRect);
int thumbPos = thumbPosition(scrollbar);
if (scrollbar->orientation() == HorizontalScrollbar)
return IntRect(trackRect.x() + thumbPos, trackRect.y() + (trackRect.height() - m_thumbFatness) / 2, thumbLength(scrollbar), m_thumbFatness);
return IntRect(trackRect.x() + (trackRect.width() - m_thumbFatness) / 2, trackRect.y() + thumbPos, m_thumbFatness, thumbLength(scrollbar));
}
bool ScrollbarThemeGtk::paint(Scrollbar* scrollbar, GraphicsContext* graphicsContext, const IntRect& damageRect)
{
if (graphicsContext->paintingDisabled())
return false;
ScrollbarControlPartMask scrollMask = NoPart;
IntRect backButtonStartPaintRect;
IntRect backButtonEndPaintRect;
IntRect forwardButtonStartPaintRect;
IntRect forwardButtonEndPaintRect;
if (hasButtons(scrollbar)) {
backButtonStartPaintRect = backButtonRect(scrollbar, BackButtonStartPart, true);
if (damageRect.intersects(backButtonStartPaintRect))
scrollMask |= BackButtonStartPart;
backButtonEndPaintRect = backButtonRect(scrollbar, BackButtonEndPart, true);
if (damageRect.intersects(backButtonEndPaintRect))
scrollMask |= BackButtonEndPart;
forwardButtonStartPaintRect = forwardButtonRect(scrollbar, ForwardButtonStartPart, true);
if (damageRect.intersects(forwardButtonStartPaintRect))
scrollMask |= ForwardButtonStartPart;
forwardButtonEndPaintRect = forwardButtonRect(scrollbar, ForwardButtonEndPart, true);
if (damageRect.intersects(forwardButtonEndPaintRect))
scrollMask |= ForwardButtonEndPart;
}
IntRect trackPaintRect = trackRect(scrollbar, true);
if (damageRect.intersects(trackPaintRect))
scrollMask |= TrackBGPart;
if (m_troughUnderSteppers && (scrollMask & BackButtonStartPart
|| scrollMask & BackButtonEndPart
|| scrollMask & ForwardButtonStartPart
|| scrollMask & ForwardButtonEndPart))
scrollMask |= TrackBGPart;
bool thumbPresent = hasThumb(scrollbar);
IntRect currentThumbRect;
if (thumbPresent) {
IntRect track = trackRect(scrollbar, false);
currentThumbRect = thumbRect(scrollbar, track);
if (damageRect.intersects(currentThumbRect))
scrollMask |= ThumbPart;
}
ScrollbarControlPartMask allButtons = BackButtonStartPart | BackButtonEndPart
| ForwardButtonStartPart | ForwardButtonEndPart;
if (scrollMask & TrackBGPart || scrollMask & ThumbPart || scrollMask & allButtons)
paintScrollbarBackground(graphicsContext, scrollbar);
paintTrackBackground(graphicsContext, scrollbar, trackPaintRect);
if (scrollMask & BackButtonStartPart)
paintButton(graphicsContext, scrollbar, backButtonStartPaintRect, BackButtonStartPart);
if (scrollMask & BackButtonEndPart)
paintButton(graphicsContext, scrollbar, backButtonEndPaintRect, BackButtonEndPart);
if (scrollMask & ForwardButtonStartPart)
paintButton(graphicsContext, scrollbar, forwardButtonStartPaintRect, ForwardButtonStartPart);
if (scrollMask & ForwardButtonEndPart)
paintButton(graphicsContext, scrollbar, forwardButtonEndPaintRect, ForwardButtonEndPart);
if (scrollMask & ThumbPart)
paintThumb(graphicsContext, scrollbar, currentThumbRect);
return true;
}
void ScrollbarThemeGtk::paintScrollCorner(ScrollView* view, GraphicsContext* context, const IntRect& cornerRect)
{
ScrollbarTheme::paintScrollCorner(view, context, cornerRect);
}
bool ScrollbarThemeGtk::shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent& event)
{
return (event.shiftKey() && event.button() == LeftButton) || (event.button() == MiddleButton);
}
int ScrollbarThemeGtk::scrollbarThickness(ScrollbarControlSize)
{
return m_thumbFatness + (m_troughBorderWidth * 2);
}
IntSize ScrollbarThemeGtk::buttonSize(Scrollbar* scrollbar)
{
if (scrollbar->orientation() == VerticalScrollbar)
return IntSize(m_thumbFatness, m_stepperSize);
return IntSize(m_stepperSize, m_thumbFatness);
}
int ScrollbarThemeGtk::minimumThumbLength(Scrollbar* scrollbar)
{
return m_minThumbLength;
}
}