// Copyright (c) 2011 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 "views/controls/message_box_view.h" #include "base/i18n/rtl.h" #include "base/message_loop.h" #include "base/utf_string_conversions.h" #include "ui/base/clipboard/clipboard.h" #include "ui/base/clipboard/scoped_clipboard_writer.h" #include "ui/base/message_box_flags.h" #include "views/controls/button/checkbox.h" #include "views/layout/grid_layout.h" #include "views/layout/layout_constants.h" #include "views/views_delegate.h" #include "views/window/client_view.h" static const int kDefaultMessageWidth = 320; /////////////////////////////////////////////////////////////////////////////// // MessageBoxView, public: MessageBoxView::MessageBoxView(int dialog_flags, const std::wstring& message, const std::wstring& default_prompt, int message_width) : message_label_(new views::Label(message)), prompt_field_(NULL), icon_(NULL), checkbox_(NULL), message_width_(message_width), ALLOW_THIS_IN_INITIALIZER_LIST(focus_grabber_factory_(this)) { Init(dialog_flags, default_prompt); } MessageBoxView::MessageBoxView(int dialog_flags, const std::wstring& message, const std::wstring& default_prompt) : message_label_(new views::Label(message)), prompt_field_(NULL), icon_(NULL), checkbox_(NULL), message_width_(kDefaultMessageWidth), ALLOW_THIS_IN_INITIALIZER_LIST(focus_grabber_factory_(this)) { Init(dialog_flags, default_prompt); } std::wstring MessageBoxView::GetInputText() { if (prompt_field_) return UTF16ToWideHack(prompt_field_->text()); return std::wstring(); } bool MessageBoxView::IsCheckBoxSelected() { return checkbox_ ? checkbox_->checked() : false; } void MessageBoxView::SetIcon(const SkBitmap& icon) { if (!icon_) icon_ = new views::ImageView(); icon_->SetImage(icon); icon_->SetBounds(0, 0, icon.width(), icon.height()); ResetLayoutManager(); } void MessageBoxView::SetCheckBoxLabel(const std::wstring& label) { if (!checkbox_) checkbox_ = new views::Checkbox(label); else checkbox_->SetLabel(label); ResetLayoutManager(); } void MessageBoxView::SetCheckBoxSelected(bool selected) { if (!checkbox_) return; checkbox_->SetChecked(selected); } /////////////////////////////////////////////////////////////////////////////// // MessageBoxView, views::View overrides: void MessageBoxView::ViewHierarchyChanged(bool is_add, views::View* parent, views::View* child) { if (child == this && is_add) { if (prompt_field_) prompt_field_->SelectAll(); } } bool MessageBoxView::AcceleratorPressed( const views::Accelerator& accelerator) { // We only accepts Ctrl-C. DCHECK(accelerator.GetKeyCode() == 'C' && accelerator.IsCtrlDown()); // We must not intercept Ctrl-C when we have a text box and it's focused. if (prompt_field_ && prompt_field_->HasFocus()) return false; if (!views::ViewsDelegate::views_delegate) return false; ui::Clipboard* clipboard = views::ViewsDelegate::views_delegate->GetClipboard(); if (!clipboard) return false; ui::ScopedClipboardWriter scw(clipboard); scw.WriteText(WideToUTF16Hack(message_label_->GetText())); return true; } /////////////////////////////////////////////////////////////////////////////// // MessageBoxView, private: void MessageBoxView::Init(int dialog_flags, const std::wstring& default_prompt) { message_label_->SetMultiLine(true); message_label_->SetAllowCharacterBreak(true); if (dialog_flags & ui::MessageBoxFlags::kAutoDetectAlignment) { // Determine the alignment and directionality based on the first character // with strong directionality. base::i18n::TextDirection direction = base::i18n::GetFirstStrongCharacterDirection(message_label_->GetText()); views::Label::Alignment alignment; if (direction == base::i18n::RIGHT_TO_LEFT) alignment = views::Label::ALIGN_RIGHT; else alignment = views::Label::ALIGN_LEFT; // In addition, we should set the RTL alignment mode as // AUTO_DETECT_ALIGNMENT so that the alignment will not be flipped around // in RTL locales. message_label_->set_rtl_alignment_mode(views::Label::AUTO_DETECT_ALIGNMENT); message_label_->SetHorizontalAlignment(alignment); } else { message_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT); } if (dialog_flags & ui::MessageBoxFlags::kFlagHasPromptField) { prompt_field_ = new views::Textfield; prompt_field_->SetText(WideToUTF16Hack(default_prompt)); } ResetLayoutManager(); } void MessageBoxView::ResetLayoutManager() { using views::GridLayout; using views::ColumnSet; // Initialize the Grid Layout Manager used for this dialog box. GridLayout* layout = GridLayout::CreatePanel(this); SetLayoutManager(layout); gfx::Size icon_size; if (icon_) icon_size = icon_->GetPreferredSize(); // Add the column set for the message displayed at the top of the dialog box. // And an icon, if one has been set. const int message_column_view_set_id = 0; ColumnSet* column_set = layout->AddColumnSet(message_column_view_set_id); if (icon_) { column_set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 0, GridLayout::FIXED, icon_size.width(), icon_size.height()); column_set->AddPaddingColumn(0, kUnrelatedControlHorizontalSpacing); } column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, GridLayout::FIXED, message_width_, 0); // Column set for prompt Textfield, if one has been set. const int textfield_column_view_set_id = 1; if (prompt_field_) { column_set = layout->AddColumnSet(textfield_column_view_set_id); if (icon_) { column_set->AddPaddingColumn(0, icon_size.width() + kUnrelatedControlHorizontalSpacing); } column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, GridLayout::USE_PREF, 0, 0); } // Column set for checkbox, if one has been set. const int checkbox_column_view_set_id = 2; if (checkbox_) { column_set = layout->AddColumnSet(checkbox_column_view_set_id); if (icon_) { column_set->AddPaddingColumn(0, icon_size.width() + kUnrelatedControlHorizontalSpacing); } column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, GridLayout::USE_PREF, 0, 0); } layout->StartRow(0, message_column_view_set_id); if (icon_) layout->AddView(icon_); layout->AddView(message_label_); if (prompt_field_) { layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); layout->StartRow(0, textfield_column_view_set_id); layout->AddView(prompt_field_); } if (checkbox_) { layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); layout->StartRow(0, checkbox_column_view_set_id); layout->AddView(checkbox_); } layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); }