diff options
author | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-09 23:11:52 +0000 |
---|---|---|
committer | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-09 23:11:52 +0000 |
commit | 870764920553f9347c599a6aed97d1d889ffeba7 (patch) | |
tree | 32207fd5879811fa5400117be9a52017423cd5e9 /ui | |
parent | c3a396716daab081b57bdf443b0e0aac50af51b5 (diff) | |
download | chromium_src-870764920553f9347c599a6aed97d1d889ffeba7.zip chromium_src-870764920553f9347c599a6aed97d1d889ffeba7.tar.gz chromium_src-870764920553f9347c599a6aed97d1d889ffeba7.tar.bz2 |
Moves view_model and related classes to views. This way I can use it
in the tabstrip.
BUG=none
TEST=none
Review URL: https://chromiumcodereview.appspot.com/10031012
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@131472 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r-- | ui/views/view_model.cc | 55 | ||||
-rw-r--r-- | ui/views/view_model.h | 80 | ||||
-rw-r--r-- | ui/views/view_model_unittest.cc | 41 | ||||
-rw-r--r-- | ui/views/view_model_utils.cc | 48 | ||||
-rw-r--r-- | ui/views/view_model_utils.h | 33 | ||||
-rw-r--r-- | ui/views/view_model_utils_unittest.cc | 46 | ||||
-rw-r--r-- | ui/views/views.gyp | 6 |
7 files changed, 309 insertions, 0 deletions
diff --git a/ui/views/view_model.cc b/ui/views/view_model.cc new file mode 100644 index 0000000..8ce2474 --- /dev/null +++ b/ui/views/view_model.cc @@ -0,0 +1,55 @@ +// Copyright (c) 2012 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 "ui/views/view_model.h" + +#include "base/logging.h" +#include "ui/views/view.h" + +namespace views { + +ViewModel::ViewModel() { +} + +ViewModel::~ViewModel() { + // view are owned by their parent, no need to delete them. +} + +void ViewModel::Add(View* view, int index) { + Entry entry; + entry.view = view; + entries_.insert(entries_.begin() + index, entry); +} + +void ViewModel::Remove(int index) { + if (index == -1) + return; + + entries_.erase(entries_.begin() + index); +} + +void ViewModel::Move(int index, int target_index) { + if (index == target_index) + return; + Entry entry(entries_[index]); + entries_.erase(entries_.begin() + index); + entries_.insert(entries_.begin() + target_index, entry); +} + +void ViewModel::Clear() { + Entries entries; + entries.swap(entries_); + for (size_t i = 0; i < entries.size(); ++i) + delete entries[i].view; +} + +int ViewModel::GetIndexOfView(const View* view) const { + for (size_t i = 0; i < entries_.size(); ++i) { + if (entries_[i].view == view) + return static_cast<int>(i); + } + return -1; +} + +} // namespace views diff --git a/ui/views/view_model.h b/ui/views/view_model.h new file mode 100644 index 0000000..6a68fb1 --- /dev/null +++ b/ui/views/view_model.h @@ -0,0 +1,80 @@ +// Copyright (c) 2012 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 UI_VIEWS_VIEW_MODEL_H_ +#define UI_VIEWS_VIEW_MODEL_H_ +#pragma once + +#include <vector> + +#include "base/basictypes.h" +#include "ui/gfx/rect.h" +#include "ui/views/views_export.h" + +namespace views { + +class View; + +// ViewModel is used to track an 'interesting' set of a views. Often times +// during animations views are removed after a delay, which makes for tricky +// coordinate conversion as you have to account for the possibility of the +// indices from the model not lining up with those you expect. This class lets +// you define the 'interesting' views and operate on those views. +class VIEWS_EXPORT ViewModel { + public: + ViewModel(); + ~ViewModel(); + + // Adds |view| to this model. This does not add |view| to a view hierarchy, + // only to this model. + void Add(View* view, int index); + + // Removes the view at the specified index. This does not actually remove the + // view from the view hierarchy. + void Remove(int index); + + // Moves the view at |index| to |target_index|. |target_index| is in terms + // of the model *after* the view at |index| is removed. + void Move(int index, int target_index); + + // Returns the number of views. + int view_size() const { return static_cast<int>(entries_.size()); } + + // Removes and deletes all the views. + void Clear(); + + // Returns the view at the specified index. + View* view_at(int index) const { + return entries_[index].view; + } + + void set_ideal_bounds(int index, const gfx::Rect& bounds) { + entries_[index].ideal_bounds = bounds; + } + + const gfx::Rect& ideal_bounds(int index) const { + return entries_[index].ideal_bounds; + } + + // Returns the index of the specified view, or -1 if the view isn't in the + // model. + int GetIndexOfView(const View* view) const; + + private: + struct Entry { + Entry() : view(NULL) {} + + View* view; + gfx::Rect ideal_bounds; + }; + typedef std::vector<Entry> Entries; + + Entries entries_; + + DISALLOW_COPY_AND_ASSIGN(ViewModel); +}; + +} // namespace views + +#endif // UI_VIEWS_VIEW_MODEL_H_ diff --git a/ui/views/view_model_unittest.cc b/ui/views/view_model_unittest.cc new file mode 100644 index 0000000..39e745f --- /dev/null +++ b/ui/views/view_model_unittest.cc @@ -0,0 +1,41 @@ +// Copyright (c) 2012 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 "ui/views/view_model.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/views/view.h" + +namespace views { + +TEST(ViewModel, BasicAssertions) { + View v1; + ViewModel model; + model.Add(&v1, 0); + EXPECT_EQ(1, model.view_size()); + EXPECT_EQ(&v1, model.view_at(0)); + gfx::Rect v1_bounds(1, 2, 3, 4); + model.set_ideal_bounds(0, v1_bounds); + EXPECT_EQ(v1_bounds, model.ideal_bounds(0)); + EXPECT_EQ(0, model.GetIndexOfView(&v1)); +} + +TEST(ViewModel, Move) { + View v1, v2, v3; + ViewModel model; + model.Add(&v1, 0); + model.Add(&v2, 1); + model.Add(&v3, 2); + model.Move(0, 2); + EXPECT_EQ(&v1, model.view_at(2)); + EXPECT_EQ(&v2, model.view_at(0)); + EXPECT_EQ(&v3, model.view_at(1)); + + model.Move(2, 0); + EXPECT_EQ(&v1, model.view_at(0)); + EXPECT_EQ(&v2, model.view_at(1)); + EXPECT_EQ(&v3, model.view_at(2)); +} + +} // namespace views diff --git a/ui/views/view_model_utils.cc b/ui/views/view_model_utils.cc new file mode 100644 index 0000000..a49fbcd --- /dev/null +++ b/ui/views/view_model_utils.cc @@ -0,0 +1,48 @@ +// Copyright (c) 2012 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 "ui/views/view_model_utils.h" + +#include <algorithm> + +#include "ui/views/view_model.h" +#include "ui/views/view.h" + +namespace views { + +// static +void ViewModelUtils::SetViewBoundsToIdealBounds(const ViewModel& model) { + for (int i = 0; i < model.view_size(); ++i) + model.view_at(i)->SetBoundsRect(model.ideal_bounds(i)); +} + +// static +int ViewModelUtils::DetermineMoveIndex(const ViewModel& model, + View* view, + int x) { + int current_index = model.GetIndexOfView(view); + DCHECK_NE(-1, current_index); + for (int i = 0; i < current_index; ++i) { + int mid_x = model.ideal_bounds(i).x() + model.ideal_bounds(i).width() / 2; + if (x < mid_x) + return i; + } + + if (current_index + 1 == model.view_size()) + return current_index; + + // For indices after the current index ignore the bounds of the view being + // dragged. This keeps the view from bouncing around as moved. + int delta = model.ideal_bounds(current_index + 1).x() - + model.ideal_bounds(current_index).x(); + for (int i = current_index + 1; i < model.view_size(); ++i) { + const gfx::Rect& bounds(model.ideal_bounds(i)); + int mid_x = bounds.x() + bounds.width() / 2 - delta; + if (x < mid_x) + return i - 1; + } + return model.view_size() - 1; +} + +} // namespace views diff --git a/ui/views/view_model_utils.h b/ui/views/view_model_utils.h new file mode 100644 index 0000000..5219ff8 --- /dev/null +++ b/ui/views/view_model_utils.h @@ -0,0 +1,33 @@ +// Copyright (c) 2012 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 UI_VIEWS_VIEW_MODEL_UTILS_H_ +#define UI_VIEWS_VIEW_MODEL_UTILS_H_ +#pragma once + +#include "base/basictypes.h" +#include "ui/views/views_export.h" + +namespace views { + +class View; +class ViewModel; + +class VIEWS_EXPORT ViewModelUtils { + public: + // Sets the bounds of each view to its ideal bounds. + static void SetViewBoundsToIdealBounds(const ViewModel& model); + + // Returns the index to move |view| to based on a x-coordinate of |x|. + static int DetermineMoveIndex(const ViewModel& model, + View* view, + int x); + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(ViewModelUtils); +}; + +} // namespace views + +#endif // UI_VIEWS_VIEW_MODEL_UTILS_H_ diff --git a/ui/views/view_model_utils_unittest.cc b/ui/views/view_model_utils_unittest.cc new file mode 100644 index 0000000..289feee --- /dev/null +++ b/ui/views/view_model_utils_unittest.cc @@ -0,0 +1,46 @@ +// Copyright (c) 2012 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 "ui/views/view_model_utils.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/views/view.h" +#include "ui/views/view_model.h" + +namespace views { + +// Makes sure SetViewBoundsToIdealBounds updates the view appropriately. +TEST(ViewModelUtils, SetViewBoundsToIdealBounds) { + View v1; + ViewModel model; + model.Add(&v1, 0); + gfx::Rect v1_bounds(1, 2, 3, 4); + model.set_ideal_bounds(0, v1_bounds); + ViewModelUtils::SetViewBoundsToIdealBounds(model); + EXPECT_EQ(v1_bounds, v1.bounds()); +} + +// Assertions for DetermineMoveIndex. +TEST(ViewModelUtils, DetermineMoveIndex) { + View v1, v2, v3; + ViewModel model; + model.Add(&v1, 0); + model.Add(&v2, 1); + model.Add(&v3, 2); + model.set_ideal_bounds(0, gfx::Rect(0, 0, 10, 10)); + model.set_ideal_bounds(1, gfx::Rect(10, 0, 1000, 10)); + model.set_ideal_bounds(2, gfx::Rect(1010, 0, 2, 10)); + + EXPECT_EQ(0, ViewModelUtils::DetermineMoveIndex(model, &v1, -10)); + EXPECT_EQ(0, ViewModelUtils::DetermineMoveIndex(model, &v1, 4)); + EXPECT_EQ(1, ViewModelUtils::DetermineMoveIndex(model, &v1, 506)); + EXPECT_EQ(2, ViewModelUtils::DetermineMoveIndex(model, &v1, 1010)); + EXPECT_EQ(2, ViewModelUtils::DetermineMoveIndex(model, &v1, 2000)); + + EXPECT_EQ(0, ViewModelUtils::DetermineMoveIndex(model, &v2, -10)); + EXPECT_EQ(0, ViewModelUtils::DetermineMoveIndex(model, &v2, 4)); + EXPECT_EQ(2, ViewModelUtils::DetermineMoveIndex(model, &v2, 12)); +} + +} // namespace views diff --git a/ui/views/views.gyp b/ui/views/views.gyp index b7975e8..cb82298 100644 --- a/ui/views/views.gyp +++ b/ui/views/views.gyp @@ -299,6 +299,10 @@ 'view_constants.cc', 'view_constants.h', 'view_aura.cc', + 'view_model.cc', + 'view_model.h', + 'view_model_utils.cc', + 'view_model_utils.h', 'view_text_utils.cc', 'view_text_utils.h', 'view_win.cc', @@ -482,6 +486,8 @@ 'test/test_views_delegate.h', 'test/views_test_base.cc', 'test/views_test_base.h', + 'view_model_unittest.cc', + 'view_model_utils_unittest.cc', 'view_unittest.cc', 'widget/native_widget_aura_unittest.cc', 'widget/native_widget_test_utils.h', |