blob: df6d9041317cfc75809ac04fe4ee80159553ede1 [file] [log] [blame]
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "views/controls/scrollbar/native_scroll_bar_gtk.h"
#include <gtk/gtk.h>
#include "ui/base/keycodes/keyboard_codes_posix.h"
#include "views/controls/scrollbar/native_scroll_bar.h"
#include "views/controls/scrollbar/native_scroll_bar_views.h"
#include "views/controls/scrollbar/scroll_bar.h"
#include "views/widget/widget.h"
namespace views {
////////////////////////////////////////////////////////////////////////////////
// NativeScrollBarGtk, public:
NativeScrollBarGtk::NativeScrollBarGtk(NativeScrollBar* scroll_bar)
: NativeControlGtk(),
native_scroll_bar_(scroll_bar) {
set_focus_view(scroll_bar);
}
NativeScrollBarGtk::~NativeScrollBarGtk() {
}
////////////////////////////////////////////////////////////////////////////////
// NativeScrollBarGtk, View overrides:
void NativeScrollBarGtk::Layout() {
SetBoundsRect(native_scroll_bar_->GetLocalBounds());
NativeControlGtk::Layout();
}
gfx::Size NativeScrollBarGtk::GetPreferredSize() {
if (native_scroll_bar_->IsHorizontal())
return gfx::Size(0, GetHorizontalScrollBarHeight());
return gfx::Size(GetVerticalScrollBarWidth(), 0);
}
// TODO(oshima|jcampan): key/mouse events are not delievered and
// the following code is not tested. It requires the focus manager to be fully
// implemented.
bool NativeScrollBarGtk::OnKeyPressed(const KeyEvent& event) {
if (!native_view())
return false;
switch (event.key_code()) {
case ui::VKEY_UP:
if (!native_scroll_bar_->IsHorizontal())
MoveStep(false /* negative */);
break;
case ui::VKEY_DOWN:
if (!native_scroll_bar_->IsHorizontal())
MoveStep(true /* positive */);
break;
case ui::VKEY_LEFT:
if (native_scroll_bar_->IsHorizontal())
MoveStep(false /* negative */);
break;
case ui::VKEY_RIGHT:
if (native_scroll_bar_->IsHorizontal())
MoveStep(true /* positive */);
break;
case ui::VKEY_PRIOR:
MovePage(false /* negative */);
break;
case ui::VKEY_NEXT:
MovePage(true /* positive */);
break;
case ui::VKEY_HOME:
MoveTo(0);
break;
case ui::VKEY_END:
MoveToBottom();
break;
default:
return false;
}
return true;
}
bool NativeScrollBarGtk::OnMouseWheel(const MouseWheelEvent& e) {
if (!native_view())
return false;
MoveBy(-e.offset()); // e.GetOffset() > 0 means scroll up.
return true;
}
////////////////////////////////////////////////////////////////////////////////
// NativeScrollBarGtk, NativeControlGtk overrides:
void NativeScrollBarGtk::CreateNativeControl() {
GtkObject* adj = gtk_adjustment_new(native_scroll_bar_->GetMinPosition(),
native_scroll_bar_->GetMinPosition(),
native_scroll_bar_->GetMaxPosition(),
10, 10,
0);
GtkWidget* widget;
if (native_scroll_bar_->IsHorizontal()) {
widget = gtk_hscrollbar_new(GTK_ADJUSTMENT(adj));
} else {
widget = gtk_vscrollbar_new(GTK_ADJUSTMENT(adj));
}
gtk_range_set_update_policy(GTK_RANGE(widget), GTK_UPDATE_CONTINUOUS);
g_signal_connect(adj, "value-changed",
G_CALLBACK(CallValueChanged), this);
NativeControlCreated(widget);
}
////////////////////////////////////////////////////////////////////////////////
// NativeScrollBarGtk, NativeScrollBarWrapper overrides:
int NativeScrollBarGtk::GetPosition() const {
return static_cast<int>(gtk_range_get_value(GTK_RANGE(native_view())));
}
View* NativeScrollBarGtk::GetView() {
return this;
}
void NativeScrollBarGtk::Update(int viewport_size,
int content_size,
int current_pos) {
if (!native_view())
return;
if (content_size < 0)
content_size = 0;
if (current_pos < 0)
current_pos = 0;
if (current_pos > content_size)
current_pos = content_size;
ScrollBarController* controller = native_scroll_bar_->controller();
int step = controller->GetScrollIncrement(native_scroll_bar_,
false /* step */,
true /* positive */);
int page = controller->GetScrollIncrement(native_scroll_bar_,
true /* page */, true);
GtkObject* adj = gtk_adjustment_new(current_pos,
native_scroll_bar_->GetMinPosition(),
content_size,
step, page,
viewport_size);
gtk_range_set_adjustment(GTK_RANGE(native_view()), GTK_ADJUSTMENT(adj));
g_signal_connect(adj, "value-changed", G_CALLBACK(CallValueChanged), this);
}
////////////////////////////////////////////////////////////////////////////////
// NativeScrollBarGtk, private:
void NativeScrollBarGtk::ValueChanged() {
ScrollBarController* controller = native_scroll_bar_->controller();
controller->ScrollToPosition(native_scroll_bar_, GetPosition());
}
// static
void NativeScrollBarGtk::CallValueChanged(GtkWidget* widget,
NativeScrollBarGtk* scroll_bar) {
scroll_bar->ValueChanged();
}
void NativeScrollBarGtk::MoveBy(int o) {
MoveTo(GetPosition() + o);
}
void NativeScrollBarGtk::MovePage(bool positive) {
ScrollBarController* controller = native_scroll_bar_->controller();
MoveBy(controller->GetScrollIncrement(native_scroll_bar_, true, positive));
}
void NativeScrollBarGtk::MoveStep(bool positive) {
ScrollBarController* controller = native_scroll_bar_->controller();
MoveBy(controller->GetScrollIncrement(native_scroll_bar_, false, positive));
}
void NativeScrollBarGtk::MoveTo(int p) {
if (p < native_scroll_bar_->GetMinPosition())
p = native_scroll_bar_->GetMinPosition();
if (p > native_scroll_bar_->GetMaxPosition())
p = native_scroll_bar_->GetMaxPosition();
GtkAdjustment* adj = gtk_range_get_adjustment(GTK_RANGE(native_view()));
gtk_adjustment_set_value(adj, p);
}
void NativeScrollBarGtk::MoveToBottom() {
GtkAdjustment* adj = gtk_range_get_adjustment(GTK_RANGE(native_view()));
MoveTo(adj->upper);
}
////////////////////////////////////////////////////////////////////////////////
// NativewScrollBarWrapper, public:
// static
NativeScrollBarWrapper* NativeScrollBarWrapper::CreateWrapper(
NativeScrollBar* scroll_bar) {
if (Widget::IsPureViews())
return new NativeScrollBarViews(scroll_bar);
return new NativeScrollBarGtk(scroll_bar);
}
// static
int NativeScrollBarWrapper::GetHorizontalScrollBarHeight() {
// TODO(oshima): get this from gtk's widget property "slider-width".
return 20;
}
// static
int NativeScrollBarWrapper::GetVerticalScrollBarWidth() {
// TODO(oshima): get this from gtk's widget property "slider-width".
return 20;
}
} // namespace views