diff options
-rw-r--r-- | views/controls/scroll_view.cc | 4 | ||||
-rw-r--r-- | views/controls/scrollbar/native_scroll_bar_gtk.cc | 214 | ||||
-rw-r--r-- | views/controls/scrollbar/native_scroll_bar_gtk.h | 79 | ||||
-rw-r--r-- | views/examples/examples_main_base.cc | 2 | ||||
-rw-r--r-- | views/examples/scroll_view_example.h | 121 | ||||
-rw-r--r-- | views/views.gyp | 6 |
6 files changed, 421 insertions, 5 deletions
diff --git a/views/controls/scroll_view.cc b/views/controls/scroll_view.cc index ecc3033..a5b5f6a 100644 --- a/views/controls/scroll_view.cc +++ b/views/controls/scroll_view.cc @@ -353,7 +353,7 @@ void ScrollView::ScrollToPosition(ScrollBar* source, int position) { else if (position > max_pos) position = max_pos; contents_->SetX(-position); - contents_->SchedulePaint(contents_->GetLocalBounds(true), true); + contents_->SchedulePaint(contents_->GetVisibleBounds(), true); } } else if (source == vert_sb_ && vert_sb_->IsVisible()) { int vh = viewport_->height(); @@ -366,7 +366,7 @@ void ScrollView::ScrollToPosition(ScrollBar* source, int position) { else if (position > max_pos) position = max_pos; contents_->SetY(-position); - contents_->SchedulePaint(contents_->GetLocalBounds(true), true); + contents_->SchedulePaint(contents_->GetVisibleBounds(), true); } } } diff --git a/views/controls/scrollbar/native_scroll_bar_gtk.cc b/views/controls/scrollbar/native_scroll_bar_gtk.cc new file mode 100644 index 0000000..616ff7f --- /dev/null +++ b/views/controls/scrollbar/native_scroll_bar_gtk.cc @@ -0,0 +1,214 @@ +// Copyright (c) 2009 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 "base/keyboard_codes_posix.h" +#include "views/controls/scrollbar/native_scroll_bar.h" +#include "views/controls/scrollbar/scroll_bar.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() { + SetBounds(native_scroll_bar_->GetLocalBounds(true)); + 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.GetKeyCode()) { + case base::VKEY_UP: + if (!native_scroll_bar_->IsHorizontal()) + MoveStep(false /* negative */); + break; + case base::VKEY_DOWN: + if (!native_scroll_bar_->IsHorizontal()) + MoveStep(true /* positive */); + break; + case base::VKEY_LEFT: + if (native_scroll_bar_->IsHorizontal()) + MoveStep(false /* negative */); + break; + case base::VKEY_RIGHT: + if (native_scroll_bar_->IsHorizontal()) + MoveStep(true /* positive */); + break; + case base::VKEY_PRIOR: + MovePage(false /* negative */); + break; + case base::VKEY_NEXT: + MovePage(true /* positive */); + break; + case base::VKEY_HOME: + MoveTo(0); + break; + case base::VKEY_END: + MoveToBottom(); + break; + default: + return false; + } + return true; +} + +bool NativeScrollBarGtk::OnMouseWheel(const MouseWheelEvent& e) { + if (!native_view() || native_scroll_bar_->IsHorizontal()) + return false; + MoveBy(e.GetOffset()); + 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(G_OBJECT(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_->GetController(); + 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(G_OBJECT(adj), "value-changed", + G_CALLBACK(CallValueChanged), this); +} + +//////////////////////////////////////////////////////////////////////////////// +// NativeScrollBarGtk, private: + +void NativeScrollBarGtk::ValueChanged() { + ScrollBarController* controller = native_scroll_bar_->GetController(); + 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_->GetController(); + MoveBy(controller->GetScrollIncrement(native_scroll_bar_, true, positive)); +} + +void NativeScrollBarGtk::MoveStep(bool positive) { + ScrollBarController* controller = native_scroll_bar_->GetController(); + MoveBy(controller->GetScrollIncrement(native_scroll_bar_, false, positive)); +} + +void NativeScrollBarGtk::MoveTo(int p) { + 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) { + 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 diff --git a/views/controls/scrollbar/native_scroll_bar_gtk.h b/views/controls/scrollbar/native_scroll_bar_gtk.h new file mode 100644 index 0000000..ca70d1d --- /dev/null +++ b/views/controls/scrollbar/native_scroll_bar_gtk.h @@ -0,0 +1,79 @@ +// Copyright (c) 2009 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. + +#ifndef VIEWS_CONTROLS_SCROLLBAR_NATIVE_SCROLL_BAR_GTK_H_ +#define VIEWS_CONTROLS_SCROLLBAR_NATIVE_SCROLL_BAR_GTK_H_ + +#include "views/controls/native_control_gtk.h" +#include "views/controls/scrollbar/native_scroll_bar_wrapper.h" + +namespace views { + +class ScrollBarContainer; + +///////////////////////////////////////////////////////////////////////////// +// +// NativeScrollBarGtk +// +// A View subclass that wraps a Native gtk scrollbar control. +// +// A scrollbar is either horizontal or vertical. +// +///////////////////////////////////////////////////////////////////////////// +class NativeScrollBarGtk : public NativeControlGtk, + public NativeScrollBarWrapper { + public: + // Creates new scrollbar, either horizontal or vertical. + explicit NativeScrollBarGtk(NativeScrollBar* native_scroll_bar); + virtual ~NativeScrollBarGtk(); + + private: + // Overridden from View for layout purpose. + virtual void Layout(); + virtual gfx::Size GetPreferredSize(); + + // Overridden from View for keyboard UI purpose. + virtual bool OnKeyPressed(const KeyEvent& event); + virtual bool OnMouseWheel(const MouseWheelEvent& e); + + // Overridden from NativeControlGtk. + virtual void CreateNativeControl(); + + // Overridden from NativeScrollBarWrapper. + virtual int GetPosition() const; + virtual View* GetView(); + virtual void Update(int viewport_size, int content_size, int current_pos); + + // Moves the scrollbar by the given value. Negative value is allowed. + // (moves upward) + void MoveBy(int o); + + // Moves the scrollbar by the page (viewport) size. + void MovePage(bool positive); + + // Moves the scrollbar by predefined step size. + void MoveStep(bool positive); + + // Moves the scrollbar to the given position. MoveTo(0) moves it to the top. + void MoveTo(int p); + + // Moves the scrollbar to the end. + void MoveToBottom(); + + // Invoked when the scrollbar's position is changed. + void ValueChanged(); + static void CallValueChanged(GtkWidget* widget, + NativeScrollBarGtk* scroll_bar); + + // The NativeScrollBar we are bound to. + NativeScrollBar* native_scroll_bar_; + + private: + DISALLOW_COPY_AND_ASSIGN(NativeScrollBarGtk); +}; + +} // namespace views + +#endif // #ifndef VIEWS_CONTROLS_SCROLLBAR_NATIVE_SCROLL_BAR_GTK_H_ + diff --git a/views/examples/examples_main_base.cc b/views/examples/examples_main_base.cc index cd65c2c..b407347 100644 --- a/views/examples/examples_main_base.cc +++ b/views/examples/examples_main_base.cc @@ -18,6 +18,7 @@ #include "views/examples/combobox_example.h" #include "views/examples/message_box_example.h" #include "views/examples/radio_button_example.h" +#include "views/examples/scroll_view_example.h" #include "views/examples/tabbed_pane_example.h" namespace examples { @@ -74,6 +75,7 @@ void ExamplesMainBase::Run() { TabbedPaneExample tabbed_pane_example(tabbed_pane, message); MessageBoxExample message_box_example(tabbed_pane, message); RadioButtonExample radio_button_example(tabbed_pane, message); + ScrollViewExample scroll_view_example(tabbed_pane, message); widget->Show(); diff --git a/views/examples/scroll_view_example.h b/views/examples/scroll_view_example.h new file mode 100644 index 0000000..b032224 --- /dev/null +++ b/views/examples/scroll_view_example.h @@ -0,0 +1,121 @@ +// Copyright (c) 2009 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. + +#ifndef VIEWS_EXAMPLES_SCROLL_BAR_EXAMPLE_H_ +#define VIEWS_EXAMPLES_SCROLL_BAR_EXAMPLE_H_ + +#include "base/string_util.h" +#include "views/controls/button/text_button.h" +#include "views/controls/scroll_view.h" +#include "views/examples/example_base.h" + +namespace examples { + +class ScrollViewExample : protected ExampleBase, private views::ButtonListener { + public: + ScrollViewExample(views::TabbedPane* tabbed_pane, views::Label* message) + : ExampleBase(message), + wide_(new views::TextButton(this, L"Wide")), + tall_(new views::TextButton(this, L"Tall")), + big_square_(new views::TextButton(this, L"Big Square")), + small_square_(new views::TextButton(this, L"Small Square")), + scroll_to_(new views::TextButton(this, L"Scroll to")), + scrollable_(new ScrollableView()), + scroll_view_(new views::ScrollView()) { + scroll_view_->SetContents(scrollable_); + scrollable_->SetBounds(0, 0, 1000, 100); + scrollable_->SetColor(SK_ColorYELLOW, SK_ColorCYAN); + + views::View* container = new views::View(); + tabbed_pane->AddTab(L"Scroll View", container); + + views::GridLayout* layout = new views::GridLayout(container); + container->SetLayoutManager(layout); + + // Add scroll view. + views::ColumnSet* column_set = layout->AddColumnSet(0); + column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, + views::GridLayout::USE_PREF, 0, 0); + layout->StartRow(1, 0); + layout->AddView(scroll_view_); + + // Add control buttons. + column_set = layout->AddColumnSet(1); + for (int i = 0; i < 5; i++) { + column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1, + views::GridLayout::USE_PREF, 0, 0); + } + layout->StartRow(0, 1); + layout->AddView(wide_); + layout->AddView(tall_); + layout->AddView(big_square_); + layout->AddView(small_square_); + layout->AddView(scroll_to_); + } + + virtual ~ScrollViewExample() {} + + private: + // ScrollView's content, which draws gradient color on background. + // TODO(oshima): add child views as well. + class ScrollableView : public views::View { + public: + ScrollableView() { + SetColor(SK_ColorRED, SK_ColorCYAN); + } + + gfx::Size GetPreferredSize() { + return gfx::Size(width(), height()); + } + + void SetColor(SkColor from, SkColor to) { + set_background( + views::Background::CreateVerticalGradientBackground(from, to)); + } + + virtual void Layout() { + SizeToPreferredSize(); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ScrollableView); + }; + + // ButtonListner implementation. + virtual void ButtonPressed(views::Button* sender, const views::Event& event) { + if (sender == wide_) { + scrollable_->SetBounds(0, 0, 1000, 100); + scrollable_->SetColor(SK_ColorYELLOW, SK_ColorCYAN); + } else if (sender == tall_) { + scrollable_->SetBounds(0, 0, 100, 1000); + scrollable_->SetColor(SK_ColorRED, SK_ColorCYAN); + } else if (sender == big_square_) { + scrollable_->SetBounds(0, 0, 1000, 1000); + scrollable_->SetColor(SK_ColorRED, SK_ColorGREEN); + } else if (sender == small_square_) { + scrollable_->SetBounds(0, 0, 100, 100); + scrollable_->SetColor(SK_ColorYELLOW, SK_ColorGREEN); + } else if (sender == scroll_to_) { + scroll_view_->ScrollContentsRegionToBeVisible(20, 500, 1000, 500); + } + scroll_view_->Layout(); + } + + // Control buttons to change the size of scrollable and jump to + // predefined position. + views::TextButton* wide_, *tall_, *big_square_, *small_square_, *scroll_to_; + + // The content of the scroll view. + ScrollableView* scrollable_; + + // The scroll view to test. + views::ScrollView* scroll_view_; + + DISALLOW_COPY_AND_ASSIGN(ScrollViewExample); +}; + +} // namespace examples + +#endif // VIEWS_EXAMPLES_SCROLL_BAR_EXAMPLE_H_ + diff --git a/views/views.gyp b/views/views.gyp index fb387e8..a16f9b2 100644 --- a/views/views.gyp +++ b/views/views.gyp @@ -159,9 +159,11 @@ 'controls/scroll_view.h', 'controls/scrollbar/bitmap_scroll_bar.cc', 'controls/scrollbar/bitmap_scroll_bar.h', - 'controls/scrollbar/native_scroll_bar_wrapper.h', + 'controls/scrollbar/native_scroll_bar_gtk.cc', + 'controls/scrollbar/native_scroll_bar_gtk.h', 'controls/scrollbar/native_scroll_bar_win.cc', 'controls/scrollbar/native_scroll_bar_win.h', + 'controls/scrollbar/native_scroll_bar_wrapper.h', 'controls/scrollbar/native_scroll_bar.cc', 'controls/scrollbar/native_scroll_bar.h', 'controls/scrollbar/scroll_bar.cc', @@ -302,10 +304,8 @@ 'controls/scrollbar/bitmap_scroll_bar.cc', 'controls/combo_box.cc', 'controls/hwnd_view.cc', - 'controls/scroll_view.cc', 'controls/table/group_table_view.cc', 'controls/native_control.cc', - 'controls/scrollbar/native_scroll_bar.cc', 'controls/separator.cc', 'controls/table/table_model.cc', 'controls/table/table_view.cc', |