summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorsky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-09 23:11:52 +0000
committersky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-09 23:11:52 +0000
commit870764920553f9347c599a6aed97d1d889ffeba7 (patch)
tree32207fd5879811fa5400117be9a52017423cd5e9 /ui
parentc3a396716daab081b57bdf443b0e0aac50af51b5 (diff)
downloadchromium_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.cc55
-rw-r--r--ui/views/view_model.h80
-rw-r--r--ui/views/view_model_unittest.cc41
-rw-r--r--ui/views/view_model_utils.cc48
-rw-r--r--ui/views/view_model_utils.h33
-rw-r--r--ui/views/view_model_utils_unittest.cc46
-rw-r--r--ui/views/views.gyp6
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',