blob: 3af89cca8e87e7b97c2d632f5736792fa0423986 [file] [log] [blame]
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
* Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
* Copyright (C) 2007 Holger Hans Peter Freyther
*
* All rights reserved.
*
* 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"
#include "FloatRect.h"
#include "Frame.h"
#include "FrameView.h"
#include "GraphicsContext.h"
#include "IntRect.h"
#include "NotImplemented.h"
#include "RenderLayer.h"
#include <gdk/gdk.h>
#include <gtk/gtk.h>
using namespace std;
namespace WebCore {
class ScrollView::ScrollViewPrivate
{
public:
ScrollViewPrivate()
: hasStaticBackground(false)
, suppressScrollbars(false)
, vScrollbarMode(ScrollbarAuto)
, hScrollbarMode(ScrollbarAuto)
, layout(0)
, scrollBarsNeedUpdate(false)
{ }
bool hasStaticBackground;
bool suppressScrollbars;
ScrollbarMode vScrollbarMode;
ScrollbarMode hScrollbarMode;
GtkLayout *layout;
IntSize contentsSize;
IntSize viewPortSize;
bool scrollBarsNeedUpdate;
};
ScrollView::ScrollView()
: m_data(new ScrollViewPrivate)
{}
ScrollView::~ScrollView()
{
delete m_data;
}
void ScrollView::updateView(const IntRect& updateRect, bool now)
{
GdkRectangle rect = { updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height() };
GdkDrawable* gdkdrawable = Widget::gdkDrawable();
if (GDK_IS_WINDOW(gdkdrawable)) {
GdkWindow* window = GDK_WINDOW(gdkdrawable);
gdk_window_invalidate_rect(window, &rect, true);
if (now)
gdk_window_process_updates(window, true);
}
}
void ScrollView::updateContents(const IntRect& updateRect, bool now)
{
updateView(updateRect, now);
}
void ScrollView::update()
{
ASSERT(gtkWidget());
gtk_widget_queue_draw(gtkWidget());
if (m_data->scrollBarsNeedUpdate)
updateScrollbars();
}
int ScrollView::visibleWidth() const
{
return m_data->viewPortSize.width();
}
int ScrollView::visibleHeight() const
{
return m_data->viewPortSize.height();
}
// Region of the content currently visible in the viewport in the content view's coordinate system.
FloatRect ScrollView::visibleContentRect() const
{
return FloatRect(contentsX(), contentsY(), visibleWidth(), visibleHeight());
}
FloatRect ScrollView::visibleContentRectConsideringExternalScrollers() const
{
// external scrollers not supported for now
return visibleContentRect();
}
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)
return;
m_data->contentsSize = newSize;
if (m_data->layout) {
gtk_layout_set_size(m_data->layout, w, h);
m_data->scrollBarsNeedUpdate = true;
}
}
int ScrollView::contentsX() const
{
g_return_val_if_fail(gtk_layout_get_hadjustment(m_data->layout), 0);
return static_cast<int>(gtk_adjustment_get_value(gtk_layout_get_hadjustment(m_data->layout)));
}
int ScrollView::contentsY() const
{
g_return_val_if_fail(gtk_layout_get_vadjustment(m_data->layout), 0);
return static_cast<int>(gtk_adjustment_get_value(gtk_layout_get_vadjustment(m_data->layout)));
}
int ScrollView::contentsWidth() const
{
return m_data->contentsSize.width();
}
int ScrollView::contentsHeight() const
{
return m_data->contentsSize.height();
}
IntSize ScrollView::scrollOffset() const
{
g_return_val_if_fail(m_data, IntSize());
return IntSize(contentsX(), contentsY());
}
void ScrollView::scrollBy(int dx, int dy)
{
GtkAdjustment* hadj = gtk_layout_get_hadjustment(m_data->layout);
GtkAdjustment* vadj = gtk_layout_get_vadjustment(m_data->layout);
g_return_if_fail(hadj);
g_return_if_fail(vadj);
int current_x = contentsX();
int current_y = contentsY();
gtk_adjustment_set_value(hadj,
CLAMP(current_x+dx, hadj->lower,
MAX(0.0, hadj->upper - hadj->page_size)));
gtk_adjustment_set_value(vadj,
CLAMP(current_y+dy, vadj->lower,
MAX(0.0, vadj->upper - vadj->page_size)));
}
ScrollbarMode ScrollView::hScrollbarMode() const
{
return m_data->hScrollbarMode;
}
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;
}
/*
* only update the adjustments, the GtkLayout is doing the work
* for us (assuming it is in a box...).
*/
void ScrollView::setFrameGeometry(const IntRect& r)
{
Widget::setFrameGeometry(r);
updateGeometry(r.width(), r.height());
}
void ScrollView::updateGeometry(int width, int height)
{
m_data->viewPortSize = IntSize(width,height);
}
void ScrollView::setGtkWidget(GtkLayout* layout)
{
g_return_if_fail(GTK_LAYOUT(layout));
m_data->layout = layout;
Widget::setGtkWidget(GTK_WIDGET(layout));
}
void ScrollView::addChild(Widget* w)
{
ASSERT(w->gtkWidget());
ASSERT(m_data->layout);
gtk_layout_put(m_data->layout, w->gtkWidget(), 0, 0);
}
void ScrollView::removeChild(Widget* w)
{
ASSERT(w->gtkWidget());
ASSERT(m_data->layout);
gtk_container_remove(GTK_CONTAINER(m_data->layout), w->gtkWidget());
}
void ScrollView::scrollRectIntoViewRecursively(const IntRect&)
{
notImplemented();
}
bool ScrollView::inWindow() const
{
notImplemented();
return true;
}
void ScrollView::wheelEvent(PlatformWheelEvent&)
{
notImplemented();
}
void ScrollView::updateScrollbars()
{
GtkAdjustment* hadj = gtk_layout_get_hadjustment(m_data->layout);
GtkAdjustment* vadj = gtk_layout_get_vadjustment(m_data->layout);
g_return_if_fail(hadj);
g_return_if_fail(vadj);
hadj->page_size = visibleWidth();
hadj->step_increment = 13;
vadj->page_size = visibleHeight();
vadj->step_increment = 13;
gtk_adjustment_changed(hadj);
gtk_adjustment_value_changed(hadj);
gtk_adjustment_changed(vadj);
gtk_adjustment_value_changed(vadj);
m_data->scrollBarsNeedUpdate = false;
}
IntPoint ScrollView::windowToContents(const IntPoint& point) const
{
return point;
}
IntPoint ScrollView::contentsToWindow(const IntPoint& point) const
{
return point;
}
PlatformScrollbar* ScrollView::scrollbarUnderMouse(const PlatformMouseEvent& mouseEvent)
{
notImplemented();
return 0;
}
}