blob: f50f9b8ae3acdddade9fd40daed7dd7774658b84 [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/views/bubble/bubble_border_arrow_utils.h"
namespace views {
gfx::Point GetArrowAnchorPointFromAnchorRect(BubbleBorder::Arrow arrow,
const gfx::Rect& anchor_rect) {
switch (arrow) {
case BubbleBorder::TOP_LEFT:
return anchor_rect.bottom_left();
case BubbleBorder::TOP_RIGHT:
return anchor_rect.bottom_right();
case BubbleBorder::BOTTOM_LEFT:
return anchor_rect.origin();
case BubbleBorder::BOTTOM_RIGHT:
return anchor_rect.top_right();
case BubbleBorder::LEFT_TOP:
return anchor_rect.top_right();
case BubbleBorder::RIGHT_TOP:
return anchor_rect.origin();
case BubbleBorder::LEFT_BOTTOM:
return anchor_rect.bottom_right();
case BubbleBorder::RIGHT_BOTTOM:
return anchor_rect.bottom_left();
case BubbleBorder::TOP_CENTER:
return anchor_rect.bottom_center();
case BubbleBorder::BOTTOM_CENTER:
return anchor_rect.top_center();
case BubbleBorder::LEFT_CENTER:
return anchor_rect.right_center();
case BubbleBorder::RIGHT_CENTER:
return anchor_rect.left_center();
default:
NOTREACHED();
}
}
gfx::Vector2d GetContentBoundsOffsetToArrowAnchorPoint(
const gfx::Rect& contents_bounds,
BubbleBorder::Arrow arrow,
const gfx::Point& anchor_point) {
switch (arrow) {
case BubbleBorder::TOP_LEFT:
return anchor_point - contents_bounds.origin();
case BubbleBorder::TOP_RIGHT:
return anchor_point - contents_bounds.top_right();
case BubbleBorder::BOTTOM_LEFT:
return anchor_point - contents_bounds.bottom_left();
case BubbleBorder::BOTTOM_RIGHT:
return anchor_point - contents_bounds.bottom_right();
case BubbleBorder::LEFT_TOP:
return anchor_point - contents_bounds.origin();
case BubbleBorder::RIGHT_TOP:
return anchor_point - contents_bounds.top_right();
case BubbleBorder::LEFT_BOTTOM:
return anchor_point - contents_bounds.bottom_left();
case BubbleBorder::RIGHT_BOTTOM:
return anchor_point - contents_bounds.bottom_right();
case BubbleBorder::TOP_CENTER:
return anchor_point - contents_bounds.top_center();
case BubbleBorder::BOTTOM_CENTER:
return anchor_point - contents_bounds.bottom_center();
case BubbleBorder::LEFT_CENTER:
return anchor_point - contents_bounds.left_center();
case BubbleBorder::RIGHT_CENTER:
return anchor_point - contents_bounds.right_center();
default:
NOTREACHED();
}
}
BubbleArrowSide GetBubbleArrowSide(BubbleBorder::Arrow arrow) {
// Note: VERTICAL arrows are on the sides of the bubble, while !VERTICAL are
// on the top or bottom.
if (int{arrow} & BubbleBorder::VERTICAL) {
return (int{arrow} & BubbleBorder::RIGHT) ? BubbleArrowSide::kRight
: BubbleArrowSide::kLeft;
}
return (int{arrow} & BubbleBorder::BOTTOM) ? BubbleArrowSide::kBottom
: BubbleArrowSide::kTop;
}
gfx::Vector2d GetContentsBoundsOffsetToPlaceVisibleArrow(
BubbleBorder::Arrow arrow,
bool include_gap) {
if (arrow == BubbleBorder::NONE || arrow == BubbleBorder::FLOAT) {
return gfx::Vector2d();
}
const gfx::Insets visible_arrow_insets =
GetVisibleArrowInsets(arrow, include_gap);
return gfx::Vector2d(
visible_arrow_insets.left() - visible_arrow_insets.right(),
visible_arrow_insets.top() - visible_arrow_insets.bottom());
}
gfx::Insets GetVisibleArrowInsets(BubbleBorder::Arrow arrow, bool include_gap) {
DCHECK(BubbleBorder::has_arrow(arrow));
const int arrow_size = include_gap ? BubbleBorder::kVisibleArrowGap +
BubbleBorder::kVisibleArrowLength
: BubbleBorder::kVisibleArrowLength;
gfx::Insets result;
switch (GetBubbleArrowSide(arrow)) {
case BubbleArrowSide::kRight:
result.set_right(arrow_size);
break;
case BubbleArrowSide::kLeft:
result.set_left(arrow_size);
break;
case BubbleArrowSide::kTop:
result.set_top(arrow_size);
break;
case BubbleArrowSide::kBottom:
result.set_bottom(arrow_size);
break;
}
return result;
}
bool IsVerticalArrow(BubbleBorder::Arrow arrow) {
const BubbleArrowSide side = GetBubbleArrowSide(arrow);
return side == BubbleArrowSide::kTop || side == BubbleArrowSide::kBottom;
}
gfx::Size GetVisibleArrowSize(BubbleBorder::Arrow arrow) {
int kVisibleArrowDiameter = 2 * BubbleBorder::kVisibleArrowRadius;
return IsVerticalArrow(arrow) ? gfx::Size(kVisibleArrowDiameter,
BubbleBorder::kVisibleArrowLength)
: gfx::Size(BubbleBorder::kVisibleArrowLength,
kVisibleArrowDiameter);
}
} // namespace views