blob: 018c797f7f810678545576c3b08a417e14c022a0 [file] [log] [blame]
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_VIEWS_TRANSLATE_TRANSLATE_BUBBLE_VIEW_H_
#define CHROME_BROWSER_UI_VIEWS_TRANSLATE_TRANSLATE_BUBBLE_VIEW_H_
#include <map>
#include <memory>
#include <string>
#include "base/functional/callback_forward.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/translate/chrome_translate_client.h"
#include "chrome/browser/ui/translate/source_language_combobox_model.h"
#include "chrome/browser/ui/translate/target_language_combobox_model.h"
#include "chrome/browser/ui/translate/translate_bubble_model.h"
#include "chrome/browser/ui/translate/translate_bubble_test_utils.h"
#include "chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h"
#include "components/language/core/common/language_experiments.h"
#include "components/translate/core/browser/translate_step.h"
#include "components/translate/core/common/translate_errors.h"
#include "content/public/browser/web_contents_observer.h"
#include "ui/base/interaction/element_identifier.h"
#include "ui/base/models/simple_menu_model.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/menu/menu_runner.h"
#include "ui/views/controls/tabbed_pane/tabbed_pane.h"
#include "ui/views/controls/tabbed_pane/tabbed_pane_listener.h"
#include "ui/views/window/non_client_view.h"
class Browser;
namespace translate {
class TranslateBubbleVisualTest;
} // namespace translate
namespace views {
class Checkbox;
class Combobox;
class LabelButton;
class View;
} // namespace views
class TranslateBubbleView : public LocationBarBubbleDelegateView,
public ui::SimpleMenuModel::Delegate,
public views::TabbedPaneListener {
public:
// Item IDs for the option button's menu.
enum OptionsMenuItem {
ALWAYS_TRANSLATE_LANGUAGE,
NEVER_TRANSLATE_LANGUAGE,
NEVER_TRANSLATE_SITE,
CHANGE_TARGET_LANGUAGE,
CHANGE_SOURCE_LANGUAGE
};
// Element IDs for ui::ElementTracker.
DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kIdentifier);
DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kSourceLanguageTab);
DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kTargetLanguageTab);
DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kCloseButton);
DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kOptionsMenuButton);
DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kChangeTargetLanguage);
DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kTargetLanguageCombobox);
DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kTargetLanguageDoneButton);
DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kChangeSourceLanguage);
DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kSourceLanguageCombobox);
DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kSourceLanguageDoneButton);
DECLARE_CLASS_ELEMENT_IDENTIFIER_VALUE(kErrorMessage);
TranslateBubbleView(views::View* anchor_view,
std::unique_ptr<TranslateBubbleModel> model,
translate::TranslateErrors error_type,
content::WebContents* web_contents,
base::OnceClosure on_closing);
TranslateBubbleView(const TranslateBubbleView&) = delete;
TranslateBubbleView& operator=(const TranslateBubbleView&) = delete;
~TranslateBubbleView() override;
void CloseTranslateBubble();
TranslateBubbleModel* model() { return model_.get(); }
// LocationBarBubbleDelegateView:
void Init() override;
View* GetInitiallyFocusedView() override;
bool ShouldShowCloseButton() const override;
bool ShouldShowWindowTitle() const override;
void WindowClosing() override;
bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
gfx::Size CalculatePreferredSize() const override;
void OnWidgetClosing(views::Widget* widget) override;
// ui::SimpleMenuModel::Delegate:
bool IsCommandIdChecked(int command_id) const override;
bool IsCommandIdEnabled(int command_id) const override;
void ExecuteCommand(int command_id, int event_flags) override;
// Returns the current view state.
TranslateBubbleModel::ViewState GetViewState() const;
// Initialize the bubble in the correct view state when it is shown.
void SetViewState(translate::TranslateStep step,
translate::TranslateErrors error_type);
// LocationBarBubbleDelegateView:
void CloseBubble() override;
private:
// IDs used by TranslateBubbleViewTest to simulate button presses.
enum ButtonID {
BUTTON_ID_DONE = 1,
BUTTON_ID_TRY_AGAIN,
BUTTON_ID_ALWAYS_TRANSLATE,
BUTTON_ID_OPTIONS_MENU,
BUTTON_ID_CLOSE,
BUTTON_ID_RESET
};
friend class TranslateBubbleViewTest;
friend class translate::TranslateBubbleVisualTest;
friend void ::translate::test_utils::PressTranslate(::Browser*);
friend void ::translate::test_utils::PressRevert(::Browser*);
friend void ::translate::test_utils::SelectTargetLanguageByDisplayName(
::Browser*,
const ::std::u16string&);
FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
TargetLanguageTabTriggersTranslate);
FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
AlwaysTranslateCheckboxShortcut);
FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
AlwaysTranslateCheckboxAndCloseButton);
FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
AlwaysTranslateCheckboxAndDoneButton);
FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest, SourceResetButton);
FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest, TargetResetButton);
FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest, SourceDoneButton);
FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest, TargetDoneButton);
FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
DoneButtonWithoutTranslating);
FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
OptionsMenuNeverTranslateLanguage);
FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
OptionsMenuRespectsBlocklistSite);
FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
MenuOptionsHiddenOnUnknownSource);
FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
OptionsMenuNeverTranslateSite);
FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
AlwaysTranslateLanguageMenuItem);
FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
TabSelectedAfterTranslation);
FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
AlwaysTranslateTriggerTranslation);
FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
AlwaysTranslateWithNeverTranslateSite);
FRIEND_TEST_ALL_PREFIXES(TranslateBubbleViewTest,
SourceLanguageTabUpdatesViewState);
// views::TabbedPaneListener:
void TabSelectedAt(int index) override;
// Returns the current child view.
views::View* GetCurrentView() const;
// Triggers options menu.
void ShowOptionsMenu(views::Button* source);
// Handles the event when the user changes an index of a combobox.
void SourceLanguageChanged();
void TargetLanguageChanged();
void AlwaysTranslatePressed();
// Updates the visibilities of child views according to the current view type.
void UpdateChildVisibilities();
// Creates the view used before/during/after translate.
std::unique_ptr<views::View> CreateView();
// AddTab function requires a view element to be shown below each tab.
// This function creates an empty view so no extra white space below the tab.
std::unique_ptr<views::View> CreateEmptyPane();
// Creates the 'error' view for Button UI. Caller takes ownership of the
// returned view.
std::unique_ptr<views::View> CreateViewError();
// Creates the 'error' view skeleton UI with no title. Caller takes ownership
// of the returned view.
std::unique_ptr<views::View> CreateViewErrorNoTitle(
std::unique_ptr<views::Button> advanced_button);
// Creates source language label and combobox for Tab UI advanced view. Caller
// takes ownership of the returned view.
std::unique_ptr<views::View> CreateViewAdvancedSource();
// Creates target language label and combobox for Tab UI advanced view. Caller
// takes ownership of the returned view.
std::unique_ptr<views::View> CreateViewAdvancedTarget();
// Creates the 'advanced' view to show source/target language combobox. Caller
// takes ownership of the returned view.
std::unique_ptr<views::View> CreateViewAdvanced(
std::unique_ptr<views::Combobox> combobox,
std::unique_ptr<views::Label> language_title_label,
std::unique_ptr<views::Button> advanced_reset_button,
std::unique_ptr<views::Button> advanced_done_button,
std::unique_ptr<views::Checkbox> advanced_always_translate_checkbox);
// Creates a translate icon for when the bottom branding isn't showing. This
// should only be used on non-Chrome-branded builds.
std::unique_ptr<views::ImageView> CreateTranslateIcon();
// Creates a three dot options menu button.
std::unique_ptr<views::Button> CreateOptionsMenuButton();
// Creates a close button.
std::unique_ptr<views::Button> CreateCloseButton();
// Get the current always translate checkbox.
views::Checkbox* GetAlwaysTranslateCheckbox();
// Sets the window title. The window title still needs to be set, even when it
// is not shown, for accessibility purposes.
void SetWindowTitle(TranslateBubbleModel::ViewState view_state);
// Updates the view state. Whenever the view state is updated, the title needs
// to be updated for accessibility.
void UpdateViewState(TranslateBubbleModel::ViewState view_state);
// Switches the view type.
void SwitchView(TranslateBubbleModel::ViewState view_state);
// Handles tab switching on when the view type switches.
void SwitchTabForViewState(TranslateBubbleModel::ViewState view_state);
// Switches to the error view.
void SwitchToErrorView(translate::TranslateErrors error_type);
// Updates the advanced view.
void UpdateAdvancedView();
// Actions for button presses shared with accelerators.
void Translate();
void ShowOriginal();
void ConfirmAdvancedOptions();
// Returns whether or not the current language selection is different from the
// initial language selection in an advanced view.
bool DidLanguageSelectionChange(TranslateBubbleModel::ViewState view_state);
// Handles the reset button in advanced view under Tab UI.
void ResetLanguage();
// Retrieve the names of the from/to languages and reset the language
// indices.
void UpdateLanguageNames(std::u16string* source_language_name,
std::u16string* target_language_name);
void UpdateInsets(TranslateBubbleModel::ViewState state);
// If the page is already translated, revert it. Otherwise decline
// translation. Then close the bubble view.
void RevertOrDeclineTranslation();
// Helper method to announce the passed-in text to the screenreader.
void AnnounceTextToScreenReader(const std::u16string& announcement_text);
raw_ptr<views::View, DanglingUntriaged> translate_view_ = nullptr;
raw_ptr<views::View, DanglingUntriaged> error_view_ = nullptr;
raw_ptr<views::View, DanglingUntriaged> advanced_view_source_ = nullptr;
raw_ptr<views::View, DanglingUntriaged> advanced_view_target_ = nullptr;
raw_ptr<views::Combobox, DanglingUntriaged> source_language_combobox_ =
nullptr;
raw_ptr<views::Combobox, DanglingUntriaged> target_language_combobox_ =
nullptr;
raw_ptr<views::Checkbox, DanglingUntriaged> always_translate_checkbox_ =
nullptr;
raw_ptr<views::Checkbox, DanglingUntriaged>
advanced_always_translate_checkbox_ = nullptr;
raw_ptr<views::TabbedPane, DanglingUntriaged> tabbed_pane_ = nullptr;
raw_ptr<views::LabelButton, DanglingUntriaged> advanced_reset_button_source_ =
nullptr;
raw_ptr<views::LabelButton, DanglingUntriaged> advanced_reset_button_target_ =
nullptr;
raw_ptr<views::LabelButton, DanglingUntriaged> advanced_done_button_source_ =
nullptr;
raw_ptr<views::LabelButton, DanglingUntriaged> advanced_done_button_target_ =
nullptr;
// Default source/target language without user interaction.
size_t previous_source_language_index_;
size_t previous_target_language_index_;
std::unique_ptr<ui::SimpleMenuModel> options_menu_model_;
std::unique_ptr<views::MenuRunner> options_menu_runner_;
std::unique_ptr<TranslateBubbleModel> model_;
translate::TranslateErrors error_type_;
// Whether the window is an incognito window.
const bool is_in_incognito_window_;
bool should_always_translate_ = false;
bool should_never_translate_language_ = false;
bool should_never_translate_site_ = false;
std::unique_ptr<WebContentMouseHandler> mouse_handler_;
base::OnceClosure on_closing_;
};
#endif // CHROME_BROWSER_UI_VIEWS_TRANSLATE_TRANSLATE_BUBBLE_VIEW_H_