Logo Search packages:      
Sourcecode: chromium-browser version File versions  Download package

bookmark_folder_tree_model.cc

// 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/browser/bookmarks/bookmark_folder_tree_model.h"

#include "app/l10n_util.h"
#include "app/resource_bundle.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "third_party/skia/include/core/SkBitmap.h"

BookmarkFolderTreeModel::BookmarkFolderTreeModel(BookmarkModel* model)
    : TreeNodeModel<FolderNode>(new FolderNode(NULL)),
      model_(model),
      recently_bookmarked_node_(new FolderNode(NULL)),
      search_node_(new FolderNode(NULL)) {
  recently_bookmarked_node_->SetTitle(
      l10n_util::GetString(IDS_BOOKMARK_TREE_RECENTLY_BOOKMARKED_NODE_TITLE));
  search_node_->SetTitle(
      l10n_util::GetString(IDS_BOOKMARK_TREE_SEARCH_NODE_TITLE));
  if (model_->IsLoaded())
    AddRootChildren();
  model_->AddObserver(this);
}

BookmarkFolderTreeModel::~BookmarkFolderTreeModel() {
  if (model_)
    model_->RemoveObserver(this);
}

BookmarkFolderTreeModel::NodeType BookmarkFolderTreeModel::GetNodeType(
    TreeModelNode* node) {
  if (node == recently_bookmarked_node_)
    return RECENTLY_BOOKMARKED;
  if (node == search_node_)
    return SEARCH;
  if (node == GetRoot())
    return NONE;
  return BOOKMARK;
}

FolderNode* BookmarkFolderTreeModel::GetFolderNodeForBookmarkNode(
    const BookmarkNode* node) {
  if (!node->is_folder())
    return NULL;

  return GetFolderNodeForBookmarkNode(AsNode(GetRoot()), node);
}

const BookmarkNode* BookmarkFolderTreeModel::TreeNodeAsBookmarkNode(
    TreeModelNode* node) {
  if (GetNodeType(node) != BOOKMARK)
    return NULL;
  return AsNode(node)->value;
}

void BookmarkFolderTreeModel::Loaded(BookmarkModel* model) {
  AddRootChildren();
}

void BookmarkFolderTreeModel::BookmarkModelBeingDeleted(BookmarkModel* model) {
  DCHECK(model_);
  model_->RemoveObserver(this);
  model_ = NULL;
}

void BookmarkFolderTreeModel::BookmarkNodeMoved(BookmarkModel* model,
                                                const BookmarkNode* old_parent,
                                                int old_index,
                                                const BookmarkNode* new_parent,
                                                int new_index) {
  const BookmarkNode* moved_node = new_parent->GetChild(new_index);
  if (!moved_node->is_folder())
    return;  // We're only showing folders, so we can ignore this.

  FolderNode* moved_folder_node = GetFolderNodeForBookmarkNode(moved_node);
  DCHECK(moved_folder_node);
  int old_folder_index =
      moved_folder_node->GetParent()->IndexOfChild(moved_folder_node);
  Remove(moved_folder_node->GetParent(), old_folder_index);
  int new_folder_index = CalculateIndexForChild(moved_node);
  Add(GetFolderNodeForBookmarkNode(new_parent), new_folder_index,
      moved_folder_node);
}

void BookmarkFolderTreeModel::BookmarkNodeAdded(BookmarkModel* model,
                                                const BookmarkNode* parent,
                                                int index) {
  const BookmarkNode* new_node = parent->GetChild(index);
  if (!new_node->is_folder())
    return;  // We're only showing folders, so we can ignore this.

  int folder_index = CalculateIndexForChild(new_node);
  Add(GetFolderNodeForBookmarkNode(parent), folder_index,
      CreateFolderNode(new_node));
}

void BookmarkFolderTreeModel::BookmarkNodeRemoved(BookmarkModel* model,
                                                  const BookmarkNode* parent,
                                                  int index,
                                                  const BookmarkNode* node) {
  if (!node->is_folder())
    return;  // We're only showing folders.

  FolderNode* folder_node = GetFolderNodeForBookmarkNode(parent);
  DCHECK(folder_node);
  for (int i = 0; i < folder_node->GetChildCount(); ++i) {
    if (folder_node->GetChild(i)->value == node) {
      scoped_ptr<FolderNode> removed_node(Remove(folder_node, i));
      return;
    }
  }

  // If we get here it means a folder was removed that we didn't know about,
  // which shouldn't happen.
  NOTREACHED();
}

