15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/view_prop.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ui {
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Maints the actual view, key and data.
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ViewProp::Data : public base::RefCounted<ViewProp::Data> {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the Data* for the view/key pair. If |create| is false and |Get|
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // has not been invoked for the view/key pair, NULL is returned.
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void Get(gfx::AcceleratedWidget view,
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  const char* key,
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  bool create,
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  scoped_refptr<Data>* data) {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!data_set_)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data_set_ = new DataSet;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<Data> new_data(new Data(view, key));
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DataSet::const_iterator i = data_set_->find(new_data.get());
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i != data_set_->end()) {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *data = *i;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!create)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_set_->insert(new_data.get());
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *data = new_data.get();
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The data.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void set_data(void* data) { data_ = data; }
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* data() const { return data_; }
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* key() const { return key_; }
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCounted<Data>;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used to order the Data in the map.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class DataComparator {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool operator()(const Data* d1, const Data* d2) const {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return (d1->view_ == d2->view_) ? (d1->key_ < d2->key_) :
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        (d1->view_ < d2->view_);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::set<Data*, DataComparator> DataSet;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Data(gfx::AcceleratedWidget view, const char* key)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : view_(view),
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        key_(key),
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data_(NULL) {}
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~Data() {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DataSet::iterator i = data_set_->find(this);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Also check for equality using == as |Get| creates dummy values in order
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to look up a value.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i != data_set_->end() && *i == this)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data_set_->erase(i);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The existing set of Data is stored here. ~Data removes from the set.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static DataSet* data_set_;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::AcceleratedWidget view_;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* key_;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* data_;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(Data);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ViewProp::Data::DataSet* ViewProp::Data::data_set_ = NULL;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ViewProp::ViewProp(gfx::AcceleratedWidget view, const char* key, void* data) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Data::Get(view, key, true, &data_);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_->set_data(data);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ViewProp::~ViewProp() {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is done to provide similar semantics to SetProp. In particular it's
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // assumed that ~ViewProp should behave as though RemoveProp was invoked.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_->set_data(NULL);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* ViewProp::GetValue(gfx::AcceleratedWidget view, const char* key) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<Data> data;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Data::Get(view, key, false, &data);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return data.get() ? data->data() : NULL;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* ViewProp::Key() const {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return data_->key();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ui
104