| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef UI_VIEWS_CONTROLS_BUTTON_IMAGE_BUTTON_H_ |
| #define UI_VIEWS_CONTROLS_BUTTON_IMAGE_BUTTON_H_ |
| |
| #include <array> |
| #include <memory> |
| #include <utility> |
| |
| #include "base/gtest_prod_util.h" |
| #include "ui/base/models/image_model.h" |
| #include "ui/base/resource/resource_scale_factor.h" |
| #include "ui/gfx/image/image_skia.h" |
| #include "ui/views/controls/button/button.h" |
| #include "ui/views/metadata/view_factory.h" |
| |
| namespace views { |
| |
| class VIEWS_EXPORT ImageButton : public Button { |
| METADATA_HEADER(ImageButton, Button) |
| |
| public: |
| // An enum describing the horizontal alignment of images on Buttons. |
| enum HorizontalAlignment { ALIGN_LEFT = 0, ALIGN_CENTER, ALIGN_RIGHT }; |
| |
| // An enum describing the vertical alignment of images on Buttons. |
| enum VerticalAlignment { ALIGN_TOP = 0, ALIGN_MIDDLE, ALIGN_BOTTOM }; |
| |
| explicit ImageButton(PressedCallback callback = PressedCallback()); |
| |
| ImageButton(const ImageButton&) = delete; |
| ImageButton& operator=(const ImageButton&) = delete; |
| |
| ~ImageButton() override; |
| |
| // Returns the image for a given |state|. |
| virtual gfx::ImageSkia GetImage(ButtonState state) const; |
| |
| virtual void SetImageModel(ButtonState state, |
| const ui::ImageModel& image_model); |
| |
| // Set the background details. The background image uses the same alignment |
| // as the image. |
| void SetBackgroundImage(SkColor color, |
| const gfx::ImageSkia* image, |
| const gfx::ImageSkia* mask); |
| |
| // How the image is laid out within the button's bounds. |
| HorizontalAlignment GetImageHorizontalAlignment() const; |
| VerticalAlignment GetImageVerticalAlignment() const; |
| void SetImageHorizontalAlignment(HorizontalAlignment h_alignment); |
| void SetImageVerticalAlignment(VerticalAlignment v_alignment); |
| |
| // The minimum size of the contents (not including the border). The contents |
| // will be at least this size, but may be larger if the image itself is |
| // larger. |
| gfx::Size GetMinimumImageSize() const; |
| void SetMinimumImageSize(const gfx::Size& size); |
| |
| // Whether we should draw our images resources horizontally flipped. |
| void SetDrawImageMirrored(bool mirrored) { draw_image_mirrored_ = mirrored; } |
| |
| // Overridden from View: |
| gfx::Size CalculatePreferredSize( |
| const SizeBounds& available_size) const override; |
| views::PaintInfo::ScaleType GetPaintScaleType() const override; |
| void OnThemeChanged() override; |
| |
| enum class MaterialIconStyle { kSmall, kLarge }; |
| |
| // Static method to create a Icon button with Google Material style |
| // guidelines. |
| static std::unique_ptr<ImageButton> CreateIconButton( |
| PressedCallback callback, |
| const gfx::VectorIcon& icon, |
| const std::u16string& accessible_name, |
| MaterialIconStyle icon_style = MaterialIconStyle::kLarge, |
| std::optional<gfx::Insets> insets = std::nullopt); |
| |
| protected: |
| // Overridden from Button: |
| void PaintButtonContents(gfx::Canvas* canvas) override; |
| |
| // Returns the image to paint. This is invoked from paint and returns a value |
| // from images. |
| virtual gfx::ImageSkia GetImageToPaint(); |
| |
| // Updates button background for |scale_factor|. |
| void UpdateButtonBackground(ui::ResourceScaleFactor scale_factor); |
| |
| // The images used to render the different states of this button. |
| std::array<ui::ImageModel, STATE_COUNT> images_; |
| |
| gfx::ImageSkia background_image_; |
| |
| private: |
| FRIEND_TEST_ALL_PREFIXES(ImageButtonTest, Basics); |
| FRIEND_TEST_ALL_PREFIXES(ImageButtonTest, ImagePositionWithBorder); |
| FRIEND_TEST_ALL_PREFIXES(ImageButtonTest, LeftAlignedMirrored); |
| FRIEND_TEST_ALL_PREFIXES(ImageButtonTest, RightAlignedMirrored); |
| FRIEND_TEST_ALL_PREFIXES(ImageButtonTest, ImagePositionWithBackground); |
| |
| FRIEND_TEST_ALL_PREFIXES(ImageButtonFactoryTest, CreateVectorImageButton); |
| |
| // Returns the correct position of the image for painting. |
| const gfx::Point ComputeImagePaintPosition(const gfx::ImageSkia& image) const; |
| |
| // Image alignment. |
| HorizontalAlignment h_alignment_ = ALIGN_LEFT; |
| VerticalAlignment v_alignment_ = ALIGN_TOP; |
| gfx::Size minimum_image_size_; |
| |
| // Whether we draw our resources horizontally flipped. This can happen in the |
| // linux titlebar, where image resources were designed to be flipped so a |
| // small curved corner in the close button designed to fit into the frame |
| // resources. |
| bool draw_image_mirrored_ = false; |
| }; |
| |
| BEGIN_VIEW_BUILDER(VIEWS_EXPORT, ImageButton, Button) |
| VIEW_BUILDER_PROPERTY(bool, DrawImageMirrored) |
| VIEW_BUILDER_PROPERTY(ImageButton::HorizontalAlignment, |
| ImageHorizontalAlignment) |
| VIEW_BUILDER_PROPERTY(ImageButton::VerticalAlignment, ImageVerticalAlignment) |
| VIEW_BUILDER_PROPERTY(gfx::Size, MinimumImageSize) |
| VIEW_BUILDER_METHOD(SetImageModel, Button::ButtonState, const ui::ImageModel&) |
| |
| END_VIEW_BUILDER |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // ToggleImageButton |
| // |
| // A toggle-able ImageButton. It swaps out its graphics when toggled. |
| // |
| //////////////////////////////////////////////////////////////////////////////// |
| class VIEWS_EXPORT ToggleImageButton : public ImageButton { |
| METADATA_HEADER(ToggleImageButton, ImageButton) |
| |
| public: |
| explicit ToggleImageButton(PressedCallback callback = PressedCallback()); |
| |
| ToggleImageButton(const ToggleImageButton&) = delete; |
| ToggleImageButton& operator=(const ToggleImageButton&) = delete; |
| |
| ~ToggleImageButton() override; |
| |
| // Change the toggled state. |
| bool GetToggled() const; |
| void SetToggled(bool toggled); |
| |
| // Like ImageButton::SetImage(), but to set the graphics used for the |
| // "has been toggled" state. Must be called for each button state |
| // before the button is toggled. |
| void SetToggledImage(ButtonState state, const gfx::ImageSkia* image); |
| void SetToggledImageModel(ButtonState state, |
| const ui::ImageModel& image_model); |
| |
| // Like Views::SetBackground(), but to set the background color used for the |
| // "has been toggled" state. |
| void SetToggledBackground(std::unique_ptr<Background> b); |
| Background* GetToggledBackground() const { return toggled_background_.get(); } |
| |
| // Get/Set the tooltip text displayed when the button is toggled. |
| std::u16string GetToggledTooltipText() const; |
| void SetToggledTooltipText(const std::u16string& tooltip); |
| |
| // Get/Set the accessible text used when the button is toggled. |
| std::u16string GetToggledAccessibleName() const; |
| void SetToggledAccessibleName(const std::u16string& name); |
| |
| // Overridden from Button: |
| void UpdateAccessibleCheckedState() override; |
| |
| // Overridden from ImageButton: |
| gfx::ImageSkia GetImage(ButtonState state) const override; |
| void SetImageModel(ButtonState state, |
| const ui::ImageModel& image_model) override; |
| |
| // Overridden from View: |
| void OnPaintBackground(gfx::Canvas* canvas) override; |
| |
| void OnTooltipTextChanged(const std::u16string& old_tooltip) override; |
| |
| void UpdateAccessibleRoleIfNeeded(); |
| |
| private: |
| void UpdateAccessibleName(); |
| void UpdateTooltipText(); |
| |
| // The parent class's images_ member is used for the current images, |
| // and this array is used to hold the alternative images. |
| // We swap between the two when toggling. |
| std::array<ui::ImageModel, STATE_COUNT> alternate_images_; |
| |
| // True if the button is currently toggled. |
| bool toggled_ = false; |
| |
| std::unique_ptr<Background> toggled_background_; |
| |
| // The parent class's tooltip_text_ is displayed when not toggled, and |
| // this one is shown when toggled. |
| std::u16string toggled_tooltip_text_; |
| |
| // The parent class's accessibility data is used when not toggled, and this |
| // one is used when toggled. |
| std::u16string toggled_accessible_name_; |
| |
| // The original tooltip text before toggling. |
| std::u16string untoggled_tooltip_text_; |
| }; |
| |
| BEGIN_VIEW_BUILDER(VIEWS_EXPORT, ToggleImageButton, ImageButton) |
| VIEW_BUILDER_PROPERTY(bool, Toggled) |
| VIEW_BUILDER_PROPERTY(std::unique_ptr<Background>, ToggledBackground) |
| VIEW_BUILDER_PROPERTY(std::u16string, ToggledTooltipText) |
| VIEW_BUILDER_PROPERTY(std::u16string, ToggledAccessibleName) |
| VIEW_BUILDER_METHOD(SetToggledImageModel, |
| Button::ButtonState, |
| const ui::ImageModel&) |
| END_VIEW_BUILDER |
| |
| } // namespace views |
| |
| DEFINE_VIEW_BUILDER(VIEWS_EXPORT, ImageButton) |
| DEFINE_VIEW_BUILDER(VIEWS_EXPORT, ToggleImageButton) |
| |
| #endif // UI_VIEWS_CONTROLS_BUTTON_IMAGE_BUTTON_H_ |