void BookmarkFolderTreeModel::BookmarkNodeChanged(BookmarkModel* model,
                                                  const BookmarkNode* node) {
  if (!node->is_folder())
    return;

  FolderNode* folder_node = GetFolderNodeForBookmarkNode(node);
  if (!folder_node)
    return;

  folder_node->SetTitle(node->GetTitle());
  FOR_EACH_OBSERVER(TreeModelObserver,
                    observer_list(),
                    TreeNodeChanged(this, folder_node));
}

void BookmarkFolderTreeModel::BookmarkNodeChildrenReordered(
    BookmarkModel* model,
    const BookmarkNode* node) {
  FolderNode* folder_node = GetFolderNodeForBookmarkNode(node);
  DCHECK(folder_node);
  if (folder_node->GetChildCount() <= 1)
    return;  // Order won't have changed if 1 or fewer nodes.

  // Build a map between folder node and bookmark node.
  std::map<const BookmarkNode*, FolderNode*> bn_to_folder;
  for (int i = 0; i < folder_node->GetChildCount(); ++i)
    bn_to_folder[folder_node->GetChild(i)->value] = folder_node->GetChild(i);

  // Remove all the folder nodes.
  int original_count = folder_node->GetChildCount();
  folder_node->RemoveAll();

  // And add them back in the new order.
  for (int i = 0; i < node->GetChildCount(); ++i) {
    const BookmarkNode* child = node->GetChild(i);
    if (child->is_folder()) {
      DCHECK(bn_to_folder.find(child) != bn_to_folder.end());
      folder_node->Add(folder_node->GetChildCount(), bn_to_folder[child]);
    }
  }
  // The new count better match the original count, otherwise we're leaking and
  // treeview is likely to get way out of sync.
  DCHECK(original_count == folder_node->GetChildCount());

  // Finally, notify observers.
  FOR_EACH_OBSERVER(TreeModelObserver,
                    observer_list(),
                    TreeNodeChildrenReordered(this, folder_node));
}

void BookmarkFolderTreeModel::GetIcons(std::vector<SkBitmap>* icons) {
  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  icons->push_back(*rb.GetBitmapNamed(IDR_BOOKMARK_MANAGER_RECENT_ICON));
  icons->push_back(*rb.GetBitmapNamed(IDR_BOOKMARK_MANAGER_SEARCH_ICON));
}

int BookmarkFolderTreeModel::GetIconIndex(TreeModelNode* node) {
  if (node == recently_bookmarked_node_)
    return 0;
  if (node == search_node_)
    return 1;

  // Return -1 to use the default.
  return -1;
}

void BookmarkFolderTreeModel::AddRootChildren() {
  Add(AsNode(GetRoot()), 0, CreateFolderNode(model_->GetBookmarkBarNode()));
  Add(AsNode(GetRoot()), 1, CreateFolderNode(model_->other_node()));
  Add(AsNode(GetRoot()), 2, recently_bookmarked_node_);
  Add(AsNode(GetRoot()), 3, search_node_);
}

FolderNode* BookmarkFolderTreeModel::GetFolderNodeForBookmarkNode(
    FolderNode* folder_node,
    const BookmarkNode* node) {
  DCHECK(node->is_folder());
  if (folder_node->value == node)
    return folder_node;
  for (int i = 0; i < folder_node->GetChildCount(); ++i) {
    FolderNode* result =
        GetFolderNodeForBookmarkNode(folder_node->GetChild(i), node);
    if (result)
      return result;
  }
  return NULL;
}

FolderNode* BookmarkFolderTreeModel::CreateFolderNode(
    const BookmarkNode* node) {
  DCHECK(node->is_folder());
  FolderNode* folder_node = new FolderNode(node);
  folder_node->SetTitle(node->GetTitle());

  // And clone the children folders.
  for (int i = 0; i < node->GetChildCount(); ++i) {
    const BookmarkNode* child = node->GetChild(i);
    if (child->is_folder())
      folder_node->Add(folder_node->GetChildCount(), CreateFolderNode(child));
  }
  return folder_node;
}

int BookmarkFolderTreeModel::CalculateIndexForChild(const BookmarkNode* node) {
  const BookmarkNode* parent = node->GetParent();
  DCHECK(parent);
  for (int i = 0, folder_count = 0; i < parent->GetChildCount(); ++i) {
    const BookmarkNode* child = parent->GetChild(i);
    if (child == node)
      return folder_count;
    if (child->is_folder())
      folder_count++;
  }
  NOTREACHED();
  return 0;
}

Generated by  Doxygen 1.6.0   Back to index