summaryrefslogtreecommitdiffstats
path: root/chrome/views/focus/view_storage.cc
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-17 02:54:02 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-17 02:54:02 +0000
commit08682a91c50c166c3b3c64f8fd3e11693a09ad3b (patch)
tree45bc0b83b34ea102afb97574b0dc79820d62fc51 /chrome/views/focus/view_storage.cc
parentac9c1dffe98ca1abc5864c7b191b05b5b75a3aea (diff)
downloadchromium_src-08682a91c50c166c3b3c64f8fd3e11693a09ad3b.zip
chromium_src-08682a91c50c166c3b3c64f8fd3e11693a09ad3b.tar.gz
chromium_src-08682a91c50c166c3b3c64f8fd3e11693a09ad3b.tar.bz2
Move focus related files into a new chrome/views/focus subdir
TBR=sky Review URL: http://codereview.chromium.org/48056 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@11837 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/views/focus/view_storage.cc')
-rw-r--r--chrome/views/focus/view_storage.cc188
1 files changed, 188 insertions, 0 deletions
diff --git a/chrome/views/focus/view_storage.cc b/chrome/views/focus/view_storage.cc
new file mode 100644
index 0000000..94826ea
--- /dev/null
+++ b/chrome/views/focus/view_storage.cc
@@ -0,0 +1,188 @@
+// Copyright (c) 2006-2008 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 "chrome/views/focus/view_storage.h"
+
+#include <algorithm>
+
+#include "chrome/common/notification_service.h"
+#include "chrome/common/stl_util-inl.h"
+
+namespace views {
+
+// This struct contains the information to locate a specific view.
+// Locating a view is not always straight-forward as a view can be a floating
+// view, or the child of a floating view. Floating views are frequently deleted
+// and recreated (typically when their container is laid out).
+struct ViewLocationInfo {
+ // True if the view is floating or the child of a floating view. False
+ // otherwise.
+ bool is_floating_view;
+
+ // If non floating, this is the stored view. If floating, the parent of the
+ // floating view.
+ View* view;
+
+ // The id of the floating view.
+ int floating_view_id;
+
+ // The path from the floating view to the stored view. The path is composed
+ // of the indexes of the views in the hierarchy.
+ std::vector<int> floating_view_to_view_path;
+};
+
+// static
+ViewStorage* ViewStorage::GetSharedInstance() {
+ return Singleton<ViewStorage>::get();
+}
+
+ViewStorage::ViewStorage() : view_storage_next_id_(0) {
+ NotificationService::current()->AddObserver(
+ this, NotificationType::VIEW_REMOVED, NotificationService::AllSources());
+}
+
+ViewStorage::~ViewStorage() {
+ STLDeleteContainerPairSecondPointers(id_to_view_location_.begin(),
+ id_to_view_location_.end());
+
+ STLDeleteContainerPairSecondPointers(view_to_ids_.begin(),
+ view_to_ids_.end());
+}
+
+int ViewStorage::CreateStorageID() {
+ return view_storage_next_id_++;
+}
+
+void ViewStorage::StoreView(int storage_id, View* view) {
+ DCHECK(view);
+ std::map<int, ViewLocationInfo*>::iterator iter =
+ id_to_view_location_.find(storage_id);
+ DCHECK(iter == id_to_view_location_.end());
+
+ if (iter != id_to_view_location_.end())
+ RemoveView(storage_id);
+
+ ViewLocationInfo* view_location_info = new ViewLocationInfo();
+ View* floating_view_parent = view->RetrieveFloatingViewParent();
+ if (floating_view_parent) {
+ // The view is a floating view or is a child of a floating view.
+ view_location_info->is_floating_view = true;
+ view_location_info->view = floating_view_parent->GetParent();
+ view_location_info->floating_view_id =
+ floating_view_parent->GetFloatingViewID();
+ // Ley's store the path from the floating view to the actual view so we can
+ // locate it when restoring.
+ View::GetViewPath(floating_view_parent, view,
+ &(view_location_info->floating_view_to_view_path));
+ } else {
+ // It is a non floating view, it can be stored as is.
+ view_location_info->is_floating_view = false;
+ view_location_info->view = view;
+ }
+ id_to_view_location_[storage_id] = view_location_info;
+
+ std::vector<int>* ids = NULL;
+ std::map<View*, std::vector<int>*>::iterator id_iter =
+ view_to_ids_.find(view_location_info->view);
+ if (id_iter == view_to_ids_.end()) {
+ ids = new std::vector<int>();
+ view_to_ids_[view_location_info->view] = ids;
+ } else {
+ ids = id_iter->second;
+ }
+ ids->push_back(storage_id);
+}
+
+View* ViewStorage::RetrieveView(int storage_id) {
+ std::map<int, ViewLocationInfo*>::iterator iter =
+ id_to_view_location_.find(storage_id);
+ if (iter == id_to_view_location_.end())
+ return NULL;
+
+ ViewLocationInfo* view_location_info = iter->second;
+ if (view_location_info->is_floating_view) {
+ View* floating_view = view_location_info->view->
+ RetrieveFloatingViewForID(view_location_info->floating_view_id);
+ View* v = NULL;
+ if (floating_view) {
+ v = View::GetViewForPath(floating_view,
+ view_location_info->floating_view_to_view_path);
+ }
+ if (!v) {
+ // If we have not found the view, it means either the floating view with
+ // the id we have is gone, or it has changed and the actual child view
+ // we have the path for is not accessible. In that case, let's make sure
+ // we don't leak the ViewLocationInfo.
+ RemoveView(storage_id);
+ }
+ return v;
+ } else {
+ return view_location_info->view;
+ }
+}
+
+void ViewStorage::RemoveView(int storage_id) {
+ EraseView(storage_id, false);
+}
+
+void ViewStorage::EraseView(int storage_id, bool remove_all_ids) {
+ // Remove the view from id_to_view_location_.
+ std::map<int, ViewLocationInfo*>::iterator location_iter =
+ id_to_view_location_.find(storage_id);
+ if (location_iter == id_to_view_location_.end())
+ return;
+
+ ViewLocationInfo* view_location = location_iter->second;
+ View* view = view_location->view;
+ delete view_location;
+ id_to_view_location_.erase(location_iter);
+
+ // Also update view_to_ids_.
+ std::map<View*, std::vector<int>*>::iterator ids_iter =
+ view_to_ids_.find(view);
+ DCHECK(ids_iter != view_to_ids_.end());
+ std::vector<int>* ids = ids_iter->second;
+
+ if (remove_all_ids) {
+ for (size_t i = 0; i < ids->size(); ++i) {
+ location_iter = id_to_view_location_.find((*ids)[i]);
+ if (location_iter != id_to_view_location_.end()) {
+ delete location_iter->second;
+ id_to_view_location_.erase(location_iter);
+ }
+ }
+ ids->clear();
+ } else {
+ std::vector<int>::iterator id_iter =
+ std::find(ids->begin(), ids->end(), storage_id);
+ DCHECK(id_iter != ids->end());
+ ids->erase(id_iter);
+ }
+
+ if (ids->empty()) {
+ delete ids;
+ view_to_ids_.erase(ids_iter);
+ }
+}
+
+void ViewStorage::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK(type == NotificationType::VIEW_REMOVED);
+
+ // Let's first retrieve the ids for that view.
+ std::map<View*, std::vector<int>*>::iterator ids_iter =
+ view_to_ids_.find(Source<View>(source).ptr());
+
+ if (ids_iter == view_to_ids_.end()) {
+ // That view is not in the view storage.
+ return;
+ }
+
+ std::vector<int>* ids = ids_iter->second;
+ DCHECK(!ids->empty());
+ EraseView((*ids)[0], true);
+}
+
+} // namespace views