| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/gtk/extension_shelf_gtk.h" | 5 #include "chrome/browser/gtk/extension_shelf_gtk.h" |
| 6 | 6 |
| 7 #include "chrome/browser/browser.h" | 7 #include "chrome/browser/browser.h" |
| 8 #include "chrome/browser/gtk/browser_window_gtk.h" | 8 #include "chrome/browser/gtk/browser_window_gtk.h" |
| 9 #include "chrome/browser/gtk/gtk_theme_provider.h" | 9 #include "chrome/browser/gtk/gtk_theme_provider.h" |
| 10 #include "chrome/browser/gtk/nine_box.h" | 10 #include "chrome/browser/gtk/nine_box.h" |
| 11 #include "chrome/browser/profile.h" | 11 #include "chrome/browser/profile.h" |
| 12 #include "chrome/common/notification_service.h" | 12 #include "chrome/common/notification_service.h" |
| 13 #include "grit/app_resources.h" | 13 #include "grit/app_resources.h" |
| 14 #include "grit/generated_resources.h" | 14 #include "grit/generated_resources.h" |
| 15 #include "grit/theme_resources.h" | 15 #include "grit/theme_resources.h" |
| 16 | 16 |
| 17 // Preferred height of the ExtensionShelfGtk. |
| 18 static const int kShelfHeight = 29; |
| 19 |
| 20 static const int kToolstripPadding = 2; |
| 21 |
| 22 class ExtensionShelfGtk::Toolstrip { |
| 23 public: |
| 24 explicit Toolstrip(ExtensionHost* host) |
| 25 : host_(host), |
| 26 extension_name_(host_->extension()->name()) { |
| 27 Init(); |
| 28 } |
| 29 |
| 30 ~Toolstrip() { |
| 31 label_.Destroy(); |
| 32 } |
| 33 |
| 34 void AddToolstripToBox(GtkWidget* box); |
| 35 void RemoveToolstripFromBox(GtkWidget* box); |
| 36 |
| 37 private: |
| 38 void Init(); |
| 39 |
| 40 ExtensionHost* host_; |
| 41 |
| 42 const std::string extension_name_; |
| 43 |
| 44 // Placeholder label with extension's name. |
| 45 // TODO(phajdan.jr): replace the label with rendered extension contents. |
| 46 OwnedWidgetGtk label_; |
| 47 |
| 48 private: |
| 49 DISALLOW_COPY_AND_ASSIGN(Toolstrip); |
| 50 }; |
| 51 |
| 52 void ExtensionShelfGtk::Toolstrip::AddToolstripToBox(GtkWidget* box) { |
| 53 gtk_box_pack_start(GTK_BOX(box), label_.get(), FALSE, FALSE, |
| 54 kToolstripPadding); |
| 55 } |
| 56 |
| 57 void ExtensionShelfGtk::Toolstrip::RemoveToolstripFromBox(GtkWidget* box) { |
| 58 gtk_container_remove(GTK_CONTAINER(box), label_.get()); |
| 59 } |
| 60 |
| 61 void ExtensionShelfGtk::Toolstrip::Init() { |
| 62 label_.Own(gtk_label_new(extension_name_.c_str())); |
| 63 gtk_widget_show_all(label_.get()); |
| 64 } |
| 65 |
| 17 ExtensionShelfGtk::ExtensionShelfGtk(Profile* profile, Browser* browser) | 66 ExtensionShelfGtk::ExtensionShelfGtk(Profile* profile, Browser* browser) |
| 18 : browser_(browser), | 67 : browser_(browser), |
| 19 theme_provider_(GtkThemeProvider::GetFrom(profile)), | 68 theme_provider_(GtkThemeProvider::GetFrom(profile)), |
| 20 model_(new ExtensionShelfModel(browser)) { | 69 model_(new ExtensionShelfModel(browser)) { |
| 21 Init(profile); | 70 Init(profile); |
| 22 | 71 |
| 23 registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED, | 72 registrar_.Add(this, NotificationType::BROWSER_THEME_CHANGED, |
| 24 NotificationService::AllSources()); | 73 NotificationService::AllSources()); |
| 25 } | 74 } |
| 26 | 75 |
| 27 ExtensionShelfGtk::~ExtensionShelfGtk() { | 76 ExtensionShelfGtk::~ExtensionShelfGtk() { |
| 28 model_->RemoveObserver(this); | 77 model_->RemoveObserver(this); |
| 29 event_box_.Destroy(); | 78 event_box_.Destroy(); |
| 30 } | 79 } |
| 31 | 80 |
| 32 void ExtensionShelfGtk::AddShelfToBox(GtkWidget* box) { | 81 void ExtensionShelfGtk::AddShelfToBox(GtkWidget* box) { |
| 33 gtk_box_pack_end(GTK_BOX(box), event_box_.get(), FALSE, FALSE, 0); | 82 gtk_box_pack_end(GTK_BOX(box), event_box_.get(), FALSE, FALSE, 0); |
| 34 } | 83 } |
| 35 | 84 |
| 36 void ExtensionShelfGtk::Show() { | 85 void ExtensionShelfGtk::Show() { |
| 37 gtk_widget_show_all(event_box_.get()); | 86 gtk_widget_show_all(event_box_.get()); |
| 38 } | 87 } |
| 39 | 88 |
| 40 void ExtensionShelfGtk::Hide() { | 89 void ExtensionShelfGtk::Hide() { |
| 41 gtk_widget_hide(event_box_.get()); | 90 gtk_widget_hide(event_box_.get()); |
| 42 } | 91 } |
| 43 | 92 |
| 44 void ExtensionShelfGtk::ToolstripInsertedAt(ExtensionHost* toolstrip, | 93 void ExtensionShelfGtk::ToolstripInsertedAt(ExtensionHost* host, |
| 45 int index) { | 94 int index) { |
| 95 Toolstrip* toolstrip = new Toolstrip(host); |
| 96 toolstrip->AddToolstripToBox(shelf_hbox_); |
| 97 toolstrips_.insert(toolstrip); |
| 98 model_->SetToolstripDataAt(index, toolstrip); |
| 99 |
| 46 AdjustHeight(); | 100 AdjustHeight(); |
| 47 } | 101 } |
| 48 | 102 |
| 49 void ExtensionShelfGtk::ToolstripRemovingAt(ExtensionHost* toolstrip, | 103 void ExtensionShelfGtk::ToolstripRemovingAt(ExtensionHost* host, |
| 50 int index) { | 104 int index) { |
| 105 Toolstrip* toolstrip = ToolstripAtIndex(index); |
| 106 toolstrip->RemoveToolstripFromBox(shelf_hbox_); |
| 107 toolstrips_.erase(toolstrip); |
| 108 model_->SetToolstripDataAt(index, NULL); |
| 109 delete toolstrip; |
| 110 |
| 51 AdjustHeight(); | 111 AdjustHeight(); |
| 52 } | 112 } |
| 53 | 113 |
| 54 void ExtensionShelfGtk::ToolstripMoved(ExtensionHost* toolstrip, | 114 void ExtensionShelfGtk::ToolstripMoved(ExtensionHost* host, |
| 55 int from_index, | 115 int from_index, |
| 56 int to_index) { | 116 int to_index) { |
| 117 // TODO(phajdan.jr): Implement reordering toolstrips. |
| 57 AdjustHeight(); | 118 AdjustHeight(); |
| 58 } | 119 } |
| 59 | 120 |
| 60 void ExtensionShelfGtk::ToolstripChangedAt(ExtensionHost* toolstrip, | 121 void ExtensionShelfGtk::ToolstripChangedAt(ExtensionHost* host, |
| 61 int index) { | 122 int index) { |
| 123 // TODO(phajdan.jr): Implement changing toolstrips. |
| 62 AdjustHeight(); | 124 AdjustHeight(); |
| 63 } | 125 } |
| 64 | 126 |
| 65 void ExtensionShelfGtk::ExtensionShelfEmpty() { | 127 void ExtensionShelfGtk::ExtensionShelfEmpty() { |
| 66 AdjustHeight(); | 128 AdjustHeight(); |
| 67 } | 129 } |
| 68 | 130 |
| 69 void ExtensionShelfGtk::ShelfModelReloaded() { | 131 void ExtensionShelfGtk::ShelfModelReloaded() { |
| 70 AdjustHeight(); | 132 for (std::set<Toolstrip*>::iterator iter = toolstrips_.begin(); |
| 133 iter != toolstrips_.end(); ++iter) { |
| 134 (*iter)->RemoveToolstripFromBox(shelf_hbox_); |
| 135 delete *iter; |
| 136 } |
| 137 toolstrips_.clear(); |
| 138 LoadFromModel(); |
| 71 } | 139 } |
| 72 | 140 |
| 73 void ExtensionShelfGtk::Init(Profile* profile) { | 141 void ExtensionShelfGtk::Init(Profile* profile) { |
| 74 event_box_.Own(gtk_event_box_new()); | 142 event_box_.Own(gtk_event_box_new()); |
| 75 | 143 |
| 76 shelf_hbox_ = gtk_hbox_new(FALSE, 0); | 144 shelf_hbox_ = gtk_hbox_new(FALSE, 0); |
| 77 gtk_widget_set_app_paintable(shelf_hbox_, TRUE); | 145 gtk_widget_set_app_paintable(shelf_hbox_, TRUE); |
| 78 g_signal_connect(G_OBJECT(shelf_hbox_), "expose-event", | 146 g_signal_connect(G_OBJECT(shelf_hbox_), "expose-event", |
| 79 G_CALLBACK(&OnHBoxExpose), this); | 147 G_CALLBACK(&OnHBoxExpose), this); |
| 80 gtk_container_add(GTK_CONTAINER(event_box_.get()), shelf_hbox_); | 148 gtk_container_add(GTK_CONTAINER(event_box_.get()), shelf_hbox_); |
| 81 | 149 |
| 82 label_ = gtk_label_new("(extension shelf will appear here)"); | 150 LoadFromModel(); |
| 83 gtk_box_pack_start(GTK_BOX(shelf_hbox_), label_, | |
| 84 TRUE, TRUE, 0); | |
| 85 | |
| 86 AdjustHeight(); | |
| 87 | |
| 88 model_->AddObserver(this); | 151 model_->AddObserver(this); |
| 89 } | 152 } |
| 90 | 153 |
| 91 void ExtensionShelfGtk::Observe(NotificationType type, | 154 void ExtensionShelfGtk::Observe(NotificationType type, |
| 92 const NotificationSource& source, | 155 const NotificationSource& source, |
| 93 const NotificationDetails& details) { | 156 const NotificationDetails& details) { |
| 94 if (type == NotificationType::BROWSER_THEME_CHANGED) { | 157 if (type == NotificationType::BROWSER_THEME_CHANGED) { |
| 95 // TODO(phajdan.jr): Handle theme changes. | 158 // TODO(phajdan.jr): Handle theme changes. |
| 96 } else { | 159 } else { |
| 97 NOTREACHED() << "unexpected notification"; | 160 NOTREACHED() << "unexpected notification"; |
| 98 } | 161 } |
| 99 } | 162 } |
| 100 | 163 |
| 101 void ExtensionShelfGtk::InitBackground() { | 164 void ExtensionShelfGtk::InitBackground() { |
| 102 if (background_ninebox_.get()) | 165 if (background_ninebox_.get()) |
| 103 return; | 166 return; |
| 104 | 167 |
| 105 background_ninebox_.reset(new NineBox( | 168 background_ninebox_.reset(new NineBox( |
| 106 browser_->profile()->GetThemeProvider(), | 169 browser_->profile()->GetThemeProvider(), |
| 107 0, IDR_THEME_TOOLBAR, 0, 0, 0, 0, 0, 0, 0)); | 170 0, IDR_THEME_TOOLBAR, 0, 0, 0, 0, 0, 0, 0)); |
| 108 } | 171 } |
| 109 | 172 |
| 110 void ExtensionShelfGtk::AdjustHeight() { | 173 void ExtensionShelfGtk::AdjustHeight() { |
| 111 if (model_->empty()) { | 174 if (model_->empty() || toolstrips_.empty()) { |
| 175 // It's possible that |model_| is not empty, but |toolstrips_| are empty |
| 176 // when removing the last toolstrip. |
| 177 DCHECK(toolstrips_.empty()); |
| 112 Hide(); | 178 Hide(); |
| 113 } else { | 179 } else { |
| 114 gtk_widget_set_size_request(event_box_.get(), -1, | 180 gtk_widget_set_size_request(event_box_.get(), -1, kShelfHeight); |
| 115 event_box_->requisition.height); | |
| 116 Show(); | 181 Show(); |
| 117 } | 182 } |
| 118 } | 183 } |
| 119 | 184 |
| 185 void ExtensionShelfGtk::LoadFromModel() { |
| 186 DCHECK(toolstrips_.empty()); |
| 187 int count = model_->count(); |
| 188 for (int i = 0; i < count; ++i) |
| 189 ToolstripInsertedAt(model_->ToolstripAt(i), i); |
| 190 AdjustHeight(); |
| 191 } |
| 192 |
| 193 ExtensionShelfGtk::Toolstrip* ExtensionShelfGtk::ToolstripAtIndex(int index) { |
| 194 return static_cast<Toolstrip*>(model_->ToolstripDataAt(index)); |
| 195 } |
| 196 |
| 120 // static | 197 // static |
| 121 gboolean ExtensionShelfGtk::OnHBoxExpose(GtkWidget* widget, | 198 gboolean ExtensionShelfGtk::OnHBoxExpose(GtkWidget* widget, |
| 122 GdkEventExpose* event, | 199 GdkEventExpose* event, |
| 123 ExtensionShelfGtk* bar) { | 200 ExtensionShelfGtk* bar) { |
| 124 // Paint the background theme image. | 201 // Paint the background theme image. |
| 125 cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window)); | 202 cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window)); |
| 126 cairo_rectangle(cr, event->area.x, event->area.y, | 203 cairo_rectangle(cr, event->area.x, event->area.y, |
| 127 event->area.width, event->area.height); | 204 event->area.width, event->area.height); |
| 128 cairo_clip(cr); | 205 cairo_clip(cr); |
| 129 bar->InitBackground(); | 206 bar->InitBackground(); |
| 130 bar->background_ninebox_->RenderTopCenterStrip( | 207 bar->background_ninebox_->RenderTopCenterStrip( |
| 131 cr, event->area.x, event->area.y, | 208 cr, event->area.x, event->area.y, |
| 132 event->area.x + event->area.width); | 209 event->area.x + event->area.width); |
| 133 cairo_destroy(cr); | 210 cairo_destroy(cr); |
| 134 | 211 |
| 135 return FALSE; // Propagate expose to children. | 212 return FALSE; // Propagate expose to children. |
| 136 } | 213 } |
| OLD | NEW |