1// Copyright (c) 2011 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/base/view_prop.h"
6
7#include <set>
8
9namespace ui {
10
11// Maints the actual view, key and data.
12class ViewProp::Data : public base::RefCounted<ViewProp::Data> {
13 public:
14  // Returns the Data* for the view/key pair. If |create| is false and |Get|
15  // has not been invoked for the view/key pair, NULL is returned.
16  static void Get(gfx::AcceleratedWidget view,
17                  const char* key,
18                  bool create,
19                  scoped_refptr<Data>* data) {
20    if (!data_set_)
21      data_set_ = new DataSet;
22    scoped_refptr<Data> new_data(new Data(view, key));
23    DataSet::const_iterator i = data_set_->find(new_data.get());
24    if (i != data_set_->end()) {
25      *data = *i;
26      return;
27    }
28    if (!create)
29      return;
30    data_set_->insert(new_data.get());
31    *data = new_data.get();
32  }
33
34  // The data.
35  void set_data(void* data) { data_ = data; }
36  void* data() const { return data_; }
37
38  const char* key() const { return key_; }
39
40 private:
41  friend class base::RefCounted<Data>;
42
43  // Used to order the Data in the map.
44  class DataComparator {
45   public:
46    bool operator()(const Data* d1, const Data* d2) const {
47      return (d1->view_ == d2->view_) ? (d1->key_ < d2->key_) :
48                                        (d1->view_ < d2->view_);
49    }
50  };
51
52  typedef std::set<Data*, DataComparator> DataSet;
53
54  Data(gfx::AcceleratedWidget view, const char* key)
55      : view_(view),
56        key_(key),
57        data_(NULL) {}
58
59  ~Data() {
60    DataSet::iterator i = data_set_->find(this);
61    // Also check for equality using == as |Get| creates dummy values in order
62    // to look up a value.
63    if (i != data_set_->end() && *i == this)
64      data_set_->erase(i);
65  }
66
67  // The existing set of Data is stored here. ~Data removes from the set.
68  static DataSet* data_set_;
69
70  const gfx::AcceleratedWidget view_;
71  const char* key_;
72  void* data_;
73
74  DISALLOW_COPY_AND_ASSIGN(Data);
75};
76
77// static
78ViewProp::Data::DataSet* ViewProp::Data::data_set_ = NULL;
79
80ViewProp::ViewProp(gfx::AcceleratedWidget view, const char* key, void* data) {
81  Data::Get(view, key, true, &data_);
82  data_->set_data(data);
83}
84
85ViewProp::~ViewProp() {
86  // This is done to provide similar semantics to SetProp. In particular it's
87  // assumed that ~ViewProp should behave as though RemoveProp was invoked.
88  data_->set_data(NULL);
89}
90
91// static
92void* ViewProp::GetValue(gfx::AcceleratedWidget view, const char* key) {
93  scoped_refptr<Data> data;
94  Data::Get(view, key, false, &data);
95  return data.get() ? data->data() : NULL;
96}
97
98// static
99const char* ViewProp::Key() const {
100  return data_->key();
101}
102
103}  // namespace ui
104