Index: chrome/browser/ui/views/echo_dialog_views_chromeos.cc |
diff --git a/chrome/browser/ui/views/echo_dialog_views_chromeos.cc b/chrome/browser/ui/views/echo_dialog_views_chromeos.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..2ff62c47c50a59ae02d706f1d30eee7f651c1f1d |
--- /dev/null |
+++ b/chrome/browser/ui/views/echo_dialog_views_chromeos.cc |
@@ -0,0 +1,413 @@ |
+// Copyright 2013 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/ui/views/echo_dialog_views_chromeos.h" |
+ |
+#include "chrome/browser/ui/echo_dialog_listener_chromeos.h" |
+#include "grit/generated_resources.h" |
+#include "ui/base/l10n/l10n_util.h" |
+#include "ui/base/resource/resource_bundle.h" |
+#include "ui/base/text/text_elider.h" |
+#include "ui/views/controls/label.h" |
+#include "ui/views/controls/link.h" |
+#include "ui/views/layout/box_layout.h" |
+#include "ui/views/widget/widget.h" |
+#include "ui/views/window/dialog_client_view.h" |
+ |
+namespace { |
+ |
+const int kDialogContentWidth = 350; |
+ |
+const int kDialogContentTopInset = 20; |
+const int kDialogContentLeftInset = 20; |
+const int kDialogContentBottomInset = 20; |
+const int kDialogContentRightInset = 100; |
+ |
+const int kLinkLeftInset = 5; |
+ |
+// Dialog text has medium sized font. |
+gfx::Font GetDefaultFontForEcho() { |
+ return ui::ResourceBundle::GetSharedInstance().GetFont( |
+ ui::ResourceBundle::MediumFont); |
+} |
+ |
+// Label that shows the service name label. |
+// The label should have underlined text and display tooltip on hover. |
+class EchoServiceNameLabel : public views::Label { |
+ public: |
+ EchoServiceNameLabel(const string16& label, const string16& tooltip) |
+ : views::Label(label) { |
+ SetTooltipText(tooltip); |
+ SetMultiLine(false); |
+ SetFont(GetDefaultFontForEcho().DeriveFont(0, gfx::Font::UNDERLINE)); |
+ } |
+ virtual ~EchoServiceNameLabel() {} |
+ |
+ // views::Label override. |
+ // Label have HitTestRect return false by default. To be able to show a |
+ // tooltip, this should be overriden. |
+ virtual bool HitTestRect(const gfx::Rect& rect) const { |
sky
2013/02/26 21:28:48
This is a bug in Label, it should be fixed there.
tbarzic
2013/02/26 23:08:50
ok, I'll upload a cl to fix this in label
tbarzic
2013/03/18 18:21:58
Done.
|
+ return GetLocalBounds().Intersects(rect); |
+ } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(EchoServiceNameLabel); |
+}; |
+ |
+// A helper view that contains horizontal set of labels representing one row of |
+// the dialog text content. The number of labels is not limited, but their |
+// combined width will be smaller than |kDialogContentWidth|. |
+class EchoDialogContentRowView : public views::View { |
+ public: |
+ EchoDialogContentRowView() { |
+ SetLayoutManager( |
+ new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0)); |
+ } |
+ |
+ virtual ~EchoDialogContentRowView() {} |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(EchoDialogContentRowView); |
+}; |
+ |
+// View representing text content of the dialog. It consists of set of |
+// vertically laid out |EchoDialogContentRowView| views with limited width. The |
+// rows are filled with text pieces that should be displayed using different |
+// styles. |
+class EchoDialogContentView : public views::View { |
sky
2013/02/26 21:28:48
Is there a reason not to use label directly? If yo
tbarzic
2013/02/26 23:08:50
It's also the label types are different: only part
sky
2013/02/27 00:38:35
2013/02/26 23:08:50, tbarzic wrote:
|
+ public: |
+ explicit EchoDialogContentView(views::LinkListener* listener); |
+ virtual ~EchoDialogContentView() {} |
+ |
+ // Creates text pieces that represent the content shown in the dialog when |
+ // echo extension is enabled to redeem offers. |
+ // |
+ // General layout of the dialog in this case is: |
+ // |
+ // -------------------------------------------------------------- |
+ // | ----------------- ---------------- ----------------- | |
+ // | | normal text 1 | | service name | | normal text 2 | | |
+ // | ----------------- ---------------- ----------------- | |
+ // | ---------------------------------------------------------- | |
+ // | | normal text 2 | | |
+ // | ---------------------------------------------------------- | |
+ // | ----------------- --------------------- | |
+ // | | normal text 2 | | 'More info' link | | |
+ // | ----------------- --------------------- | |
+ // -------------------------------------------------------------- |
+ // |
+ // Where 'normal text' is predetermined text of type TEXT_PIECE_LABEL, |
+ // 'service name' equals |service_name| and is of type |
+ // TEXT_PIECE_SERVICE_NAME_LABEL. Hovering over the 'service name' label will |
+ // display tooltip whose content equals |origin|. |
+ // Note that the labels may be broken up, preferably at word delimiters (this |
+ // is not possible for words that are too long). |
+ void InitializeForEnabledEcho(const string16& service_name, |
+ const string16& origin); |
+ |
+ // Creates text pieces that represent the content shown in the dialog when |
+ // echo extension is not allowed to redeem offers. |
+ // |
+ // General layout of the dialog in this case is: |
+ // |
+ // -------------------------------------------------------------- |
+ // | ---------------------------------------------------------- | |
+ // | | normal text 1 | | |
+ // | ---------------------------------------------------------- | |
+ // | ----------------- --------------------- | |
+ // | | normal text 1 | | 'More info' link | | |
+ // | ----------------- --------------------- | |
+ // -------------------------------------------------------------- |
+ // |
+ // With the same parts as for the enabled echo. |
+ void InitializeForDisabledEcho(); |
+ |
+ // Creates layout with text pieces initialized in |
+ // |InitializeFor{Disabled|Enabled}Echo|. |
+ void SetupLayout(); |
+ |
+ private: |
+ enum TextPieceType { |
+ TEXT_PIECE_INVALID, |
+ TEXT_PIECE_LABEL, |
+ TEXT_PIECE_SERVICE_NAME_LABEL, |
+ TEXT_PIECE_LINK |
+ }; |
+ |
+ // Information about a text piece that should be shown in the dialog. |
+ struct TextPieceInfo { |
+ TextPieceInfo() : type(TEXT_PIECE_INVALID) {} |
+ TextPieceInfo(const string16& label, |
+ TextPieceType type) |
+ : label(label), |
+ type(type) { |
+ } |
+ |
+ string16 label; |
+ TextPieceType type; |
+ }; |
+ |
+ // Adds text piece described with |info| to the |current_row|. |
+ // If the whole text piece doesn't fit in the row, the row is filled with as |
+ // much of words from the text piece as possible. New row are created and |
+ // filled with text pieces content until the whole text piece is added to the |
+ // layout. |
+ // Upon completion |current_row| will be set to the last added row. |
+ void SetupTextPieceLayout(const TextPieceInfo& info, |
+ EchoDialogContentRowView** current_row); |
+ // Creates a label view for text piece of type |type| with content |text|. |
+ // |at_row_start| is set if the text_piece would be the first text piece in |
+ // the row. Links are added additional padding if they are not at the row |
+ // start. |
+ views::Label* CreateTextPieceView(TextPieceType type, |
+ const string16& label, |
+ bool at_row_start); |
+ |
+ string16 service_origin_; |
+ // Listener invoked when a label of type link is clicked. |
+ views::LinkListener* link_listener_; |
+ // Dialog content divided into pieces with different display stype. |
+ std::vector<TextPieceInfo> text_pieces_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(EchoDialogContentView); |
+}; |
+ |
+EchoDialogContentView::EchoDialogContentView(views::LinkListener* link_listener) |
+ : link_listener_(link_listener) { |
+ SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0 ,0)); |
+} |
+ |
+void EchoDialogContentView::InitializeForEnabledEcho( |
+ const string16& service_name, |
+ const string16& origin) { |
+ service_origin_ = origin; |
+ |
+ size_t service_name_offset = 0; |
+ string16 text = l10n_util::GetStringFUTF16(IDS_ECHO_CONSENT_DIALOG_TEXT, |
+ service_name, |
+ &service_name_offset); |
+ |
+ text_pieces_.push_back( |
+ TextPieceInfo(text.substr(0, service_name_offset), TEXT_PIECE_LABEL)); |
+ text_pieces_.push_back( |
+ TextPieceInfo(service_name, TEXT_PIECE_SERVICE_NAME_LABEL)); |
+ text_pieces_.push_back( |
+ TextPieceInfo(text.substr(service_name_offset + service_name.length()), |
+ TEXT_PIECE_LABEL)); |
+ text_pieces_.push_back(TextPieceInfo( |
+ l10n_util::GetStringUTF16(IDS_OFFERS_CONSENT_INFOBAR_LABEL_LEARN_MORE), |
+ TEXT_PIECE_LINK)); |
+} |
+ |
+void EchoDialogContentView::InitializeForDisabledEcho() { |
+ text_pieces_.push_back(TextPieceInfo( |
+ l10n_util::GetStringUTF16(IDS_ECHO_DISABLED_CONSENT_DIALOG_TEXT), |
+ TEXT_PIECE_LABEL)); |
+ text_pieces_.push_back(TextPieceInfo( |
+ l10n_util::GetStringUTF16(IDS_OFFERS_CONSENT_INFOBAR_LABEL_LEARN_MORE), |
+ TEXT_PIECE_LINK)); |
+} |
+ |
+void EchoDialogContentView::SetupLayout() { |
+ EchoDialogContentRowView* current_row = new EchoDialogContentRowView(); |
+ AddChildView(current_row); |
+ for (size_t i= 0; i < text_pieces_.size(); ++i) |
+ SetupTextPieceLayout(text_pieces_[i], ¤t_row); |
+ |
+ set_border(views::Border::CreateEmptyBorder(kDialogContentTopInset, |
+ kDialogContentLeftInset, |
+ kDialogContentBottomInset, |
+ kDialogContentRightInset)); |
+} |
+ |
+void EchoDialogContentView::SetupTextPieceLayout( |
+ const TextPieceInfo& info, |
+ EchoDialogContentRowView** current_row) { |
+ if (info.label.empty()) |
+ return; |
+ |
+ gfx::Size current_size = (*current_row)->GetPreferredSize(); |
+ |
+ scoped_ptr<views::Label> text_piece( |
+ CreateTextPieceView(info.type, info.label, current_size.width() == 0)); |
+ gfx::Size text_piece_size = text_piece->GetPreferredSize(); |
+ |
+ // If the while label can fit in the free space in the current row, just add |
+ // it and return. |
+ if (text_piece_size.width() + current_size.width() < kDialogContentWidth) { |
+ (*current_row)->AddChildView(text_piece.release()); |
+ return; |
+ } |
+ |
+ string16 residue = info.label; |
+ gfx::Font text_piece_font = text_piece->font(); |
+ std::vector<string16> lines; |
+ |
+ // Fill up the free space in the current row. |IGNORE_LONG_WORDS| is used to |
+ // ensure words don't get broken in pieces. This step can be skipped if the |
+ // current row is empty. |
+ if (current_size.width() > 0) { |
+ ui::ElideRectangleText(info.label, text_piece_font, |
+ kDialogContentWidth - current_size.width(), text_piece_size.height(), |
+ ui::IGNORE_LONG_WORDS, &lines); |
+ if (!lines[0].empty()) { |
+ text_piece->SetText(lines[0]); |
+ (*current_row)->AddChildView(text_piece.release()); |
+ |
+ // Compute the part of the text piece that still has to be added to the |
+ // view layout. |
+ residue = info.label.substr(lines[0].length()); |
+ TrimWhitespace(residue, TRIM_LEADING, &residue); |
+ } |
+ } |
+ |
+ // Brake up the rest of the text piece into lines shorter than |
+ // |kEchoPromtWidth|, so they can fit in a single row. Use INT_MAX so the |
+ // number of lines is not limited. |
+ ui::ElideRectangleText(residue, text_piece_font, kDialogContentWidth, INT_MAX, |
+ ui::WRAP_LONG_WORDS, &lines); |
+ |
+ // Add lines one by one to the layout. |
+ for (size_t i = 0; i < lines.size(); ++i) { |
+ if ((*current_row)->GetPreferredSize().width() > 0) { |
+ *current_row = new EchoDialogContentRowView(); |
+ AddChildView(*current_row); |
+ } |
+ (*current_row)->AddChildView(CreateTextPieceView(info.type, lines[i], |
+ true)); |
+ } |
+} |
+ |
+views::Label* EchoDialogContentView::CreateTextPieceView(TextPieceType type, |
+ const string16& text, |
+ bool at_row_start) { |
+ switch (type) { |
+ case TEXT_PIECE_LABEL: |
+ { |
+ views::Label* label = new views::Label(text); |
+ label->SetMultiLine(false); |
+ label->SetFont(GetDefaultFontForEcho()); |
+ return label; |
+ } |
+ case TEXT_PIECE_SERVICE_NAME_LABEL: |
+ return new EchoServiceNameLabel(text, service_origin_); |
+ case TEXT_PIECE_LINK: |
+ { |
+ views::Link* link = new views::Link(text); |
+ link->set_listener(link_listener_); |
+ link->SetUnderline(false); |
+ link->SetFont(GetDefaultFontForEcho()); |
+ if (!at_row_start) { |
+ link->set_border( |
+ views::Border::CreateEmptyBorder(0, kLinkLeftInset, 0, 0)); |
+ } |
+ return link; |
+ } |
+ default: |
+ NOTREACHED(); |
+ return NULL; |
+ } |
+} |
+ |
+} // namespace |
+ |
+EchoDialogView::EchoDialogView(EchoDialogListener* listener) |
+ : listener_(listener), |
+ ok_button_label_id_(0), |
+ cancel_button_label_id_(0) { |
+ SetLayoutManager( |
+ new views::BoxLayout(views::BoxLayout::kVertical, 0, 0 ,0)); |
+} |
+ |
+EchoDialogView::~EchoDialogView() {} |
+ |
+void EchoDialogView::InitForEnabledEcho(const string16& service_name, |
+ const string16& origin) { |
+ ok_button_label_id_ = IDS_OFFERS_CONSENT_INFOBAR_ENABLE_BUTTON; |
+ cancel_button_label_id_ = IDS_OFFERS_CONSENT_INFOBAR_DISABLE_BUTTON; |
+ |
+ EchoDialogContentView* dialog_content = new EchoDialogContentView(this); |
+ dialog_content->InitializeForEnabledEcho(service_name, origin); |
+ dialog_content->SetupLayout(); |
+ |
+ AddChildView(dialog_content); |
+} |
+ |
+void EchoDialogView::InitForDisabledEcho() { |
+ ok_button_label_id_ = 0; |
+ cancel_button_label_id_ = IDS_ECHO_CONSENT_DISMISS_BUTTON; |
+ |
+ EchoDialogContentView* dialog_content = new EchoDialogContentView(this); |
+ dialog_content->InitializeForDisabledEcho(); |
+ dialog_content->SetupLayout(); |
+ |
+ AddChildView(dialog_content); |
+} |
+ |
+void EchoDialogView::Show(gfx::NativeWindow parent) { |
+ DCHECK(cancel_button_label_id_); |
+ |
+ views::DialogDelegateView::CreateDialogWidget(this, parent, parent); |
+ set_border(views::Border::CreateEmptyBorder(0, 0, 10, 0)); |
+ GetWidget()->Show(); |
+} |
+ |
+int EchoDialogView::GetDefaultDialogButton() const { |
+ return ui::DIALOG_BUTTON_NONE; |
+} |
+ |
+int EchoDialogView::GetDialogButtons() const { |
+ int buttons = ui::DIALOG_BUTTON_NONE; |
+ if (ok_button_label_id_) |
+ buttons |= ui::DIALOG_BUTTON_OK; |
+ if (cancel_button_label_id_) |
+ buttons |= ui::DIALOG_BUTTON_CANCEL; |
+ return buttons; |
+} |
+ |
+bool EchoDialogView::Accept() { |
+ if (listener_) { |
+ listener_->OnAccept(); |
+ listener_ = NULL; |
+ } |
+ return true; |
+} |
+ |
+bool EchoDialogView::Cancel() { |
+ if (listener_) { |
+ listener_->OnCancel(); |
+ listener_ = NULL; |
+ } |
+ return true; |
+} |
+ |
+string16 EchoDialogView::GetDialogButtonLabel(ui::DialogButton button) const { |
+ if (button == ui::DIALOG_BUTTON_OK && ok_button_label_id_) |
+ return l10n_util::GetStringUTF16(ok_button_label_id_); |
+ if (button == ui::DIALOG_BUTTON_CANCEL && cancel_button_label_id_) |
+ return l10n_util::GetStringUTF16(cancel_button_label_id_); |
+ return string16(); |
+} |
+ |
+ui::ModalType EchoDialogView::GetModalType() const { |
+ return ui::MODAL_TYPE_WINDOW; |
+} |
+ |
+bool EchoDialogView::ShouldShowWindowTitle() const { |
+ return false; |
+} |
+ |
+bool EchoDialogView::ShouldShowWindowIcon() const { |
+ return false; |
+} |
+ |
+void EchoDialogView::LinkClicked(views::Link* source, int event_flags) { |
+ if (!listener_) |
+ return; |
+ listener_->OnMoreInfoLinkClicked(); |
+} |
+ |
+EchoDialog* EchoDialog::Create(EchoDialogListener* listener) { |
+ return new EchoDialogView(listener); |
+} |