Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(278)

Side by Side Diff: chrome/browser/gtk/bookmark_editor_gtk.cc

Issue 99131: Create a bookmark editor dialog interface and implement a GTK version. (Closed)
Patch Set: fixes for tony Created 11 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/gtk/bookmark_editor_gtk.h ('k') | chrome/browser/views/bookmark_bubble_view.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/gtk/bookmark_editor_gtk.h"
6
7 #include <gtk/gtk.h>
8
9 #include "base/basictypes.h"
10 #include "base/gfx/gtk_util.h"
11 #include "base/logging.h"
12 #include "base/string_util.h"
13 #include "chrome/browser/history/history.h"
14 #include "chrome/browser/profile.h"
15 #include "chrome/browser/net/url_fixer_upper.h"
16 #include "chrome/common/l10n_util.h"
17 #include "googleurl/src/gurl.h"
18 #include "grit/chromium_strings.h"
19 #include "grit/generated_resources.h"
20 #include "grit/locale_settings.h"
21
22 namespace {
23
24 // Background color of text field when URL is invalid.
25 const GdkColor kErrorColor = GDK_COLOR_RGB(0xFF, 0xBC, 0xBC);
26
27 // Preferred width of the tree.
28 static const int kTreeWidth = 300;
29
30 } // namespace
31
32 // static
33 void BookmarkEditor::Show(gfx::NativeWindow parent_hwnd,
34 Profile* profile,
35 BookmarkNode* parent,
36 BookmarkNode* node,
37 Configuration configuration,
38 Handler* handler) {
39 DCHECK(profile);
40 BookmarkEditorGtk* editor =
41 new BookmarkEditorGtk(parent_hwnd, profile, parent, node, configuration,
42 handler);
43 editor->Show();
44 }
45
46 BookmarkEditorGtk::BookmarkEditorGtk(
47 GtkWindow* window,
48 Profile* profile,
49 BookmarkNode* parent,
50 BookmarkNode* node,
51 BookmarkEditor::Configuration configuration,
52 BookmarkEditor::Handler* handler)
53 : profile_(profile),
54 dialog_(NULL),
55 parent_(parent),
56 node_(node),
57 running_menu_for_root_(false),
58 show_tree_(configuration == SHOW_TREE),
59 handler_(handler) {
60 DCHECK(profile);
61 Init(window);
62 }
63
64 BookmarkEditorGtk::~BookmarkEditorGtk() {
65 // The tree model is deleted before the view. Reset the model otherwise the
66 // tree will reference a deleted model.
67
68 // TODO(erg): Enable this when we have a |tree_view_|.
69 // if (tree_view_)
70 // tree_view_->SetModel(NULL);
71 bb_model_->RemoveObserver(this);
72 }
73
74 void BookmarkEditorGtk::Init(GtkWindow* parent_window) {
75 bb_model_ = profile_->GetBookmarkModel();
76 DCHECK(bb_model_);
77 bb_model_->AddObserver(this);
78
79 dialog_ = gtk_dialog_new_with_buttons(
80 l10n_util::GetStringUTF8(IDS_BOOMARK_EDITOR_TITLE).c_str(),
81 parent_window,
82 GTK_DIALOG_MODAL,
83 NULL);
84
85 // TODO(erg): Add "New Folder" button here and insert at correct place; to
86 // the extreme left of the dialog.
87 close_button_ = gtk_dialog_add_button(GTK_DIALOG(dialog_),
88 GTK_STOCK_CANCEL,
89 GTK_RESPONSE_REJECT);
90 ok_button_ = gtk_dialog_add_button(GTK_DIALOG(dialog_),
91 GTK_STOCK_OK, GTK_RESPONSE_ACCEPT);
92 gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_ACCEPT);
93
94 // The GTK dialog content area layout (overview)
95 //
96 // +- GtkVBox |content_area| --------------------------------------+
97 // |+- GtkTable |table| ------------------------------------------+|
98 // ||+- GtkLabel ------+ +- GtkEntry |name_entry_| --------------+||
99 // ||| | | |||
100 // ||+-----------------+ +---------------------------------------+||
101 // ||+- GtkLabel ------+ +- GtkEntry |url_entry_| ---------------+||
102 // ||| | | |||
103 // ||+-----------------+ +---------------------------------------+||
104 // |--------------------------------------------------------------+|
105 // |----------------------------------------------------------------
tony 2009/04/28 19:24:34 Awesome.
106 GtkWidget* content_area = GTK_DIALOG(dialog_)->vbox;
107 gtk_container_set_border_width(GTK_CONTAINER(content_area), 12);
108 GtkWidget* table = gtk_table_new(2, 2, FALSE);
109
110 GtkWidget* label = gtk_label_new(
111 l10n_util::GetStringUTF8(IDS_BOOMARK_EDITOR_NAME_LABEL).c_str());
112 gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(label),
113 0, 1, 0, 1,
114 (GtkAttachOptions)(GTK_SHRINK),
115 (GtkAttachOptions)(GTK_SHRINK),
116 12, 0);
117 name_entry_ = gtk_entry_new();
118 gtk_entry_set_text(GTK_ENTRY(name_entry_),
119 node_ ? WideToUTF8(node_->GetTitle()).c_str() : "");
120 g_signal_connect(G_OBJECT(name_entry_), "changed",
121 G_CALLBACK(OnEntryChanged), this);
122 g_object_set(G_OBJECT(name_entry_), "activates-default", TRUE, NULL);
123 gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(name_entry_),
124 1, 2, 0, 1,
125 (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
126 (GtkAttachOptions)(GTK_FILL),
127 0, 0);
128
129 label = gtk_label_new(
130 l10n_util::GetStringUTF8(IDS_BOOMARK_EDITOR_URL_LABEL).c_str());
131 gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(label),
132 0, 1, 1, 2,
133 (GtkAttachOptions)(GTK_SHRINK),
134 (GtkAttachOptions)(GTK_SHRINK),
135 12, 0);
136 url_entry_ = gtk_entry_new();
137 gtk_entry_set_text(GTK_ENTRY(url_entry_),
138 node_ ? node_->GetURL().spec().c_str() : "");
139 g_signal_connect(G_OBJECT(url_entry_), "changed",
140 G_CALLBACK(OnEntryChanged), this);
141 g_object_set(G_OBJECT(url_entry_), "activates-default", TRUE, NULL);
142 gtk_table_attach(GTK_TABLE(table), GTK_WIDGET(url_entry_),
143 1, 2, 1, 2,
144 (GtkAttachOptions)(GTK_EXPAND | GTK_FILL),
145 (GtkAttachOptions)(GTK_FILL),
146 0, 0);
147
148 gtk_box_pack_start(GTK_BOX(content_area), table, FALSE, FALSE, 0);
149
150 // TODO(erg): Port the windows bookmark tree model and enable this tree view.
151 //
152 // folder_tree_ = gtk_tree_view_new();
153 // gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(folder_tree_), TRUE);
154 // gtk_widget_set_size_request(folder_tree_, kTreeWidth, -1);
155 // gtk_widget_show(folder_tree_);
156 // gtk_box_pack_start(GTK_BOX(content_area), folder_tree_, FALSE, FALSE, 0);
157
158 g_signal_connect(dialog_, "response",
159 G_CALLBACK(OnResponse), this);
160 g_signal_connect(dialog_, "delete-event",
161 G_CALLBACK(OnWindowDeleteEvent), this);
162 g_signal_connect(dialog_, "destroy",
163 G_CALLBACK(OnWindowDestroy), this);
164 }
165
166 void BookmarkEditorGtk::Show() {
167 // Manually call our OnEntryChanged handler to set the initial state.
168 OnEntryChanged(NULL, this);
169
170 gtk_widget_show_all(dialog_);
171 }
172
173 void BookmarkEditorGtk::Close() {
174 // Under the model that we've inherited from Windows, dialogs can receive
175 // more than one Close() call inside the current message loop event.
176 if (dialog_) {
177 gtk_widget_destroy(dialog_);
178 dialog_ = NULL;
179 }
180 }
181
182 void BookmarkEditorGtk::BookmarkNodeMoved(BookmarkModel* model,
183 BookmarkNode* old_parent,
184 int old_index,
185 BookmarkNode* new_parent,
186 int new_index) {
187 Reset();
188 }
189
190 void BookmarkEditorGtk::BookmarkNodeAdded(BookmarkModel* model,
191 BookmarkNode* parent,
192 int index) {
193 Reset();
194 }
195
196 void BookmarkEditorGtk::BookmarkNodeRemoved(BookmarkModel* model,
197 BookmarkNode* parent,
198 int index,
199 BookmarkNode* node) {
200 if ((node_ && node_->HasAncestor(node)) ||
201 (parent_ && parent_->HasAncestor(node))) {
202 // The node, or its parent was removed. Close the dialog.
203 Close();
204 } else {
205 Reset();
206 }
207 }
208
209 void BookmarkEditorGtk::BookmarkNodeChildrenReordered(BookmarkModel* model,
210 BookmarkNode* node) {
211 Reset();
212 }
213
214 void BookmarkEditorGtk::Reset() {
215 // TODO(erg): The windows implementation tries to be smart. For now, just
216 // close the window.
217 Close();
218 }
219
220 GURL BookmarkEditorGtk::GetInputURL() const {
221 std::wstring input = URLFixerUpper::FixupURL(
222 UTF8ToWide(gtk_entry_get_text(GTK_ENTRY(url_entry_))), L"");
223 return GURL(WideToUTF8(input));
224 }
225
226 std::wstring BookmarkEditorGtk::GetInputTitle() const {
227 return UTF8ToWide(gtk_entry_get_text(GTK_ENTRY(name_entry_)));
228 }
229
230 void BookmarkEditorGtk::ApplyEdits() {
231 // TODO(erg): This is massively simplified because I haven't added a
232 // GtkTreeView to this class yet. Then, this will have to be a copy of
233 // BookmarkEditorView::ApplyEdits().
234
235 // We're going to apply edits to the bookmark bar model, which will call us
236 // back. Normally when a structural edit occurs we reset the tree model.
237 // We don't want to do that here, so we remove ourselves as an observer.
238 bb_model_->RemoveObserver(this);
239
240 GURL new_url(GetInputURL());
241 std::wstring new_title(GetInputTitle());
242
243 BookmarkNode* old_parent = node_ ? node_->GetParent() : NULL;
244 const int old_index = old_parent ? old_parent->IndexOfChild(node_) : -1;
245
246 if (!node_) {
247 BookmarkNode* node =
248 bb_model_->AddURL(parent_, parent_->GetChildCount(), new_title,
249 new_url);
250 if (handler_.get())
251 handler_->NodeCreated(node);
252 return;
253 }
254 // If we're not showing the tree we only need to modify the node.
255 if (old_index == -1) {
256 NOTREACHED();
257 return;
258 }
259 if (new_url != node_->GetURL()) {
260 bb_model_->AddURLWithCreationTime(old_parent, old_index, new_title,
261 new_url, node_->date_added());
262 bb_model_->Remove(old_parent, old_index + 1);
263 } else {
264 bb_model_->SetTitle(node_, new_title);
265 }
266 }
267
268 // static
269 void BookmarkEditorGtk::OnResponse(GtkDialog* dialog, int response_id,
270 BookmarkEditorGtk* window) {
271 if (response_id == GTK_RESPONSE_ACCEPT) {
272 window->ApplyEdits();
273 }
274
275 window->Close();
276 }
277
278 // static
279 gboolean BookmarkEditorGtk::OnWindowDeleteEvent(
280 GtkWidget* widget,
281 GdkEvent* event,
282 BookmarkEditorGtk* dialog) {
283 dialog->Close();
284
285 // Return true to prevent the gtk dialog from being destroyed. Close will
286 // destroy it for us and the default gtk_dialog_delete_event_handler() will
287 // force the destruction without us being able to stop it.
288 return TRUE;
289 }
290
291 // static
292 void BookmarkEditorGtk::OnWindowDestroy(GtkWidget* widget,
293 BookmarkEditorGtk* dialog) {
294 MessageLoop::current()->DeleteSoon(FROM_HERE, dialog);
295 }
296
297 // static
298 void BookmarkEditorGtk::OnEntryChanged(GtkEditable* entry,
299 BookmarkEditorGtk* dialog) {
300 const GURL url(dialog->GetInputURL());
301 if (!url.is_valid()) {
302 gtk_widget_modify_base(dialog->url_entry_, GTK_STATE_NORMAL, &kErrorColor);
303 gtk_widget_set_sensitive(GTK_WIDGET(dialog->ok_button_), false);
304 } else {
305 gtk_widget_modify_base(dialog->url_entry_, GTK_STATE_NORMAL, NULL);
306 gtk_widget_set_sensitive(GTK_WIDGET(dialog->ok_button_), true);
307 }
308 }
OLDNEW
« no previous file with comments | « chrome/browser/gtk/bookmark_editor_gtk.h ('k') | chrome/browser/views/bookmark_bubble_view.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698