// Copyright (c) 2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/gtk/about_chrome_dialog.h" #include #include #include "app/l10n_util.h" #include "app/resource_bundle.h" #include "base/file_version_info.h" #include "base/gfx/gtk_util.h" #include "chrome/common/chrome_constants.h" #include "chrome/browser/profile.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" #include "grit/theme_resources.h" #include "webkit/glue/webkit_glue.h" namespace { // The pixel width of the version text field. Ideally, we'd like to have the // bounds set to the edge of the icon. However, the icon is not a view but a // part of the background, so we have to hard code the width to make sure // the version field doesn't overlap it. const int kVersionFieldWidth = 195; // The URLs that you navigate to when clicking the links in the About dialog. const wchar_t* const kChromiumUrl = L"http://www.chromium.org/"; const wchar_t* const kAcknowledgements = L"about:credits"; const wchar_t* const kTOS = L"about:terms"; // Left or right margin. const int kPanelHorizMargin = 13; // Top or bottom margin. const int kPanelVertMargin = 13; // These are used as placeholder text around the links in the text in the about // dialog. const wchar_t* kBeginLinkChr = L"BEGIN_LINK_CHR"; const wchar_t* kBeginLinkOss = L"BEGIN_LINK_OSS"; const wchar_t* kEndLinkChr = L"END_LINK_CHR"; const wchar_t* kEndLinkOss = L"END_LINK_OSS"; const wchar_t* kBeginLink = L"BEGIN_LINK"; const wchar_t* kEndLink = L"END_LINK"; void RemoveText(std::wstring* text, const wchar_t* to_remove) { size_t start = text->find(to_remove, 0); if (start != std::string::npos) { size_t length = wcslen(to_remove); *text = text->substr(0, start) + text->substr(start + length); } } void OnDialogResponse(GtkDialog* dialog, int response_id) { // We're done. gtk_widget_destroy(GTK_WIDGET(dialog)); } void FixLabelWrappingCallback(GtkWidget *label, GtkAllocation *allocation, gpointer data) { gtk_widget_set_size_request(label, allocation->width, -1); } GtkWidget* MakeMarkupLabel(const char* format, const std::wstring& str) { GtkWidget* label = gtk_label_new(NULL); char* markup = g_markup_printf_escaped( format, WideToUTF8(str).c_str()); gtk_label_set_markup(GTK_LABEL(label), markup); g_free(markup); return label; } } // namespace void ShowAboutDialogForProfile(GtkWindow* parent, Profile* profile) { ResourceBundle& rb = ResourceBundle::GetSharedInstance(); static GdkPixbuf* background = rb.GetPixbufNamed(IDR_ABOUT_BACKGROUND); scoped_ptr version_info( FileVersionInfo::CreateFileVersionInfoForCurrentModule()); std::wstring current_version = version_info->file_version(); #if !defined(GOOGLE_CHROME_BUILD) current_version += L" ("; current_version += version_info->last_change(); current_version += L")"; #endif // Build the dialog. GtkWidget* dialog = gtk_dialog_new_with_buttons( l10n_util::GetStringUTF8(IDS_ABOUT_CHROME_TITLE).c_str(), parent, GTK_DIALOG_MODAL, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL); // Pick up the style set in gtk_util.cc:InitRCStyles(). // The layout of this dialog is special because the logo should be flush // with the edges of the window. gtk_widget_set_name(dialog, "about-dialog"); gtk_dialog_set_has_separator(GTK_DIALOG(dialog), FALSE); GtkWidget* content_area = GTK_DIALOG(dialog)->vbox; // Use an event box to get the background painting correctly GtkWidget* ebox = gtk_event_box_new(); gtk_widget_modify_bg(ebox, GTK_STATE_NORMAL, &gfx::kGdkWhite); GtkWidget* hbox = gtk_hbox_new(FALSE, 0); GtkWidget* text_alignment = gtk_alignment_new(0.0, 0.0, 1.0, 1.0); gtk_alignment_set_padding(GTK_ALIGNMENT(text_alignment), kPanelVertMargin, kPanelVertMargin, kPanelHorizMargin, kPanelHorizMargin); GtkWidget* text_vbox = gtk_vbox_new(FALSE, 0); GtkWidget* product_label = MakeMarkupLabel( "%s", l10n_util::GetString(IDS_PRODUCT_NAME)); gtk_box_pack_start(GTK_BOX(text_vbox), product_label, FALSE, FALSE, 0); GtkWidget* version_label = MakeMarkupLabel( "%s", current_version); gtk_label_set_selectable(GTK_LABEL(version_label), TRUE); gtk_box_pack_start(GTK_BOX(text_vbox), version_label, FALSE, FALSE, 0); gtk_container_add(GTK_CONTAINER(text_alignment), text_vbox); gtk_box_pack_start(GTK_BOX(hbox), text_alignment, TRUE, FALSE, 0); GtkWidget* image_vbox = gtk_vbox_new(FALSE, 0); gtk_box_pack_end(GTK_BOX(image_vbox), gtk_image_new_from_pixbuf(background), FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), image_vbox, FALSE, FALSE, 0); gtk_container_add(GTK_CONTAINER(ebox), hbox); gtk_box_pack_start(GTK_BOX(content_area), ebox, TRUE, TRUE, 0); // We use a separate box for the licensing etc. text. See the comment near // the top of this function about using a special layout for this dialog. GtkWidget* vbox = gtk_vbox_new(FALSE, 6); gtk_container_set_border_width(GTK_CONTAINER(vbox), 12); GtkWidget* copyright_label = MakeMarkupLabel( "%s", l10n_util::GetString(IDS_ABOUT_VERSION_COPYRIGHT)); gtk_box_pack_start(GTK_BOX(vbox), copyright_label, TRUE, TRUE, 5); // TODO(erg): Figure out how to really insert links. We could just depend on // (or include the source of) libsexy's SexyUrlLabel gtk widget... std::wstring license = l10n_util::GetString(IDS_ABOUT_VERSION_LICENSE); RemoveText(&license, kBeginLinkChr); RemoveText(&license, kBeginLinkOss); RemoveText(&license, kBeginLink); RemoveText(&license, kEndLinkChr); RemoveText(&license, kEndLinkOss); RemoveText(&license, kEndLink); GtkWidget* license_label = MakeMarkupLabel( "%s", license); gtk_label_set_line_wrap(GTK_LABEL(license_label), TRUE); gtk_misc_set_alignment(GTK_MISC(license_label), 0, 0); gtk_box_pack_start(GTK_BOX(vbox), license_label, TRUE, TRUE, 0); // Hack around Gtk's not-so-good label wrapping, as described here: // http://blog.16software.com/dynamic-label-wrapping-in-gtk g_signal_connect(G_OBJECT(license_label), "size-allocate", G_CALLBACK(FixLabelWrappingCallback), NULL); gtk_box_pack_start(GTK_BOX(content_area), vbox, TRUE, TRUE, 0); g_signal_connect(dialog, "response", G_CALLBACK(OnDialogResponse), NULL); gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); gtk_widget_show_all(dialog); }