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 ¤tly_selected_iter)) { 443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ApplyEdits(NULL); 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ApplyEdits(¤tly_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