blob: ab07b3ad003c65b2c78497d18eb2ddb1de909105 [file] [log] [blame]
// 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_NATIVE_THEME_NATIVE_THEME_BASE_H_
#define UI_NATIVE_THEME_NATIVE_THEME_BASE_H_
#include <array>
#include <optional>
#include "base/component_export.h"
#include "base/containers/span.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkRect.h"
#include "ui/color/color_id.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/size.h"
#include "ui/native_theme/native_theme.h"
namespace cc {
class PaintCanvas;
}
namespace ui {
class ColorProvider;
class NativeThemeBaseTest;
class COMPONENT_EXPORT(NATIVE_THEME) NativeThemeBase : public NativeTheme {
public:
NativeThemeBase(const NativeThemeBase&) = delete;
NativeThemeBase& operator=(const NativeThemeBase&) = delete;
// NativeTheme:
gfx::Size GetPartSize(Part part,
State state,
const ExtraParams& extra_params) const override;
float GetBorderRadiusForPart(Part part,
float width,
float height) const override;
SkColor GetScrollbarThumbColor(
const ColorProvider* color_provider,
State state,
const ScrollbarThumbExtraParams& extra_params) const override;
protected:
enum ControlColorId {
kBorder,
kDisabledBorder,
kHoveredBorder,
kPressedBorder,
kAccent,
kDisabledAccent,
kHoveredAccent,
kPressedAccent,
kCheckboxBackground,
kDisabledCheckboxBackground,
kFill,
kDisabledFill,
kHoveredFill,
kPressedFill,
kLightenLayer,
kProgressValue,
kSlider,
kDisabledSlider,
kHoveredSlider,
kPressedSlider,
kSliderBorder,
kHoveredSliderBorder,
kPressedSliderBorder,
kAutoCompleteBackground,
kScrollbarArrowBackground,
kScrollbarArrowBackgroundDisabled,
kScrollbarArrowBackgroundHovered,
kScrollbarArrowBackgroundPressed,
kScrollbarArrow,
kScrollbarArrowDisabled,
kScrollbarArrowHovered,
kScrollbarArrowPressed,
// TODO(crbug.com/40242489): kScrollbarCorner overlaps with
// NativeTheme::Part::kScrollbarCorner. Make ControlColorId a enum class
// or remove the class completely in favor of ColorProvider colors.
kScrollbarCornerControlColorId,
kScrollbarTrack,
kScrollbarThumb,
kScrollbarThumbHovered,
kScrollbarThumbPressed,
kButtonBorder,
kButtonDisabledBorder,
kButtonHoveredBorder,
kButtonPressedBorder,
kButtonFill,
kButtonDisabledFill,
kButtonHoveredFill,
kButtonPressedFill
};
static constexpr auto kButtonBorderColors =
std::to_array({kButtonDisabledBorder, kButtonHoveredBorder, kButtonBorder,
kButtonPressedBorder});
using NativeTheme::NativeTheme;
~NativeThemeBase() override;
// NativeTheme:
void PaintImpl(cc::PaintCanvas* canvas,
const ColorProvider* color_provider,
Part part,
State state,
const gfx::Rect& rect,
const ExtraParams& extra_params,
bool forced_colors,
bool dark_mode,
PreferredContrast contrast,
std::optional<SkColor> accent_color) const override;
// Returns the size of a vertical scrollbar button. Horizontal scrollbars
// transpose this value.
//
// NOTE: The width here is also assumed to be the track width, so should be
// nonzero even if buttons should not be drawn.
virtual gfx::Size GetVerticalScrollbarButtonSize() const;
// Returns the size of a vertical scrollbar thumb. Horizontal scrollbars
// transpose this value.
virtual gfx::Size GetVerticalScrollbarThumbSize() const;
// Returns the scrollbar arrow rect, given an arrow button rect of `rect`.
virtual gfx::RectF GetArrowRect(const gfx::Rect& rect,
Part part,
State state) const;
virtual SkColor GetControlColor(ControlColorId color_id,
bool dark_mode,
PreferredContrast contrast,
const ColorProvider* color_provider) const;
// Returns any custom color ID to use based on `state` and `extra_params`. If
// this returns null, the default thumb color for the state will be used.
virtual std::optional<ColorId> GetScrollbarThumbColorId(
State state,
const ScrollbarThumbExtraParams& extra_params) const;
// Returns the amount a hovered or pressed scrollbar part should contrast with
// the normal version of that part. Used when there is a custom scrollbar part
// color to try and mimic the default behavior.
virtual float GetScrollbarPartContrastRatioForState(State state) const;
virtual void PaintFrameTopArea(
cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const FrameTopAreaExtraParams& extra_params) const;
virtual void PaintMenuPopupBackground(
cc::PaintCanvas* canvas,
const ColorProvider* color_provider,
const gfx::Size& size,
const MenuBackgroundExtraParams& extra_params) const;
virtual void PaintMenuSeparator(
cc::PaintCanvas* canvas,
const ColorProvider* color_provider,
State state,
const gfx::Rect& rect,
const MenuSeparatorExtraParams& extra_params) const;
// Paints arrow buttons for scrollbars and inner spin buttons.
virtual void PaintArrowButton(
cc::PaintCanvas* canvas,
const ColorProvider* color_provider,
const gfx::Rect& rect,
Part part,
State state,
bool forced_colors,
bool dark_mode,
PreferredContrast contrast,
const ScrollbarArrowExtraParams& extra_params) const;
virtual void PaintScrollbarThumb(
cc::PaintCanvas* canvas,
const ColorProvider* color_provider,
Part part,
State state,
const gfx::Rect& rect,
const ScrollbarThumbExtraParams& extra_params) const;
virtual void PaintScrollbarTrack(
cc::PaintCanvas* canvas,
const ColorProvider* color_provider,
Part part,
State state,
const ScrollbarTrackExtraParams& extra_params,
const gfx::Rect& rect,
bool forced_colors,
PreferredContrast contrast) const;
virtual void PaintScrollbarCorner(
cc::PaintCanvas* canvas,
const ColorProvider* color_provider,
State state,
const gfx::Rect& rect,
const ScrollbarTrackExtraParams& extra_params) const;
// Selects a color from `colors` based on `state`, then returns the physical
// color. `colors` must be in the same order as the actual `State` enum.
SkColor GetControlColorForState(base::span<const ControlColorId, 4> colors,
State state,
bool dark_mode,
PreferredContrast contrast,
const ColorProvider* color_provider) const;
SkColor GetScrollbarArrowBackgroundColor(
const ScrollbarArrowExtraParams& extra_params,
State state,
bool dark_mode,
PreferredContrast contrast,
const ColorProvider* color_provider) const;
SkColor GetScrollbarArrowForegroundColor(
SkColor bg_color,
const ScrollbarArrowExtraParams& extra_params,
State state,
bool dark_mode,
PreferredContrast contrast,
const ColorProvider* color_provider) const;
// For disabled controls, lightens the background so the translucent disabled
// color works regardless of what it's over.
void PaintLightenLayer(cc::PaintCanvas* canvas,
const ColorProvider* color_provider,
const SkRect& skrect,
State state,
float border_radius,
bool dark_mode,
PreferredContrast contrast) const;
// Paints arrows for scrollbars and inner spin buttons.
void PaintArrow(cc::PaintCanvas* canvas,
const gfx::Rect& rect,
Part part,
State state,
SkColor color) const;
private:
friend class NativeThemeBaseTest;
static constexpr auto kBorderColors =
std::to_array({kDisabledBorder, kHoveredBorder, kBorder, kPressedBorder});
static constexpr auto kAccentColors =
std::to_array({kDisabledAccent, kHoveredAccent, kAccent, kPressedAccent});
static constexpr auto kCheckboxBackgroundColors =
std::to_array({kDisabledCheckboxBackground, kCheckboxBackground,
kCheckboxBackground, kCheckboxBackground});
static constexpr auto kFillColors =
std::to_array({kDisabledFill, kHoveredFill, kFill, kPressedFill});
static constexpr auto kSliderColors =
std::to_array({kDisabledSlider, kHoveredSlider, kSlider, kPressedSlider});
static constexpr auto kSliderBorderColors =
std::to_array({kDisabledBorder, kHoveredSliderBorder, kSliderBorder,
kPressedSliderBorder});
static SkPath PathForArrow(const gfx::RectF& rect, Part part);
// Like `GetControlColorForState()`; however, if `accent_color` is non-null
// and `state` is not `kDisabled`, overrides the default colors with computed
// ones based on `accent_color`.
SkColor GetAccentOrControlColorForState(
std::optional<SkColor> accent_color,
base::span<const ControlColorId, 4> colors,
State state,
bool dark_mode,
PreferredContrast contrast,
const ColorProvider* color_provider) const;
// Adjusts custom scrollbar button/thumb colors to meet contrast minima. When
// `state` is hovered or pressed, `color` (if present) will be adjusted to
// contrast with the normal state. If `bg_color` is present, also attempts to
// ensure `color` maintains visible contrast with it.
std::optional<SkColor> GetContrastingColorForScrollbarPart(
std::optional<SkColor> color,
std::optional<SkColor> bg_color,
State state) const;
void PaintCheckbox(cc::PaintCanvas* canvas,
const ColorProvider* color_provider,
State state,
const gfx::Rect& rect,
const ButtonExtraParams& extra_params,
bool dark_mode,
PreferredContrast contrast,
std::optional<SkColor> accent_color) const;
void PaintInnerSpinButton(cc::PaintCanvas* canvas,
const ColorProvider* color_provider,
State state,
gfx::Rect rect,
const InnerSpinButtonExtraParams& extra_params,
bool forced_colors,
bool dark_mode,
PreferredContrast contrast) const;
void PaintMenuList(cc::PaintCanvas* canvas,
const ColorProvider* color_provider,
State state,
const gfx::Rect& rect,
const MenuListExtraParams& extra_params,
bool dark_mode,
PreferredContrast contrast) const;
void PaintProgressBar(cc::PaintCanvas* canvas,
const ColorProvider* color_provider,
State state,
const gfx::Rect& rect,
const ProgressBarExtraParams& extra_params,
bool dark_mode,
PreferredContrast contrast,
std::optional<SkColor> accent_color) const;
void PaintButton(cc::PaintCanvas* canvas,
const ColorProvider* color_provider,
State state,
const gfx::Rect& rect,
const ButtonExtraParams& extra_params,
bool dark_mode,
PreferredContrast contrast) const;
void PaintRadio(cc::PaintCanvas* canvas,
const ColorProvider* color_provider,
State state,
const gfx::Rect& rect,
const ButtonExtraParams& extra_params,
bool dark_mode,
PreferredContrast contrast,
std::optional<SkColor> accent_color) const;
void PaintSliderTrack(cc::PaintCanvas* canvas,
const ColorProvider* color_provider,
State state,
const gfx::Rect& rect,
const SliderExtraParams& extra_params,
bool dark_mode,
PreferredContrast contrast,
std::optional<SkColor> accent_color) const;
void PaintSliderThumb(cc::PaintCanvas* canvas,
const ColorProvider* color_provider,
State state,
const gfx::Rect& rect,
const SliderExtraParams& extra_params,
bool dark_mode,
PreferredContrast contrast,
std::optional<SkColor> accent_color) const;
void PaintTextField(cc::PaintCanvas* canvas,
const ColorProvider* color_provider,
State state,
const gfx::Rect& rect,
const TextFieldExtraParams& extra_params,
bool dark_mode,
PreferredContrast contrast) const;
// Draws the common elements of checkboxes and radio buttons. Returns the
// rectangle within which any additional decorations should be drawn, or empty
// if none.
SkRect PaintCheckboxRadioCommon(cc::PaintCanvas* canvas,
const ColorProvider* color_provider,
State state,
const gfx::Rect& rect,
const ButtonExtraParams& extra_params,
bool is_checkbox,
float border_radius,
bool dark_mode,
PreferredContrast contrast,
std::optional<SkColor> accent_color) const;
};
} // namespace ui
#endif // UI_NATIVE_THEME_NATIVE_THEME_BASE_H_