1// Copyright (c) 2012 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/ui/gtk/infobars/confirm_infobar_gtk.h"
6
7#include <gtk/gtk.h>
8
9#include "base/strings/utf_string_conversions.h"
10#include "chrome/browser/ui/gtk/event_utils.h"
11#include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
12#include "chrome/browser/ui/gtk/gtk_chrome_shrinkable_hbox.h"
13#include "chrome/browser/ui/gtk/gtk_util.h"
14#include "ui/base/gtk/gtk_signal_registrar.h"
15
16
17// ConfirmInfoBarDelegate ------------------------------------------------------
18
19InfoBar* ConfirmInfoBarDelegate::CreateInfoBar(InfoBarService* owner) {
20  return new ConfirmInfoBarGtk(owner, this);
21}
22
23
24// ConfirmInfoBarGtk -----------------------------------------------------------
25
26ConfirmInfoBarGtk::ConfirmInfoBarGtk(InfoBarService* owner,
27                                     ConfirmInfoBarDelegate* delegate)
28    : InfoBarGtk(owner, delegate),
29      confirm_hbox_(NULL),
30      size_group_(NULL) {
31}
32
33ConfirmInfoBarGtk::~ConfirmInfoBarGtk() {
34  if (size_group_)
35    g_object_unref(size_group_);
36}
37
38void ConfirmInfoBarGtk::InitWidgets() {
39  InfoBarGtk::InitWidgets();
40
41  confirm_hbox_ = gtk_chrome_shrinkable_hbox_new(FALSE, FALSE,
42                                                 kEndOfLabelSpacing);
43  // This alignment allocates the confirm hbox only as much space as it
44  // requests, and less if there is not enough available.
45  GtkWidget* align = gtk_alignment_new(0, 0, 0, 1);
46  gtk_container_add(GTK_CONTAINER(align), confirm_hbox_);
47  gtk_box_pack_start(GTK_BOX(hbox()), align, TRUE, TRUE, 0);
48
49  // We add the buttons in reverse order and pack end instead of start so
50  // that the first widget to get shrunk is the label rather than the button(s).
51  AddButton(ConfirmInfoBarDelegate::BUTTON_OK);
52  AddButton(ConfirmInfoBarDelegate::BUTTON_CANCEL);
53
54  std::string label_text = UTF16ToUTF8(GetDelegate()->GetMessageText());
55  GtkWidget* label = CreateLabel(label_text);
56  gtk_util::ForceFontSizePixels(label, 13.4);
57  gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
58  gtk_util::CenterWidgetInHBox(confirm_hbox_, label, true, 0);
59  signals()->Connect(label, "map",
60                     G_CALLBACK(gtk_util::InitLabelSizeRequestAndEllipsizeMode),
61                     NULL);
62
63  std::string link_text = UTF16ToUTF8(GetDelegate()->GetLinkText());
64  if (link_text.empty())
65    return;
66
67  GtkWidget* link = CreateLinkButton(link_text);
68  gtk_misc_set_alignment(GTK_MISC(GTK_CHROME_LINK_BUTTON(link)->label), 0, 0.5);
69  signals()->Connect(link, "clicked", G_CALLBACK(OnLinkClickedThunk), this);
70  gtk_util::SetButtonTriggersNavigation(link);
71  // Until we switch to vector graphics, force the font size.
72  // 13.4px == 10pt @ 96dpi
73  gtk_util::ForceFontSizePixels(GTK_CHROME_LINK_BUTTON(link)->label, 13.4);
74  gtk_util::CenterWidgetInHBox(hbox(), link, true, kEndOfLabelSpacing);
75}
76
77ConfirmInfoBarDelegate* ConfirmInfoBarGtk::GetDelegate() {
78  return delegate()->AsConfirmInfoBarDelegate();
79}
80
81void ConfirmInfoBarGtk::AddButton(ConfirmInfoBarDelegate::InfoBarButton type) {
82  DCHECK(confirm_hbox_);
83  if (delegate()->AsConfirmInfoBarDelegate()->GetButtons() & type) {
84    if (!size_group_)
85      size_group_ = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
86
87    GtkWidget* button = gtk_button_new_with_label(UTF16ToUTF8(
88        delegate()->AsConfirmInfoBarDelegate()->GetButtonLabel(type)).c_str());
89    gtk_size_group_add_widget(size_group_, button);
90
91    gtk_util::CenterWidgetInHBox(confirm_hbox_, button, true, 0);
92    signals()->Connect(button, "clicked",
93                       G_CALLBACK(type == ConfirmInfoBarDelegate::BUTTON_OK ?
94                                  OnOkButtonThunk : OnCancelButtonThunk),
95                       this);
96  }
97}
98
99void ConfirmInfoBarGtk::OnOkButton(GtkWidget* widget) {
100  if (delegate()->AsConfirmInfoBarDelegate()->Accept())
101    RemoveSelf();
102}
103
104void ConfirmInfoBarGtk::OnCancelButton(GtkWidget* widget) {
105  if (delegate()->AsConfirmInfoBarDelegate()->Cancel())
106    RemoveSelf();
107}
108
109void ConfirmInfoBarGtk::OnLinkClicked(GtkWidget* widget) {
110  if (delegate()->AsConfirmInfoBarDelegate()->LinkClicked(
111        event_utils::DispositionForCurrentButtonPressEvent()))
112    RemoveSelf();
113}
114