172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/gtk/bookmarks/bookmark_editor_gtk.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <gtk/gtk.h>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/basictypes.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h"
123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/bookmarks/bookmark_model.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/bookmarks/bookmark_utils.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/history.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/net/url_fixer_upper.h"
1721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
18dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/gtk/bookmarks/bookmark_tree_model.h"
19dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/gtk/bookmarks/bookmark_utils_gtk.h"
20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/gtk/gtk_theme_service.h"
2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/gtk_util.h"
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "googleurl/src/gurl.h"
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/chromium_strings.h"
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h"
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/locale_settings.h"
2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
2772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/models/simple_menu_model.h"
2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/gtk_util.h"
2972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/point.h"
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#if defined(TOOLKIT_VIEWS)
324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "views/controls/menu/menu_2.h"
334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#else
3472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/gtk/menu_gtk.h"
354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#endif
364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Background color of text field when URL is invalid.
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst GdkColor kErrorColor = GDK_COLOR_RGB(0xFF, 0xBC, 0xBC);
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Preferred initial dimensions, in pixels, of the folder tree.
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kTreeWidth = 300;
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kTreeHeight = 150;
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
484a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochclass BookmarkEditorGtk::ContextMenuController
4972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    : public ui::SimpleMenuModel::Delegate {
504a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch public:
514a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  explicit ContextMenuController(BookmarkEditorGtk* editor)
524a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      : editor_(editor),
534a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        running_menu_for_root_(false) {
5472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    menu_model_.reset(new ui::SimpleMenuModel(this));
554a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    menu_model_->AddItemWithStringId(COMMAND_EDIT, IDS_EDIT);
564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    menu_model_->AddItemWithStringId(
574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        COMMAND_NEW_FOLDER,
584a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        IDS_BOOMARK_EDITOR_NEW_FOLDER_MENU_ITEM);
594a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#if defined(TOOLKIT_VIEWS)
604a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    menu_.reset(new views::Menu2(menu_model_.get()));
614a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#else
624a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    menu_.reset(new MenuGtk(NULL, menu_model_.get()));
634a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#endif
644a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
654a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  virtual ~ContextMenuController() {}
664a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
6772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  void RunMenu(const gfx::Point& point, guint32 event_time) {
684a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    const BookmarkNode* selected_node = GetSelectedNode();
694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    if (selected_node)
70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      running_menu_for_root_ = selected_node->parent()->IsRoot();
714a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#if defined(TOOLKIT_VIEWS)
724a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    menu_->RunContextMenuAt(point);
734a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#else
7472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    menu_->PopupAsContext(point, event_time);
754a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#endif
764a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
774a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
784a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  void Cancel() {
794a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    editor_ = NULL;
804a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#if defined(TOOLKIT_VIEWS)
814a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    menu_->CancelMenu();
824a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#else
834a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    menu_->Cancel();
844a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#endif
854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
864a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
874a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch private:
884a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  enum ContextMenuCommand {
894a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    COMMAND_EDIT,
904a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    COMMAND_NEW_FOLDER
914a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  };
924a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
9372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Overridden from ui::SimpleMenuModel::Delegate:
944a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  virtual bool IsCommandIdEnabled(int command_id) const {
954a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    return !(command_id == COMMAND_EDIT && running_menu_for_root_) &&
964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        (editor_ != NULL);
974a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
984a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
994a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  virtual bool IsCommandIdChecked(int command_id) const {
1004a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    return false;
1014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
1024a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1034a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  virtual bool GetAcceleratorForCommandId(int command_id,
10472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                          ui::Accelerator* accelerator) {
1054a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    return false;
1064a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
1074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1084a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  virtual void ExecuteCommand(int command_id) {
1094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    if (!editor_)
1104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      return;
1114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    switch (command_id) {
1134a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      case COMMAND_EDIT: {
1144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        GtkTreeIter iter;
1154a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        if (!gtk_tree_selection_get_selected(editor_->tree_selection_,
1164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                                             NULL,
1174a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                                             &iter)) {
1184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch          return;
1194a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        }
1204a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1214a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        GtkTreePath* path = gtk_tree_model_get_path(
1224a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch            GTK_TREE_MODEL(editor_->tree_store_), &iter);
1234a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        gtk_tree_view_expand_to_path(GTK_TREE_VIEW(editor_->tree_view_), path);
1244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        // Make the folder name editable.
1264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        gtk_tree_view_set_cursor(GTK_TREE_VIEW(editor_->tree_view_), path,
1274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch            gtk_tree_view_get_column(GTK_TREE_VIEW(editor_->tree_view_), 0),
1284a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch            TRUE);
1294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        gtk_tree_path_free(path);
1314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        break;
1324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      }
1334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      case COMMAND_NEW_FOLDER:
1344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        editor_->NewFolder();
1354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        break;
1364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      default:
1374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        NOTREACHED();
1384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch        break;
1394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    }
1404a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
1414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  int64 GetRowIdAt(GtkTreeModel* model, GtkTreeIter* iter) {
1434a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    GValue value = { 0, };
1444a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    gtk_tree_model_get_value(model, iter, bookmark_utils::ITEM_ID, &value);
1454a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    int64 id = g_value_get_int64(&value);
1464a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    g_value_unset(&value);
1474a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    return id;
1484a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
1494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1504a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  const BookmarkNode* GetNodeAt(GtkTreeModel* model, GtkTreeIter* iter) {
1514a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    int64 id = GetRowIdAt(model, iter);
1524a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    return (id > 0) ? editor_->bb_model_->GetNodeByID(id) : NULL;
1534a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
1544a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1554a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  const BookmarkNode* GetSelectedNode() {
1564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    GtkTreeModel* model;
1574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    GtkTreeIter iter;
1584a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    if (!gtk_tree_selection_get_selected(editor_->tree_selection_,
1594a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                                         &model,
1604a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                                         &iter)) {
1614a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      return NULL;
1624a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    }
1634a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1644a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    return GetNodeAt(model, &iter);
1654a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
1664a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1674a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // The model and view for the right click context menu.
16872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  scoped_ptr<ui::SimpleMenuModel> menu_model_;
1694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#if defined(TOOLKIT_VIEWS)
1704a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  scoped_ptr<views::Menu2> menu_;
1714a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#else
1724a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  scoped_ptr<MenuGtk> menu_;
1734a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#endif
1744a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1754a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // The context menu was brought up for. Set to NULL when the menu is canceled.
1764a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  BookmarkEditorGtk* editor_;
1774a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1784a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // If true, we're running the menu for the bookmark bar or other bookmarks
1794a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // nodes.
1804a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  bool running_menu_for_root_;
1814a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
1824a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(ContextMenuController);
1834a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch};
1844a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BookmarkEditor::Show(gfx::NativeWindow parent_hwnd,
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          Profile* profile,
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          const BookmarkNode* parent,
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          const EditDetails& details,
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          Configuration configuration) {
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(profile);
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BookmarkEditorGtk* editor =
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new BookmarkEditorGtk(parent_hwnd, profile, parent, details,
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            configuration);
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  editor->Show();
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBookmarkEditorGtk::BookmarkEditorGtk(
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkWindow* window,
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Profile* profile,
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const BookmarkNode* parent,
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const EditDetails& details,
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    BookmarkEditor::Configuration configuration)
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : profile_(profile),
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      dialog_(NULL),
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      parent_(parent),
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      details_(details),
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      running_menu_for_root_(false),
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      show_tree_(configuration == SHOW_TREE) {
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(profile);
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Init(window);
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBookmarkEditorGtk::~BookmarkEditorGtk() {
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The tree model is deleted before the view. Reset the model otherwise the
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // tree will reference a deleted model.
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bb_model_->RemoveObserver(this);
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BookmarkEditorGtk::Init(GtkWindow* parent_window) {
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bb_model_ = profile_->GetBookmarkModel();
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(bb_model_);
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bb_model_->AddObserver(this);
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  dialog_ = gtk_dialog_new_with_buttons(
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      l10n_util::GetStringUTF8(IDS_BOOMARK_EDITOR_TITLE).c_str(),
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      parent_window,
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GTK_DIALOG_MODAL,
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NULL);
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_dialog_set_has_separator(GTK_DIALOG(dialog_), FALSE);
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (show_tree_) {
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkWidget* action_area = GTK_DIALOG(dialog_)->action_area;
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    new_folder_button_ = gtk_button_new_with_label(
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        l10n_util::GetStringUTF8(IDS_BOOMARK_EDITOR_NEW_FOLDER_BUTTON).c_str());
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    g_signal_connect(new_folder_button_, "clicked",
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     G_CALLBACK(OnNewFolderClickedThunk), this);
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_container_add(GTK_CONTAINER(action_area), new_folder_button_);
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_button_box_set_child_secondary(GTK_BUTTON_BOX(action_area),
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                       new_folder_button_, TRUE);
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_ACCEPT);
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The GTK dialog content area layout (overview)
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // +- GtkVBox |vbox| ----------------------------------------------+
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |+- GtkTable |table| ------------------------------------------+|
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ||+- GtkLabel ------+ +- GtkEntry |name_entry_| --------------+||
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |||                 | |                                       |||
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ||+-----------------+ +---------------------------------------+||
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ||+- GtkLabel ------+ +- GtkEntry |url_entry_| ---------------+|| *
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |||                 | |                                       |||
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ||+-----------------+ +---------------------------------------+||
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |+-------------------------------------------------------------+|
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |+- GtkScrollWindow |scroll_window| ---------------------------+|
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ||+- GtkTreeView |tree_view_| --------------------------------+||
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |||+- GtkTreeViewColumn |name_column| -----------------------+|||
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ||||                                                         ||||
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ||||                                                         ||||
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ||||                                                         ||||
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ||||                                                         ||||
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |||+---------------------------------------------------------+|||
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ||+-----------------------------------------------------------+||
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |+-------------------------------------------------------------+|
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // +---------------------------------------------------------------+
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  //
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // * The url and corresponding label are not shown if creating a new folder.
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* content_area = GTK_DIALOG(dialog_)->vbox;
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_set_spacing(GTK_BOX(content_area), gtk_util::kContentAreaSpacing);
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* vbox = gtk_vbox_new(FALSE, 12);
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  name_entry_ = gtk_entry_new();
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string title;
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (details_.type == EditDetails::EXISTING_NODE) {
2803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    title = UTF16ToUTF8(details_.existing_node->GetTitle());
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (details_.type == EditDetails::NEW_FOLDER) {
2823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    title = l10n_util::GetStringUTF8(IDS_BOOMARK_EDITOR_NEW_FOLDER_NAME);
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_entry_set_text(GTK_ENTRY(name_entry_), title.c_str());
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(name_entry_, "changed",
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnEntryChangedThunk), this);
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_entry_set_activates_default(GTK_ENTRY(name_entry_), TRUE);
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* table;
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (details_.type != EditDetails::NEW_FOLDER) {
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    url_entry_ = gtk_entry_new();
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::string url_spec;
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (details_.type == EditDetails::EXISTING_NODE)
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      url_spec = details_.existing_node->GetURL().spec();
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_entry_set_text(GTK_ENTRY(url_entry_), url_spec.c_str());
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    g_signal_connect(url_entry_, "changed",
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     G_CALLBACK(OnEntryChangedThunk), this);
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_entry_set_activates_default(GTK_ENTRY(url_entry_), TRUE);
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    table = gtk_util::CreateLabeledControlsGroup(NULL,
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        l10n_util::GetStringUTF8(IDS_BOOMARK_EDITOR_NAME_LABEL).c_str(),
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        name_entry_,
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        l10n_util::GetStringUTF8(IDS_BOOMARK_EDITOR_URL_LABEL).c_str(),
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        url_entry_,
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NULL);
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    url_entry_ = NULL;
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    table = gtk_util::CreateLabeledControlsGroup(NULL,
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        l10n_util::GetStringUTF8(IDS_BOOMARK_EDITOR_NAME_LABEL).c_str(),
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        name_entry_,
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NULL);
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (show_tree_) {
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkTreeIter selected_iter;
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int64 selected_id = 0;
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (details_.type == EditDetails::EXISTING_NODE)
320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      selected_id = details_.existing_node->parent()->id();
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    else if (parent_)
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      selected_id = parent_->id();
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    tree_store_ = bookmark_utils::MakeFolderTreeStore();
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bookmark_utils::AddToTreeStore(bb_model_, selected_id, tree_store_,
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   &selected_iter);
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    tree_view_ = bookmark_utils::MakeTreeViewForStore(tree_store_);
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_set_size_request(tree_view_, kTreeWidth, kTreeHeight);
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    tree_selection_ = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view_));
3294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    g_signal_connect(tree_view_, "button-press-event",
3304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                     G_CALLBACK(OnTreeViewButtonPressEventThunk), this);
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkTreePath* path = NULL;
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (selected_id) {
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      path = gtk_tree_model_get_path(GTK_TREE_MODEL(tree_store_),
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     &selected_iter);
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // We don't have a selected parent (Probably because we're making a new
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // bookmark). Select the first item in the list.
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      path = gtk_tree_path_new_from_string("0");
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_tree_view_expand_to_path(GTK_TREE_VIEW(tree_view_), path);
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_tree_selection_select_path(tree_selection_, path);
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_tree_path_free(path);
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL);
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    GTK_POLICY_NEVER,
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   GTK_POLICY_AUTOMATIC);
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window),
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                        GTK_SHADOW_ETCHED_IN);
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_container_add(GTK_CONTAINER(scroll_window), tree_view_);
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_box_pack_start(GTK_BOX(vbox), scroll_window, TRUE, TRUE, 0);
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view_)),
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     "changed", G_CALLBACK(OnSelectionChangedThunk), this);
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_box_pack_start(GTK_BOX(content_area), vbox, TRUE, TRUE, 0);
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(dialog_, "response",
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnResponseThunk), this);
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(dialog_, "delete-event",
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnWindowDeleteEventThunk), this);
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  g_signal_connect(dialog_, "destroy",
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   G_CALLBACK(OnWindowDestroyThunk), this);
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BookmarkEditorGtk::Show() {
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Manually call our OnEntryChanged handler to set the initial state.
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  OnEntryChanged(NULL);
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_util::ShowDialog(dialog_);
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BookmarkEditorGtk::Close() {
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Under the model that we've inherited from Windows, dialogs can receive
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // more than one Close() call inside the current message loop event.
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (dialog_) {
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_destroy(dialog_);
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    dialog_ = NULL;
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BookmarkEditorGtk::BookmarkNodeMoved(BookmarkModel* model,
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          const BookmarkNode* old_parent,
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          int old_index,
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          const BookmarkNode* new_parent,
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          int new_index) {
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Reset();
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BookmarkEditorGtk::BookmarkNodeAdded(BookmarkModel* model,
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          const BookmarkNode* parent,
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          int index) {
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Reset();
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BookmarkEditorGtk::BookmarkNodeRemoved(BookmarkModel* model,
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                            const BookmarkNode* parent,
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                            int index,
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                            const BookmarkNode* node) {
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if ((details_.type == EditDetails::EXISTING_NODE &&
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       details_.existing_node->HasAncestor(node)) ||
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      (parent_ && parent_->HasAncestor(node))) {
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The node, or its parent was removed. Close the dialog.
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Close();
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Reset();
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BookmarkEditorGtk::BookmarkNodeChildrenReordered(
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    BookmarkModel* model, const BookmarkNode* node) {
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Reset();
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BookmarkEditorGtk::Reset() {
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TODO(erg): The windows implementation tries to be smart. For now, just
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // close the window.
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Close();
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGURL BookmarkEditorGtk::GetInputURL() const {
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!url_entry_)
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return GURL();  // Happens when we're editing a folder.
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return URLFixerUpper::FixupURL(gtk_entry_get_text(GTK_ENTRY(url_entry_)),
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 std::string());
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstring16 BookmarkEditorGtk::GetInputTitle() const {
4333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return UTF8ToUTF16(gtk_entry_get_text(GTK_ENTRY(name_entry_)));
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BookmarkEditorGtk::ApplyEdits() {
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(bb_model_->IsLoaded());
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkTreeIter currently_selected_iter;
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (show_tree_) {
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!gtk_tree_selection_get_selected(tree_selection_, NULL,
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                         &currently_selected_iter)) {
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ApplyEdits(NULL);
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ApplyEdits(&currently_selected_iter);
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BookmarkEditorGtk::ApplyEdits(GtkTreeIter* selected_parent) {
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We're going to apply edits to the bookmark bar model, which will call us
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // back. Normally when a structural edit occurs we reset the tree model.
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We don't want to do that here, so we remove ourselves as an observer.
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bb_model_->RemoveObserver(this);
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL new_url(GetInputURL());
4583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  string16 new_title(GetInputTitle());
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!show_tree_ || !selected_parent) {
461ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    bookmark_utils::ApplyEditsWithNoFolderChange(
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        bb_model_, parent_, details_, new_title, new_url);
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
466ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Create the new folders and update the titles.
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const BookmarkNode* new_parent =
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bookmark_utils::CommitTreeStoreDifferencesBetween(
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bb_model_, tree_store_, selected_parent);
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!new_parent) {
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Bookmarks must be parented.
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED();
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
477ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bookmark_utils::ApplyEditsWithPossibleFolderChange(
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bb_model_, new_parent, details_, new_title, new_url);
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
481ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BookmarkEditorGtk::AddNewFolder(GtkTreeIter* parent, GtkTreeIter* child) {
482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_store_append(tree_store_, child, parent);
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_store_set(
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      tree_store_, child,
485ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      bookmark_utils::FOLDER_ICON, GtkThemeService::GetFolderIcon(true),
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bookmark_utils::FOLDER_NAME,
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          l10n_util::GetStringUTF8(IDS_BOOMARK_EDITOR_NEW_FOLDER_NAME).c_str(),
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bookmark_utils::ITEM_ID, static_cast<int64>(0),
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bookmark_utils::IS_EDITABLE, TRUE,
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      -1);
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BookmarkEditorGtk::OnSelectionChanged(GtkWidget* selection) {
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!gtk_tree_selection_get_selected(tree_selection_, NULL, NULL))
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_set_sensitive(new_folder_button_, FALSE);
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  else
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    gtk_widget_set_sensitive(new_folder_button_, TRUE);
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BookmarkEditorGtk::OnResponse(GtkWidget* dialog, int response_id) {
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (response_id == GTK_RESPONSE_ACCEPT)
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ApplyEdits();
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Close();
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgboolean BookmarkEditorGtk::OnWindowDeleteEvent(GtkWidget* widget,
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                GdkEvent* event) {
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Close();
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Return true to prevent the gtk dialog from being destroyed. Close will
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // destroy it for us and the default gtk_dialog_delete_event_handler() will
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // force the destruction without us being able to stop it.
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return TRUE;
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BookmarkEditorGtk::OnWindowDestroy(GtkWidget* widget) {
518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BookmarkEditorGtk::OnEntryChanged(GtkWidget* entry) {
522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gboolean can_close = TRUE;
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (details_.type == EditDetails::NEW_FOLDER) {
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (GetInputTitle().empty()) {
525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_widget_modify_base(name_entry_, GTK_STATE_NORMAL,
526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             &kErrorColor);
527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      can_close = FALSE;
528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_widget_modify_base(name_entry_, GTK_STATE_NORMAL, NULL);
530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GURL url(GetInputURL());
533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!url.is_valid()) {
534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_widget_modify_base(url_entry_, GTK_STATE_NORMAL,
535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             &kErrorColor);
536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      can_close = FALSE;
537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_widget_modify_base(url_entry_, GTK_STATE_NORMAL, NULL);
539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog_),
542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    GTK_RESPONSE_ACCEPT, can_close);
543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BookmarkEditorGtk::OnNewFolderClicked(GtkWidget* button) {
5464a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  NewFolder();
5474a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
5484a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
5494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochgboolean BookmarkEditorGtk::OnTreeViewButtonPressEvent(GtkWidget* widget,
5504a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                                                       GdkEventButton* event) {
5514a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (event->button == 3) {
55272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!menu_controller_.get())
55372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      menu_controller_.reset(new ContextMenuController(this));
55472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    menu_controller_->RunMenu(gfx::Point(event->x_root, event->y_root),
55572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                              event->time);
5564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
5574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
5584a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  return FALSE;
5594a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
5604a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
5614a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid BookmarkEditorGtk::NewFolder() {
562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkTreeIter iter;
563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!gtk_tree_selection_get_selected(tree_selection_,
564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                       NULL,
565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                       &iter)) {
566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NOTREACHED() << "Something should always be selected if New Folder " <<
567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                    "is clicked";
568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkTreeIter new_item_iter;
572ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  AddNewFolder(&iter, &new_item_iter);
573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkTreePath* path = gtk_tree_model_get_path(
575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GTK_TREE_MODEL(tree_store_), &new_item_iter);
576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_view_expand_to_path(GTK_TREE_VIEW(tree_view_), path);
577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Make the folder name editable.
579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_view_set_cursor(GTK_TREE_VIEW(tree_view_), path,
580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      gtk_tree_view_get_column(GTK_TREE_VIEW(tree_view_), 0),
581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      TRUE);
582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gtk_tree_path_free(path);
584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
585