1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ui/views/focus/view_storage.h"
6
7#include <algorithm>
8
9#include "base/logging.h"
10#include "base/memory/singleton.h"
11#include "base/stl_util.h"
12
13namespace views {
14
15// static
16ViewStorage* ViewStorage::GetInstance() {
17  return Singleton<ViewStorage>::get();
18}
19
20ViewStorage::ViewStorage() : view_storage_next_id_(0) {
21}
22
23ViewStorage::~ViewStorage() {
24  STLDeleteContainerPairSecondPointers(view_to_ids_.begin(),
25                                       view_to_ids_.end());
26}
27
28int ViewStorage::CreateStorageID() {
29  return view_storage_next_id_++;
30}
31
32void ViewStorage::StoreView(int storage_id, View* view) {
33  DCHECK(view);
34  std::map<int, View*>::iterator iter = id_to_view_.find(storage_id);
35
36  if (iter != id_to_view_.end()) {
37    NOTREACHED();
38    RemoveView(storage_id);
39  }
40
41  id_to_view_[storage_id] = view;
42
43  std::vector<int>* ids = NULL;
44  std::map<View*, std::vector<int>*>::iterator id_iter =
45      view_to_ids_.find(view);
46  if (id_iter == view_to_ids_.end()) {
47    ids = new std::vector<int>();
48    view_to_ids_[view] = ids;
49  } else {
50    ids = id_iter->second;
51  }
52  ids->push_back(storage_id);
53}
54
55View* ViewStorage::RetrieveView(int storage_id) {
56  std::map<int, View*>::iterator iter = id_to_view_.find(storage_id);
57  if (iter == id_to_view_.end())
58    return NULL;
59  return iter->second;
60}
61
62void ViewStorage::RemoveView(int storage_id) {
63  EraseView(storage_id, false);
64}
65
66void ViewStorage::ViewRemoved(View* removed) {
67  // Let's first retrieve the ids for that view.
68  std::map<View*, std::vector<int>*>::iterator ids_iter =
69      view_to_ids_.find(removed);
70
71  if (ids_iter == view_to_ids_.end()) {
72    // That view is not in the view storage.
73    return;
74  }
75
76  std::vector<int>* ids = ids_iter->second;
77  DCHECK(!ids->empty());
78  EraseView((*ids)[0], true);
79}
80
81void ViewStorage::EraseView(int storage_id, bool remove_all_ids) {
82  // Remove the view from id_to_view_location_.
83  std::map<int, View*>::iterator view_iter = id_to_view_.find(storage_id);
84  if (view_iter == id_to_view_.end())
85    return;
86
87  View* view = view_iter->second;
88  id_to_view_.erase(view_iter);
89
90  // Also update view_to_ids_.
91  std::map<View*, std::vector<int>*>::iterator ids_iter =
92      view_to_ids_.find(view);
93  DCHECK(ids_iter != view_to_ids_.end());
94  std::vector<int>* ids = ids_iter->second;
95
96  if (remove_all_ids) {
97    for (size_t i = 0; i < ids->size(); ++i) {
98      view_iter = id_to_view_.find((*ids)[i]);
99      if (view_iter != id_to_view_.end())
100        id_to_view_.erase(view_iter);
101    }
102    ids->clear();
103  } else {
104    std::vector<int>::iterator id_iter =
105        std::find(ids->begin(), ids->end(), storage_id);
106    DCHECK(id_iter != ids->end());
107    ids->erase(id_iter);
108  }
109
110  if (ids->empty()) {
111    delete ids;
112    view_to_ids_.erase(ids_iter);
113  }
114}
115
116}  // namespace views
117