summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/app/theme/theme_resources.grd2
-rw-r--r--chrome/browser/views/app_launcher.cc6
-rw-r--r--chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc2
-rw-r--r--chrome/browser/views/bookmark_bubble_view.cc5
-rw-r--r--chrome/browser/views/bubble_border.cc521
-rw-r--r--chrome/browser/views/bubble_border.h104
-rw-r--r--chrome/browser/views/extensions/extension_installed_bubble.cc3
-rw-r--r--chrome/browser/views/extensions/extension_installed_bubble.h4
-rw-r--r--chrome/browser/views/extensions/extension_popup.cc4
-rw-r--r--chrome/browser/views/first_run_bubble.cc5
-rw-r--r--chrome/browser/views/first_run_bubble.h3
-rw-r--r--chrome/browser/views/info_bubble.cc82
-rw-r--r--chrome/browser/views/info_bubble.h44
-rw-r--r--chrome/browser/views/location_bar/content_setting_image_view.cc3
-rw-r--r--chrome/browser/views/location_bar/location_bar_view.cc4
-rw-r--r--chrome/browser/views/pinned_contents_info_bubble.cc13
-rw-r--r--chrome/browser/views/pinned_contents_info_bubble.h14
17 files changed, 318 insertions, 501 deletions
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd
index beeb4e9..cfa5851 100644
--- a/chrome/app/theme/theme_resources.grd
+++ b/chrome/app/theme/theme_resources.grd
@@ -304,8 +304,6 @@
<include name="IDR_BUBBLE_BL" file="bubble_bl.png" type="BINDATA" />
<include name="IDR_BUBBLE_T_ARROW" file="bubble_t_arrow.png" type="BINDATA" />
<include name="IDR_BUBBLE_B_ARROW" file="bubble_b_arrow.png" type="BINDATA" />
- <include name="IDR_BUBBLE_L_ARROW" file="bubble_l_arrow.png" type="BINDATA" />
- <include name="IDR_BUBBLE_R_ARROW" file="bubble_r_arrow.png" type="BINDATA" />
<include name="IDR_CLOSED_WINDOW" file="closed_window.png" type="BINDATA" />
<include name="IDR_THEME_TAB_BACKGROUND_INCOGNITO" file="theme_tab_background_incognito.png" type="BINDATA" />
diff --git a/chrome/browser/views/app_launcher.cc b/chrome/browser/views/app_launcher.cc
index 7b15433..87c6bb9 100644
--- a/chrome/browser/views/app_launcher.cc
+++ b/chrome/browser/views/app_launcher.cc
@@ -251,9 +251,9 @@ AppLauncher* AppLauncher::Show(Browser* browser,
BrowserView* browser_view = static_cast<BrowserView*>(browser->window());
app_launcher->hash_params_ = hash_params;
app_launcher->info_bubble_ =
- PinnedContentsInfoBubble::Show(browser_view->GetWidget(),
- bounds, BubbleBorder::TOP_LEFT, bubble_anchor,
- app_launcher->info_bubble_content_, app_launcher);
+ PinnedContentsInfoBubble::Show(browser_view->frame()->GetWindow(),
+ bounds, bubble_anchor, app_launcher->info_bubble_content_,
+ app_launcher);
app_launcher->info_bubble_content_->BubbleShown();
return app_launcher;
}
diff --git a/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc b/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc
index 4542d3a..f569ff9 100644
--- a/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc
+++ b/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc
@@ -510,7 +510,7 @@ AutocompletePopupContentsView::AutocompletePopupContentsView(
ALLOW_THIS_IN_INITIALIZER_LIST(size_animation_(this)) {
// The following little dance is required because set_border() requires a
// pointer to a non-const object.
- BubbleBorder* bubble_border = new BubbleBorder(BubbleBorder::NONE);
+ BubbleBorder* bubble_border = new BubbleBorder;
bubble_border_ = bubble_border;
set_border(bubble_border);
}
diff --git a/chrome/browser/views/bookmark_bubble_view.cc b/chrome/browser/views/bookmark_bubble_view.cc
index 101ae5a..837969c 100644
--- a/chrome/browser/views/bookmark_bubble_view.cc
+++ b/chrome/browser/views/bookmark_bubble_view.cc
@@ -25,8 +25,6 @@
#include "views/controls/button/native_button.h"
#include "views/controls/textfield/textfield.h"
#include "views/focus/focus_manager.h"
-#include "views/window/client_view.h"
-#include "views/window/window.h"
using views::Combobox;
using views::ColumnSet;
@@ -148,8 +146,7 @@ void BookmarkBubbleView::Show(views::Window* parent,
return;
bubble_ = new BookmarkBubbleView(delegate, profile, url, newly_bookmarked);
- InfoBubble::Show(parent->GetClientView()->GetWidget(), bounds,
- BubbleBorder::TOP_LEFT, bubble_, bubble_);
+ InfoBubble::Show(parent, bounds, bubble_, bubble_);
GURL url_ptr(url);
NotificationService::current()->Notify(
NotificationType::BOOKMARK_BUBBLE_SHOWN,
diff --git a/chrome/browser/views/bubble_border.cc b/chrome/browser/views/bubble_border.cc
index 468026e..3548286 100644
--- a/chrome/browser/views/bubble_border.cc
+++ b/chrome/browser/views/bubble_border.cc
@@ -22,11 +22,9 @@ SkBitmap* BubbleBorder::bottom_ = NULL;
SkBitmap* BubbleBorder::bottom_left_ = NULL;
SkBitmap* BubbleBorder::top_arrow_ = NULL;
SkBitmap* BubbleBorder::bottom_arrow_ = NULL;
-SkBitmap* BubbleBorder::left_arrow_ = NULL;
-SkBitmap* BubbleBorder::right_arrow_ = NULL;
// static
-int BubbleBorder::arrow_offset_;
+int BubbleBorder::arrow_x_offset_;
// The height inside the arrow image, in pixels.
static const int kArrowInteriorHeight = 7;
@@ -41,126 +39,41 @@ gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& position_relative_to,
insets.top() + insets.bottom());
// Screen position depends on the arrow location.
- // The arrow should overlap the target by some amount since there is space
- // for shadow between arrow tip and bitmap bounds.
+ // The arrow should overlap the target by some amount since the bottom arrow
+ // has lots of shadow below it and the top arrow is given an equivalent amount
+ // of padding.
const int kArrowOverlap = 3;
- int x = position_relative_to.x();
+ int x = position_relative_to.x() + (position_relative_to.width() / 2);
+ int arrow_offset = override_arrow_x_offset_ ? override_arrow_x_offset_ :
+ arrow_x_offset_;
+ if (arrow_is_left())
+ x -= arrow_offset;
+ else if (arrow_location_ == NONE)
+ x -= ((contents_size.width() / 2) + insets.left());
+ else
+ x += (arrow_offset - border_size.width() + 1);
int y = position_relative_to.y();
- int w = position_relative_to.width();
- int h = position_relative_to.height();
- int arrow_offset = override_arrow_offset_ ? override_arrow_offset_ :
- arrow_offset_;
-
- // Calculate bubble x coordinate.
- switch (arrow_location_) {
- case TOP_LEFT:
- case BOTTOM_LEFT:
- x += w / 2 - arrow_offset;
- break;
-
- case TOP_RIGHT:
- case BOTTOM_RIGHT:
- x += w / 2 + arrow_offset - border_size.width();
- break;
-
- case LEFT_TOP:
- case LEFT_BOTTOM:
- x += w - kArrowOverlap;
- break;
-
- case RIGHT_TOP:
- case RIGHT_BOTTOM:
- x += kArrowOverlap - border_size.width();
- break;
-
- case FLOAT:
- case NONE:
- x += w / 2 - border_size.width() / 2;
- break;
- }
-
- // Calculate bubble y coordinate.
- switch (arrow_location_) {
- case TOP_LEFT:
- case TOP_RIGHT:
- y += h - kArrowOverlap;
- break;
-
- case BOTTOM_LEFT:
- case BOTTOM_RIGHT:
- y += kArrowOverlap - border_size.height();
- break;
-
- case LEFT_TOP:
- case RIGHT_TOP:
- y += h / 2 - arrow_offset;
- break;
-
- case LEFT_BOTTOM:
- case RIGHT_BOTTOM:
- y += h / 2 + arrow_offset - border_size.height();
- break;
-
- case FLOAT:
- y += h / 2 - border_size.height() / 2;
- break;
-
- case NONE:
- y += h;
- break;
- }
+ if (arrow_is_bottom())
+ y += (kArrowOverlap - border_size.height());
+ else if (arrow_location_ == NONE)
+ y += position_relative_to.height();
+ else
+ y += (position_relative_to.height() - kArrowOverlap);
return gfx::Rect(x, y, border_size.width(), border_size.height());
}
void BubbleBorder::GetInsets(gfx::Insets* insets) const {
- int top = top_->height();
- int bottom = bottom_->height();
- int left = left_->width();
- int right = right_->width();
- switch (arrow_location_) {
- case TOP_LEFT:
- case TOP_RIGHT:
- top = std::max(top, top_arrow_->height());
- break;
-
- case BOTTOM_LEFT:
- case BOTTOM_RIGHT:
- bottom = std::max(bottom, bottom_arrow_->height());
- break;
-
- case LEFT_TOP:
- case LEFT_BOTTOM:
- left = std::max(left, left_arrow_->width());
- break;
-
- case RIGHT_TOP:
- case RIGHT_BOTTOM:
- right = std::max(right, right_arrow_->width());
- break;
-
- case NONE:
- top = 0;
- break;
-
- case FLOAT:
- // Nothing to do.
- break;
+ int top, bottom;
+ if (arrow_is_bottom()) {
+ top = top_->height();
+ bottom = std::max(bottom_->height(), bottom_arrow_->height());
+ } else {
+ top = (arrow_location_ == NONE) ?
+ 0 : std::max(top_->height(), top_arrow_->height());
+ bottom = bottom_->height();
}
- insets->Set(top, left, bottom, right);
-}
-
-int BubbleBorder::SetArrowOffset(int offset, const gfx::Size& contents_size) {
- gfx::Size border_size(contents_size);
- gfx::Insets insets;
- GetInsets(&insets);
- border_size.Enlarge(insets.left() + insets.right(),
- insets.top() + insets.bottom());
- offset = std::max(arrow_offset_,
- std::min(offset, (is_arrow_on_horizontal(arrow_location_) ?
- border_size.width() : border_size.height()) - arrow_offset_));
- override_arrow_offset_ = offset;
- return override_arrow_offset_;
+ insets->Set(top, left_->width(), bottom, right_->width());
}
// static
@@ -177,22 +90,15 @@ void BubbleBorder::InitClass() {
bottom_right_ = rb.GetBitmapNamed(IDR_BUBBLE_BR);
bottom_ = rb.GetBitmapNamed(IDR_BUBBLE_B);
bottom_left_ = rb.GetBitmapNamed(IDR_BUBBLE_BL);
- left_arrow_ = rb.GetBitmapNamed(IDR_BUBBLE_L_ARROW);
top_arrow_ = rb.GetBitmapNamed(IDR_BUBBLE_T_ARROW);
- right_arrow_ = rb.GetBitmapNamed(IDR_BUBBLE_R_ARROW);
bottom_arrow_ = rb.GetBitmapNamed(IDR_BUBBLE_B_ARROW);
- // Calculate horizontal and vertical insets for arrow by ensuring that
- // the widest arrow and corner images will have enough room to avoid overlap
- int offset_x =
+ // Calculate horizontal inset for arrow by ensuring that the widest arrow
+ // and corner images will have enough room to avoid overlap.
+ arrow_x_offset_ =
(std::max(top_arrow_->width(), bottom_arrow_->width()) / 2) +
std::max(std::max(top_left_->width(), top_right_->width()),
std::max(bottom_left_->width(), bottom_right_->width()));
- int offset_y =
- (std::max(left_arrow_->height(), right_arrow_->height()) / 2) +
- std::max(std::max(top_left_->height(), top_right_->height()),
- std::max(bottom_left_->height(), bottom_right_->height()));
- arrow_offset_ = std::max(offset_x, offset_y);
initialized = true;
}
@@ -200,232 +106,177 @@ void BubbleBorder::InitClass() {
void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const {
// Convenience shorthand variables.
- // If |arrow_location_| == NONE, the entire top edge is omitted and height of
- // corresponding bitmaps is set to 0.
- const int tl_width = top_left_->width();
- const int tl_height = (arrow_location_ == NONE ? 0 : top_left_->height());
- const int t_height = (arrow_location_ == NONE ? 0 : top_->height());
- const int tr_width = top_right_->width();
- const int tr_height = (arrow_location_ == NONE ? 0 : top_right_->height());
- const int l_width = left_->width();
- const int r_width = right_->width();
- const int br_width = bottom_right_->width();
- const int br_height = bottom_right_->height();
- const int b_height = bottom_->height();
- const int bl_width = bottom_left_->width();
- const int bl_height = bottom_left_->height();
+ int width = view.width();
+ int tl_width = top_left_->width();
+ int tl_height = top_left_->height();
+ int t_height = top_->height();
+ int tr_width = top_right_->width();
+ int tr_height = top_right_->height();
+ int r_width = right_->width();
+ int br_width = bottom_right_->width();
+ int br_height = bottom_right_->height();
+ int b_height = bottom_->height();
+ int bl_width = bottom_left_->width();
+ int bl_height = bottom_left_->height();
+
+ /* The variables below can be confusing; here's what they mean:
+ *
+ * 0∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙┌───┐ ┌───┐
+ * border_top∙∙∙∙∙∙∙┌────┬─┤ ▲ ├──────┤ ▲ ├─┬────┐
+ * │ / │-│∙ ∙│------│∙ ∙│-│ \ │
+ * top∙∙∙∙∙∙∙∙∙∙∙∙∙∙│ / ├─┴───┴──────┴───┴─┤ \ │
+ * tl_bottom∙∙∙∙∙∙├───┬┘ └┬───┤∙∙∙∙∙∙tr_bottom
+ * │ | │ │ | │
+ * │ | │ │ | │
+ * │ | │ │ | │
+ * bl_y∙∙∙∙∙∙∙∙∙∙∙├───┴┐ ┌┴───┤∙∙∙∙∙∙br_y
+ * bottom∙∙∙∙∙∙∙∙∙∙∙│ \ ├─┬───┬──────┬───┬─┤ / │
+ * │ \ │-│. .│------│. .│-│ / │
+ * border_bottom∙∙∙∙└────┴─┤ ▼ ├──────┤ ▼ ├─┴────┘
+ * view.height()∙∙∙∙∙∙∙∙∙∙∙└───┘ └───┘
+ *
+ * If |arrow_location_| == NONE, the entire top edge is ommitted, and
+ * |tl_bottom| == |tr_bottom| == 0. Otherwise, one of the four arrows will be
+ * drawn.
+ */
gfx::Insets insets;
GetInsets(&insets);
- const int top = insets.top() - t_height;
- const int bottom = view.height() - insets.bottom() + b_height;
- const int left = insets.left() - l_width;
- const int right = view.width() - insets.right() + r_width;
- const int height = bottom - top;
- const int width = right - left;
-
- // |arrow_offset| is offset of arrow from the begining of the edge.
- int arrow_offset = arrow_offset_;
- if (override_arrow_offset_)
- arrow_offset = override_arrow_offset_;
- else if (is_arrow_on_horizontal(arrow_location_) &&
- !is_arrow_on_left(arrow_location_)) {
- arrow_offset = view.width() - arrow_offset - 1;
- } else if (!is_arrow_on_horizontal(arrow_location_) &&
- !is_arrow_on_top(arrow_location_)) {
- arrow_offset = view.height() - arrow_offset - 1;
- }
-
- // Left edge.
- if (arrow_location_ == LEFT_TOP || arrow_location_ == LEFT_BOTTOM) {
- int start_y = top + tl_height;
- int before_arrow = arrow_offset - start_y - left_arrow_->height() / 2;
- int after_arrow = height - tl_height - bl_height -
- left_arrow_->height() - before_arrow;
- DrawArrowInterior(canvas,
- false,
- left_arrow_->width() - kArrowInteriorHeight,
- start_y + before_arrow + left_arrow_->height() / 2,
- kArrowInteriorHeight,
- left_arrow_->height() / 2 - 1);
- DrawEdgeWithArrow(canvas,
- false,
- left_,
- left_arrow_,
- left,
- start_y,
- before_arrow,
- after_arrow,
- left_->width() - left_arrow_->width());
+ int top = insets.top();
+ int bottom = view.height() - insets.bottom();
+ int border_bottom = bottom + b_height;
+ int bl_y = border_bottom - bl_height;
+ int br_y = border_bottom - br_height;
+
+ int border_top, tl_bottom, tr_bottom;
+ if (arrow_location_ == NONE) {
+ border_top = tl_bottom = tr_bottom = 0;
} else {
- canvas->TileImageInt(*left_, left, top + tl_height, l_width,
- height - tl_height - bl_height);
+ border_top = top - t_height;
+ tl_bottom = border_top + tl_height;
+ tr_bottom = border_top + tr_height;
+
+ // Top left corner
+ canvas->DrawBitmapInt(*top_left_, 0, border_top);
+
+ // Top right corner
+ canvas->DrawBitmapInt(*top_right_, width - tr_width, border_top);
}
+ // Right edge
+ canvas->TileImageInt(*right_, width - r_width, tr_bottom, r_width,
+ br_y - tr_bottom);
+
+ // Bottom right corner
+ canvas->DrawBitmapInt(*bottom_right_, width - br_width, br_y);
+
+
+ // Bottom left corner
+ canvas->DrawBitmapInt(*bottom_left_, 0, bl_y);
+
+ // Left edge
+ canvas->TileImageInt(*left_, 0, tl_bottom, left_->width(), bl_y - tl_bottom);
+
+ // Arrow edge, if necessary
+ bool should_draw_top_edge = false;
+ bool should_draw_bottom_edge = true;
if (arrow_location_ != NONE) {
- // Top left corner.
- canvas->DrawBitmapInt(*top_left_, left, top);
-
- // Top edge.
- if (arrow_location_ == TOP_LEFT || arrow_location_ == TOP_RIGHT) {
- int start_x = left + tl_width;
- int before_arrow = arrow_offset - start_x - top_arrow_->width() / 2;
- int after_arrow = width - tl_width - tr_width -
- top_arrow_->width() - before_arrow;
- DrawArrowInterior(canvas,
- true,
- start_x + before_arrow + top_arrow_->width() / 2,
- top_arrow_->height() - kArrowInteriorHeight,
- 1 - top_arrow_->width() / 2,
- kArrowInteriorHeight);
- DrawEdgeWithArrow(canvas,
- true,
- top_,
- top_arrow_,
- start_x,
- top,
- before_arrow,
- after_arrow,
- top_->height() - top_arrow_->height());
+ /* Here's what the variables below mean (without loss of generality):
+ *
+ * arrow_center
+ * arrow_x │ arrow_r
+ * │ │ │
+ * left_of_edge─┬────┐ │ │ │ ┌────┬─right_of_edge
+ * arrow_y∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙┌───┐
+ * edge_y∙∙∙∙∙∙∙┌────┬───┤ ▲ ├───────┬────┐ ┐
+ * │ / │---│∙ ∙│-------│ \ │ ├─e_height
+ * │ / ├───┴───┴───────┤ \ │ ┘
+ * ├───┬┘ └┬───┤
+ * | | └─┬─┘ | |
+ * ∙ ∙└─┬─┘ │ └───┬───┘∙ ∙
+ * left_of_arrow─┘ │ └─right_of_arrow
+ * arrow_width
+ *
+ * Not shown: border_y and tip_y contain the base and tip coordinates inside
+ * the arrow for use filling the arrow interior with the background color.
+ */
+
+ SkBitmap* edge;
+ SkBitmap* arrow;
+ int left_of_edge, right_of_edge, edge_y, arrow_y;
+ SkScalar border_y, tip_y;
+ if (arrow_is_bottom()) {
+ should_draw_top_edge = true;
+ should_draw_bottom_edge = false;
+ edge = bottom_;
+ arrow = bottom_arrow_;
+ left_of_edge = bl_width;
+ right_of_edge = br_width;
+ edge_y = arrow_y = bottom;
+ border_y = SkIntToScalar(bottom);
+ tip_y = SkIntToScalar(bottom + kArrowInteriorHeight);
} else {
- canvas->TileImageInt(*top_, left + tl_width, top,
- width - tl_width - tr_width, t_height);
+ edge = top_;
+ arrow = top_arrow_;
+ left_of_edge = tl_width;
+ right_of_edge = tr_width;
+ edge_y = border_top;
+ arrow_y = top - top_arrow_->height();
+ border_y = SkIntToScalar(top);
+ tip_y = SkIntToScalar(top - kArrowInteriorHeight);
+ }
+ int arrow_offset = override_arrow_x_offset_ ? override_arrow_x_offset_ :
+ arrow_x_offset_;
+ int arrow_width = arrow->width();
+ int arrow_center = arrow_is_left() ?
+ arrow_offset : width - arrow_offset - 1;
+ int arrow_x = arrow_center - (arrow_width / 2);
+ SkScalar arrow_interior_x =
+ SkIntToScalar(arrow_center - kArrowInteriorHeight);
+ SkScalar arrow_interior_r =
+ SkIntToScalar(arrow_center + kArrowInteriorHeight);
+ int arrow_r = arrow_x + arrow_width;
+ int e_height = edge->height();
+
+ // Edge to the left of the arrow
+ int left_of_arrow = arrow_x - left_of_edge;
+ if (left_of_arrow) {
+ canvas->TileImageInt(*edge, left_of_edge, edge_y, left_of_arrow,
+ e_height);
}
- // Top right corner.
- canvas->DrawBitmapInt(*top_right_, right - tr_width, top);
+ // Interior of the arrow (filled with background color)
+ SkPaint paint;
+ paint.setStyle(SkPaint::kFill_Style);
+ paint.setColor(background_color_);
+ gfx::Path path;
+ path.incReserve(4);
+ path.moveTo(arrow_interior_x, border_y);
+ path.lineTo(SkIntToScalar(arrow_center), tip_y);
+ path.lineTo(arrow_interior_r, border_y);
+ path.close();
+ canvas->drawPath(path, paint);
+
+ // Arrow border
+ canvas->DrawBitmapInt(*arrow, arrow_x, arrow_y);
+
+ // Edge to the right of the arrow
+ int right_of_arrow = width - arrow_r - right_of_edge;
+ if (right_of_arrow)
+ canvas->TileImageInt(*edge, arrow_r, edge_y, right_of_arrow, e_height);
}
- // Right edge.
- if (arrow_location_ == RIGHT_TOP || arrow_location_ == RIGHT_BOTTOM) {
- int start_y = top + tr_height;
- int before_arrow = arrow_offset - start_y - right_arrow_->height() / 2;
- int after_arrow = height - tl_height - bl_height -
- right_arrow_->height() - before_arrow;
- DrawArrowInterior(canvas,
- false,
- right - r_width + kArrowInteriorHeight,
- start_y + before_arrow + right_arrow_->height() / 2,
- -kArrowInteriorHeight,
- right_arrow_->height() / 2 - 1);
- DrawEdgeWithArrow(canvas,
- false,
- right_,
- right_arrow_,
- right - r_width,
- start_y,
- before_arrow,
- after_arrow,
- 0);
- } else {
- canvas->TileImageInt(*right_, right - r_width, top + tr_height, r_width,
- height - tr_height - br_height);
+ // Top edge, if not already drawn
+ if (should_draw_top_edge) {
+ canvas->TileImageInt(*top_, tl_width, border_top,
+ width - tl_width - tr_width, t_height);
}
- // Bottom right corner.
- canvas->DrawBitmapInt(*bottom_right_, right - br_width, bottom - br_height);
-
- // Bottom edge.
- if (arrow_location_ == BOTTOM_LEFT || arrow_location_ == BOTTOM_RIGHT) {
- int start_x = left + bl_width;
- int before_arrow = arrow_offset - start_x - bottom_arrow_->width() / 2;
- int after_arrow = width - bl_width - br_width -
- bottom_arrow_->width() - before_arrow;
- DrawArrowInterior(canvas,
- true,
- start_x + before_arrow + bottom_arrow_->width() / 2,
- bottom - b_height + kArrowInteriorHeight,
- 1 - bottom_arrow_->width() / 2,
- -kArrowInteriorHeight);
- DrawEdgeWithArrow(canvas,
- true,
- bottom_,
- bottom_arrow_,
- start_x,
- bottom - b_height,
- before_arrow,
- after_arrow,
- 0);
- } else {
- canvas->TileImageInt(*bottom_, left + bl_width, bottom - b_height,
+ // Bottom edge, if not already drawn
+ if (should_draw_bottom_edge) {
+ canvas->TileImageInt(*bottom_, bl_width, bottom,
width - bl_width - br_width, b_height);
}
-
- // Bottom left corner.
- canvas->DrawBitmapInt(*bottom_left_, left, bottom - bl_height);
-}
-
-void BubbleBorder::DrawEdgeWithArrow(gfx::Canvas* canvas,
- bool is_horizontal,
- SkBitmap* edge,
- SkBitmap* arrow,
- int start_x,
- int start_y,
- int before_arrow,
- int after_arrow,
- int offset) const {
- /* Here's what the parameters mean:
- * start_x
- * .
- * . ┌───┐ ┬ offset
- * start_y..........┌────┬────────┤ ▲ ├────────┬────┐ ┴
- * │ / │--------│∙ ∙│--------│ \ │
- * │ / ├────────┴───┴────────┤ \ │
- * ├───┬┘ └┬───┤
- * └───┬────┘ └───┬────┘
- * before_arrow ─┘ └─ after_arrow
- */
- if (before_arrow) {
- canvas->TileImageInt(*edge, start_x, start_y,
- is_horizontal ? before_arrow : edge->width(),
- is_horizontal ? edge->height() : before_arrow);
- }
-
- canvas->DrawBitmapInt(*arrow,
- start_x + (is_horizontal ? before_arrow : offset),
- start_y + (is_horizontal ? offset : before_arrow));
-
- if (after_arrow) {
- start_x += (is_horizontal ? before_arrow + arrow->width() : 0);
- start_y += (is_horizontal ? 0 : before_arrow + arrow->height());
- canvas->TileImageInt(*edge, start_x, start_y,
- is_horizontal ? after_arrow : edge->width(),
- is_horizontal ? edge->height() : after_arrow);
- }
-}
-
-void BubbleBorder::DrawArrowInterior(gfx::Canvas* canvas,
- bool is_horizontal,
- int tip_x,
- int tip_y,
- int shift_x,
- int shift_y) const {
- /* This function fills the interior of the arrow with background color.
- * It draws isosceles triangle under semitransparent arrow tip.
- *
- * Here's what the parameters mean:
- *
- * ┌──────── |tip_x|
- * ┌─────┐
- * │ ▲ │ ──── |tip y|
- * │∙∙∙∙∙│ ┐
- * └─────┘ └─── |shift_x| (offset from tip to vertexes of isosceles triangle)
- * └────────── |shift_y|
- */
- SkPaint paint;
- paint.setStyle(SkPaint::kFill_Style);
- paint.setColor(background_color_);
- gfx::Path path;
- path.incReserve(4);
- path.moveTo(SkIntToScalar(tip_x), SkIntToScalar(tip_y));
- path.lineTo(SkIntToScalar(tip_x + shift_x),
- SkIntToScalar(tip_y + shift_y));
- if (is_horizontal)
- path.lineTo(SkIntToScalar(tip_x - shift_x), SkIntToScalar(tip_y + shift_y));
- else
- path.lineTo(SkIntToScalar(tip_x + shift_x), SkIntToScalar(tip_y - shift_y));
- path.close();
- canvas->drawPath(path, paint);
}
/////////////////////////
diff --git a/chrome/browser/views/bubble_border.h b/chrome/browser/views/bubble_border.h
index 753d1e6..3670503 100644
--- a/chrome/browser/views/bubble_border.h
+++ b/chrome/browser/views/bubble_border.h
@@ -11,31 +11,25 @@
class SkBitmap;
-// Renders a border, with optional arrow, and a custom dropshadow.
-// This can be used to produce floating "bubble" objects with rounded corners.
+// Renders a border, with optional arrow (off by default), and a custom
+// dropshadow. This can be used to produce floating "bubble" objects.
+//
+// If the arrow is on, the bubble has four round corner. If not, it has round
+// corners on the bottom and square corners on the top, and lacks a top border.
class BubbleBorder : public views::Border {
public:
// Possible locations for the (optional) arrow.
- // 0 bit specifies left or right.
- // 1 bit specifies top or bottom.
- // 2 bit specifies horizontal or vertical.
enum ArrowLocation {
- TOP_LEFT = 0,
- TOP_RIGHT = 1,
- BOTTOM_LEFT = 2,
- BOTTOM_RIGHT = 3,
- LEFT_TOP = 4,
- RIGHT_TOP = 5,
- LEFT_BOTTOM = 6,
- RIGHT_BOTTOM = 7,
- NONE = 8, // No arrow and top border. Aligned under the supplied rect.
- FLOAT = 9 // No arrow but has top edge. Centered over the supplied rect.
+ NONE,
+ TOP_LEFT,
+ TOP_RIGHT,
+ BOTTOM_LEFT,
+ BOTTOM_RIGHT
};
- explicit BubbleBorder(ArrowLocation arrow_location)
- : override_arrow_offset_(0),
- arrow_location_(arrow_location),
- background_color_(SK_ColorWHITE) {
+ BubbleBorder() : override_arrow_x_offset_(0),
+ arrow_location_(NONE),
+ background_color_(SK_ColorWHITE) {
InitClass();
}
@@ -53,28 +47,10 @@ class BubbleBorder : public views::Border {
arrow_location_ = arrow_location;
}
- static ArrowLocation rtl_mirror(ArrowLocation loc) {
- return loc >= NONE ? loc : static_cast<ArrowLocation>(loc ^ 1);
- }
-
- static ArrowLocation horizontal_mirror(ArrowLocation loc) {
- return loc >= NONE ? loc : static_cast<ArrowLocation>(loc ^ 2);
- }
-
- static bool has_arrow(ArrowLocation loc) {
- return loc >= NONE ? false : true;
- }
-
- static bool is_arrow_on_left(ArrowLocation loc) {
- return loc >= NONE ? false : !(loc & 1);
- }
-
- static bool is_arrow_on_top(ArrowLocation loc) {
- return loc >= NONE ? false : !(loc & 2);
- }
-
- static bool is_arrow_on_horizontal(ArrowLocation loc) {
- return loc >= NONE ? false : !(loc & 4);
+ // Sets a fixed x offset for the arrow. The arrow will still point to the
+ // same location but the bubble will shift horizontally to make that happen.
+ void set_arrow_offset(int offset) {
+ override_arrow_x_offset_ = offset;
}
// Sets the background color for the arrow body. This is irrelevant if you do
@@ -88,15 +64,12 @@ class BubbleBorder : public views::Border {
// given the rect to point to and the size of the contained contents. This
// depends on the arrow location, so if you change that, you should call this
// again to find out the new coordinates.
+ //
+ // For borders without an arrow, gives the bounds with the content centered
+ // underneath the supplied rect.
gfx::Rect GetBounds(const gfx::Rect& position_relative_to,
const gfx::Size& contents_size) const;
- // Sets a fixed offset for the arrow from the beginning of corresponding edge.
- // The arrow will still point to the same location but the bubble will shift
- // location to make that happen. Returns actuall arrow offset, in case of
- // overflow it differ from desired.
- int SetArrowOffset(int offset, const gfx::Size& contents_size);
-
// Overridden from views::Border:
virtual void GetInsets(gfx::Insets* insets) const;
@@ -106,26 +79,20 @@ class BubbleBorder : public views::Border {
virtual ~BubbleBorder() { }
+ // Returns true if there is an arrow and it is positioned on the bottom edge.
+ bool arrow_is_bottom() const {
+ return (arrow_location_ == BOTTOM_LEFT) ||
+ (arrow_location_ == BOTTOM_RIGHT);
+ }
+
+ // Returns true if there is an arrow and it is positioned on the left side.
+ bool arrow_is_left() const {
+ return (arrow_location_ == TOP_LEFT) || (arrow_location_ == BOTTOM_LEFT);
+ }
+
// Overridden from views::Border:
virtual void Paint(const views::View& view, gfx::Canvas* canvas) const;
- void DrawEdgeWithArrow(gfx::Canvas* canvas,
- bool is_horizontal,
- SkBitmap* edge,
- SkBitmap* arrow,
- int start_x,
- int start_y,
- int before_arrow,
- int after_arrow,
- int offset) const;
-
- void DrawArrowInterior(gfx::Canvas* canvas,
- bool is_horizontal,
- int tip_x,
- int tip_y,
- int shift_x,
- int shift_y) const;
-
// Border graphics.
static SkBitmap* left_;
static SkBitmap* top_left_;
@@ -135,16 +102,13 @@ class BubbleBorder : public views::Border {
static SkBitmap* bottom_right_;
static SkBitmap* bottom_;
static SkBitmap* bottom_left_;
- static SkBitmap* left_arrow_;
static SkBitmap* top_arrow_;
- static SkBitmap* right_arrow_;
static SkBitmap* bottom_arrow_;
- // Minimal offset of the arrow from the closet edge of bounding rect.
- static int arrow_offset_;
+ static int arrow_x_offset_;
- // If specified, overrides the pre-calculated |arrow_offset_| of the arrow.
- int override_arrow_offset_;
+ // If specified, overrides the pre-calculated |arrow_x_offset_| of the arrow.
+ int override_arrow_x_offset_;
ArrowLocation arrow_location_;
SkColor background_color_;
diff --git a/chrome/browser/views/extensions/extension_installed_bubble.cc b/chrome/browser/views/extensions/extension_installed_bubble.cc
index 36fd253..b02b56d 100644
--- a/chrome/browser/views/extensions/extension_installed_bubble.cc
+++ b/chrome/browser/views/extensions/extension_installed_bubble.cc
@@ -332,8 +332,7 @@ void ExtensionInstalledBubble::ShowInternal() {
bubble_content_ = new InstalledBubbleContent(extension_, type_,
&icon_);
- InfoBubble::Show(browser_view->GetWidget(), bounds, BubbleBorder::TOP_RIGHT,
- bubble_content_, this);
+ InfoBubble::Show(browser_view->GetWindow(), bounds, bubble_content_, this);
}
// InfoBubbleDelegate
diff --git a/chrome/browser/views/extensions/extension_installed_bubble.h b/chrome/browser/views/extensions/extension_installed_bubble.h
index b4ee946..c49515d 100644
--- a/chrome/browser/views/extensions/extension_installed_bubble.h
+++ b/chrome/browser/views/extensions/extension_installed_bubble.h
@@ -67,6 +67,10 @@ class ExtensionInstalledBubble
bool closed_by_escape);
virtual bool CloseOnEscape() { return true; }
+ // Arrow subjects appear on the right side (for RTL), so do not prefer
+ // origin side anchor.
+ virtual bool PreferOriginSideAnchor() { return false; }
+
Extension* extension_;
Browser* browser_;
SkBitmap icon_;
diff --git a/chrome/browser/views/extensions/extension_popup.cc b/chrome/browser/views/extensions/extension_popup.cc
index f30aac9..3e91205a 100644
--- a/chrome/browser/views/extensions/extension_popup.cc
+++ b/chrome/browser/views/extensions/extension_popup.cc
@@ -114,7 +114,9 @@ ExtensionPopup::ExtensionPopup(ExtensionHost* host,
chromeos::WM_IPC_WINDOW_CHROME_INFO_BUBBLE,
NULL);
#endif
- border_ = new BubbleBorder(arrow_location);
+ border_ = new BubbleBorder;
+ border_->set_arrow_location(arrow_location);
+
border_view_ = new views::View;
border_view_->set_background(new BubbleBackground(border_));
diff --git a/chrome/browser/views/first_run_bubble.cc b/chrome/browser/views/first_run_bubble.cc
index 7728888..692650c 100644
--- a/chrome/browser/views/first_run_bubble.cc
+++ b/chrome/browser/views/first_run_bubble.cc
@@ -471,9 +471,8 @@ void FirstRunMinimalBubbleView::FocusWillChange(View* focused_before,
// static
FirstRunBubble* FirstRunBubble::Show(Profile* profile,
- views::Widget* parent,
+ views::Window* parent,
const gfx::Rect& position_relative_to,
- BubbleBorder::ArrowLocation arrow_location,
FirstRun::BubbleType bubble_type) {
FirstRunBubble* window = new FirstRunBubble();
FirstRunBubbleViewBase* view = NULL;
@@ -492,7 +491,7 @@ FirstRunBubble* FirstRunBubble::Show(Profile* profile,
NOTREACHED();
}
window->set_view(view);
- window->Init(parent, position_relative_to, arrow_location, view, window);
+ window->Init(parent, position_relative_to, view, window);
window->GetFocusManager()->AddFocusChangeListener(view);
view->BubbleShown();
return window;
diff --git a/chrome/browser/views/first_run_bubble.h b/chrome/browser/views/first_run_bubble.h
index 65752db..cccce32 100644
--- a/chrome/browser/views/first_run_bubble.h
+++ b/chrome/browser/views/first_run_bubble.h
@@ -16,9 +16,8 @@ class Profile;
class FirstRunBubble : public InfoBubble,
public InfoBubbleDelegate {
public:
- static FirstRunBubble* Show(Profile* profile, views::Widget* parent,
+ static FirstRunBubble* Show(Profile* profile, views::Window* window,
const gfx::Rect& position_relative_to,
- BubbleBorder::ArrowLocation arrow_location,
FirstRun::BubbleType bubble_type);
private:
diff --git a/chrome/browser/views/info_bubble.cc b/chrome/browser/views/info_bubble.cc
index 8d30c83..3a69a1b 100644
--- a/chrome/browser/views/info_bubble.cc
+++ b/chrome/browser/views/info_bubble.cc
@@ -5,6 +5,7 @@
#include "chrome/browser/views/info_bubble.h"
#include "base/keyboard_codes.h"
+#include "chrome/browser/views/bubble_border.h"
#include "chrome/browser/window_sizer.h"
#include "chrome/common/notification_service.h"
#include "gfx/canvas.h"
@@ -13,8 +14,6 @@
#include "third_party/skia/include/core/SkPaint.h"
#include "views/fill_layout.h"
#include "views/widget/root_view.h"
-#include "views/widget/widget.h"
-#include "views/window/client_view.h"
#include "views/window/window.h"
#if defined(OS_CHROMEOS)
@@ -33,30 +32,26 @@ const SkColor InfoBubble::kBackgroundColor = SK_ColorWHITE;
void BorderContents::Init() {
DCHECK(!bubble_border_);
- bubble_border_ = new BubbleBorder(BubbleBorder::LEFT_TOP);
+ bubble_border_ = new BubbleBorder();
set_border(bubble_border_);
bubble_border_->set_background_color(InfoBubble::kBackgroundColor);
}
void BorderContents::SizeAndGetBounds(
const gfx::Rect& position_relative_to,
- BubbleBorder::ArrowLocation arrow_location,
const gfx::Size& contents_size,
+ bool prefer_arrow_on_right,
gfx::Rect* contents_bounds,
gfx::Rect* window_bounds) {
- if (UILayoutIsRightToLeft())
- arrow_location = BubbleBorder::rtl_mirror(arrow_location);
- bubble_border_->set_arrow_location(arrow_location);
- // Set the border.
- set_border(bubble_border_);
- bubble_border_->set_background_color(InfoBubble::kBackgroundColor);
-
// Give the contents a margin.
gfx::Size local_contents_size(contents_size);
local_contents_size.Enlarge(kLeftMargin + kRightMargin,
kTopMargin + kBottomMargin);
// Try putting the arrow in its initial location, and calculating the bounds.
+ BubbleBorder::ArrowLocation arrow_location(prefer_arrow_on_right ?
+ BubbleBorder::TOP_RIGHT : BubbleBorder::TOP_LEFT);
+ bubble_border_->set_arrow_location(arrow_location);
*window_bounds =
bubble_border_->GetBounds(position_relative_to, local_contents_size);
@@ -67,14 +62,16 @@ void BorderContents::SizeAndGetBounds(
monitor_provider->GetMonitorWorkAreaMatching(position_relative_to));
if (!monitor_bounds.IsEmpty() && !monitor_bounds.Contains(*window_bounds)) {
// The bounds don't fit. Move the arrow to try and improve things.
- if (window_bounds->bottom() > monitor_bounds.bottom())
- arrow_location = BubbleBorder::horizontal_mirror(arrow_location);
- else if (BubbleBorder::is_arrow_on_left(arrow_location) ?
- (window_bounds->right() > monitor_bounds.right()) :
- (window_bounds->x() < monitor_bounds.x())) {
- arrow_location = BubbleBorder::rtl_mirror(arrow_location);
+ bool arrow_on_left = prefer_arrow_on_right ?
+ (window_bounds->x() < monitor_bounds.x()) :
+ (window_bounds->right() <= monitor_bounds.right());
+ if (window_bounds->bottom() > monitor_bounds.bottom()) {
+ arrow_location = arrow_on_left ?
+ BubbleBorder::BOTTOM_LEFT : BubbleBorder::BOTTOM_RIGHT;
+ } else {
+ arrow_location = arrow_on_left ?
+ BubbleBorder::TOP_LEFT : BubbleBorder::TOP_RIGHT;
}
-
bubble_border_->set_arrow_location(arrow_location);
// Now get the recalculated bounds.
@@ -137,13 +134,13 @@ void BorderWidget::Init(HWND owner) {
gfx::Rect BorderWidget::SizeAndGetBounds(
const gfx::Rect& position_relative_to,
- BubbleBorder::ArrowLocation arrow_location,
- const gfx::Size& contents_size) {
+ const gfx::Size& contents_size,
+ bool prefer_arrow_on_right) {
// Ask the border view to calculate our bounds (and our contents').
gfx::Rect contents_bounds;
gfx::Rect window_bounds;
- border_contents_->SizeAndGetBounds(position_relative_to, arrow_location,
- contents_size, &contents_bounds,
+ border_contents_->SizeAndGetBounds(position_relative_to, contents_size,
+ prefer_arrow_on_right, &contents_bounds,
&window_bounds);
SetBounds(window_bounds);
@@ -177,14 +174,12 @@ LRESULT BorderWidget::OnMouseActivate(HWND window,
// InfoBubble -----------------------------------------------------------------
// static
-InfoBubble* InfoBubble::Show(views::Widget* parent,
+InfoBubble* InfoBubble::Show(views::Window* parent,
const gfx::Rect& position_relative_to,
- BubbleBorder::ArrowLocation arrow_location,
views::View* contents,
InfoBubbleDelegate* delegate) {
InfoBubble* window = new InfoBubble;
- window->Init(parent, position_relative_to, arrow_location,
- contents, delegate);
+ window->Init(parent, position_relative_to, contents, delegate);
return window;
}
@@ -199,33 +194,29 @@ InfoBubble::InfoBubble()
border_contents_(NULL),
#endif
delegate_(NULL),
+ parent_(NULL),
closed_(false) {
}
-void InfoBubble::Init(views::Widget* parent,
+void InfoBubble::Init(views::Window* parent,
const gfx::Rect& position_relative_to,
- BubbleBorder::ArrowLocation arrow_location,
views::View* contents,
InfoBubbleDelegate* delegate) {
+ parent_ = parent;
delegate_ = delegate;
position_relative_to_ = position_relative_to;
- arrow_location_ = arrow_location;
contents_ = contents;
// Create the main window.
#if defined(OS_WIN)
- views::Window* parent_window = parent->GetWindow();
- if (parent_window)
- parent_window->DisableInactiveRendering();
+ parent_->DisableInactiveRendering();
set_window_style(WS_POPUP | WS_CLIPCHILDREN);
set_window_ex_style(WS_EX_TOOLWINDOW);
- WidgetWin::Init(parent->GetNativeView(), gfx::Rect());
+ WidgetWin::Init(parent->GetNativeWindow(), gfx::Rect());
#elif defined(OS_LINUX)
MakeTransparent();
make_transient_to_parent();
- WidgetGtk::Init(
- GTK_WIDGET(static_cast<WidgetGtk*>(parent)->GetNativeView()),
- gfx::Rect());
+ WidgetGtk::Init(GTK_WIDGET(parent->GetNativeWindow()), gfx::Rect());
#if defined(OS_CHROMEOS)
chromeos::WmIpc::instance()->SetWindowType(
GetNativeView(),
@@ -249,6 +240,9 @@ void InfoBubble::Init(views::Widget* parent,
// Calculate and set the bounds for all windows and views.
gfx::Rect window_bounds;
+ bool prefer_arrow_on_right = delegate &&
+ (contents->UILayoutIsRightToLeft() == delegate->PreferOriginSideAnchor());
+
#if defined(OS_WIN)
DCHECK(!border_.get());
border_.reset(CreateBorderWidget());
@@ -256,8 +250,8 @@ void InfoBubble::Init(views::Widget* parent,
// Initialize and position the border window.
window_bounds = border_->SizeAndGetBounds(position_relative_to,
- arrow_location,
- contents->GetPreferredSize());
+ contents->GetPreferredSize(),
+ prefer_arrow_on_right);
// Make |contents| take up the entire contents view.
contents_view->SetLayoutManager(new views::FillLayout);
@@ -271,7 +265,7 @@ void InfoBubble::Init(views::Widget* parent,
border_contents_->Init();
gfx::Rect contents_bounds;
border_contents_->SizeAndGetBounds(position_relative_to,
- arrow_location, contents->GetPreferredSize(),
+ contents->GetPreferredSize(), prefer_arrow_on_right,
&contents_bounds, &window_bounds);
// This new view must be added before |contents| so it will paint under it.
contents_view->AddChildView(0, border_contents_);
@@ -310,15 +304,19 @@ BorderWidget* InfoBubble::CreateBorderWidget() {
void InfoBubble::SizeToContents() {
gfx::Rect window_bounds;
+ bool prefer_arrow_on_right = delegate_ &&
+ (contents_->UILayoutIsRightToLeft() ==
+ delegate_->PreferOriginSideAnchor());
+
#if defined(OS_WIN)
// Initialize and position the border window.
window_bounds = border_->SizeAndGetBounds(position_relative_to_,
- arrow_location_,
- contents_->GetPreferredSize());
+ contents_->GetPreferredSize(),
+ prefer_arrow_on_right);
#else
gfx::Rect contents_bounds;
border_contents_->SizeAndGetBounds(position_relative_to_,
- arrow_location_, contents_->GetPreferredSize(),
+ contents_->GetPreferredSize(), prefer_arrow_on_right,
&contents_bounds, &window_bounds);
// |contents_view| has no layout manager, so we have to explicitly position
// its children.
diff --git a/chrome/browser/views/info_bubble.h b/chrome/browser/views/info_bubble.h
index fa15bf7..4b76507 100644
--- a/chrome/browser/views/info_bubble.h
+++ b/chrome/browser/views/info_bubble.h
@@ -8,7 +8,6 @@
#include "third_party/skia/include/core/SkColor.h"
#include "views/accelerator.h"
#include "views/view.h"
-#include "chrome/browser/views/bubble_border.h"
#if defined(OS_WIN)
#include "views/widget/widget_win.h"
#elif defined(OS_LINUX)
@@ -27,10 +26,11 @@
#if defined(OS_WIN)
class BorderWidget;
#endif
+class BubbleBorder;
class InfoBubble;
namespace views {
-class Widget;
+class Window;
}
namespace gfx {
@@ -48,13 +48,16 @@ class BorderContents : public views::View {
// Given the size of the contents and the rect to point at, returns the bounds
// of both the border and the contents inside the bubble.
- // |arrow_location| specifies the preferred location for the arrow
+ // |prefer_arrow_on_right| specifies the preferred location for the arrow
// anchor. If the bubble does not fit on the monitor, the arrow location may
- // changed so it can. In case of RTL arrow is mirrored.
+ // changed so it can.
+ //
+ // TODO(pkasting): Maybe this should use mirroring transformations instead,
+ // which would hopefully simplify this code.
virtual void SizeAndGetBounds(
const gfx::Rect& position_relative_to, // In screen coordinates
- BubbleBorder::ArrowLocation arrow_location,
const gfx::Size& contents_size,
+ bool prefer_arrow_on_right,
gfx::Rect* contents_bounds, // Returned in window coordinates
gfx::Rect* window_bounds); // Returned in screen coordinates
@@ -93,12 +96,11 @@ class BorderWidget : public views::WidgetWin {
// Given the size of the contained contents (without margins), and the rect
// (in screen coordinates) to point to, sets the border window positions and
// sizes the border window and returns the bounds (in screen coordinates) the
- // contents should use. |arrow_location| is prefered arrow location,
- // the function tries to preserve the location and direction, in case of RTL
- // arrow location is mirrored.
+ // contents should use. |is_rtl| is supplied to
+ // BorderContents::InitAndGetBounds(), see its declaration for details.
virtual gfx::Rect SizeAndGetBounds(const gfx::Rect& position_relative_to,
- BubbleBorder::ArrowLocation arrow_location,
- const gfx::Size& contents_size);
+ const gfx::Size& contents_size,
+ bool is_rtl);
protected:
// Instanciates and returns the BorderContents this BorderWidget should use.
@@ -127,6 +129,12 @@ class InfoBubbleDelegate {
// Whether the InfoBubble should be closed when the Esc key is pressed.
virtual bool CloseOnEscape() = 0;
+
+ // Whether the default placement of the anchor is on the origin side of the
+ // text direction. For example: if true (the default) in LTR text direction,
+ // the ArrowLocation will be TOP_LEFT, if false it will be TOP_RIGHT.
+ // RTL is the reverse.
+ virtual bool PreferOriginSideAnchor() { return true; }
};
// TODO(sky): this code is ifdef-tastic. It might be cleaner to refactor the
@@ -145,14 +153,15 @@ class InfoBubble
// screen coordinates at which the InfoBubble will point. Show() takes
// ownership of |contents| and deletes the created InfoBubble when another
// window is activated. You can explicitly close the bubble by invoking
- // Close(). |arrow_location| specifies prefered bubble alignment.
- // You may provide an optional |delegate| to:
+ // Close(). You may provide an optional |delegate| to:
// - Be notified when the InfoBubble is closed.
// - Prevent the InfoBubble from being closed when the Escape key is
// pressed (the default behavior).
- static InfoBubble* Show(views::Widget* parent,
+ // - Have the InfoBubble prefer to anchor its arrow to the non-origin
+ // side of text direction. (see comment above
+ // InfoBubbleDelegate::PreferOriginSideAnchor); .
+ static InfoBubble* Show(views::Window* parent,
const gfx::Rect& position_relative_to,
- BubbleBorder::ArrowLocation arrow_location,
views::View* contents,
InfoBubbleDelegate* delegate);
@@ -170,9 +179,8 @@ class InfoBubble
virtual ~InfoBubble() {}
// Creates the InfoBubble.
- virtual void Init(views::Widget* parent,
+ virtual void Init(views::Window* parent,
const gfx::Rect& position_relative_to,
- BubbleBorder::ArrowLocation arrow_location,
views::View* contents,
InfoBubbleDelegate* delegate);
@@ -209,11 +217,13 @@ class InfoBubble
// The delegate, if any.
InfoBubbleDelegate* delegate_;
+ // The window that this InfoBubble is parented to.
+ views::Window* parent_;
+
// Have we been closed?
bool closed_;
gfx::Rect position_relative_to_;
- BubbleBorder::ArrowLocation arrow_location_;
views::View* contents_;
diff --git a/chrome/browser/views/location_bar/content_setting_image_view.cc b/chrome/browser/views/location_bar/content_setting_image_view.cc
index 747af48..03b30eb 100644
--- a/chrome/browser/views/location_bar/content_setting_image_view.cc
+++ b/chrome/browser/views/location_bar/content_setting_image_view.cc
@@ -72,8 +72,7 @@ void ContentSettingImageView::OnMouseReleased(const views::MouseEvent& event,
profile_, tab_contents);
DCHECK(!info_bubble_);
info_bubble_ =
- InfoBubble::Show(GetWidget(), screen_bounds, BubbleBorder::TOP_LEFT,
- bubble_contents, this);
+ InfoBubble::Show(GetWindow(), screen_bounds, bubble_contents, this);
bubble_contents->set_info_bubble(info_bubble_);
}
diff --git a/chrome/browser/views/location_bar/location_bar_view.cc b/chrome/browser/views/location_bar/location_bar_view.cc
index 1d75f3a..16ea52f 100644
--- a/chrome/browser/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/views/location_bar/location_bar_view.cc
@@ -781,8 +781,8 @@ void LocationBarView::ShowFirstRunBubbleInternal(
if (UILayoutIsRightToLeft())
origin.set_x(width() - origin.x());
views::View::ConvertPointToScreen(this, &origin);
- FirstRunBubble::Show(profile_, GetWidget(), gfx::Rect(origin, gfx::Size()),
- BubbleBorder::TOP_LEFT, bubble_type);
+ FirstRunBubble::Show(profile_, GetWindow(), gfx::Rect(origin, gfx::Size()),
+ bubble_type);
#endif
}
diff --git a/chrome/browser/views/pinned_contents_info_bubble.cc b/chrome/browser/views/pinned_contents_info_bubble.cc
index 8f6c1636..a4edcf1 100644
--- a/chrome/browser/views/pinned_contents_info_bubble.cc
+++ b/chrome/browser/views/pinned_contents_info_bubble.cc
@@ -5,14 +5,15 @@
#include "chrome/browser/views/pinned_contents_info_bubble.h"
#include "chrome/browser/views/bubble_border.h"
+#include "views/window/window.h"
#if defined(OS_WIN)
// BorderWidget ---------------------------------------------------------------
void PinnedContentsBorderContents::SizeAndGetBounds(
const gfx::Rect& position_relative_to,
- BubbleBorder::ArrowLocation arrow_location,
const gfx::Size& contents_size,
+ bool prefer_arrow_on_right,
gfx::Rect* contents_bounds,
gfx::Rect* window_bounds) {
// Arrow offset is calculated from the middle of the |position_relative_to|.
@@ -22,10 +23,10 @@ void PinnedContentsBorderContents::SizeAndGetBounds(
gfx::Insets insets;
bubble_border_->GetInsets(&insets);
offset += kLeftMargin + insets.left() + 1;
- bubble_border_->SetArrowOffset(offset, contents_size);
+ bubble_border_->set_arrow_offset(offset);
BorderContents::SizeAndGetBounds(
- position_relative_to, arrow_location, contents_size,
+ position_relative_to, contents_size, prefer_arrow_on_right,
contents_bounds, window_bounds);
// Now move the y position to make sure the bubble contents overlap the view.
@@ -41,16 +42,14 @@ BorderContents* PinnedContentsBorderWidget::CreateBorderContents() {
// static
PinnedContentsInfoBubble* PinnedContentsInfoBubble::Show(
- views::Widget* parent,
+ views::Window* parent,
const gfx::Rect& position_relative_to,
- BubbleBorder::ArrowLocation arrow_location,
const gfx::Point& bubble_anchor,
views::View* contents,
InfoBubbleDelegate* delegate) {
PinnedContentsInfoBubble* window =
new PinnedContentsInfoBubble(bubble_anchor);
- window->Init(parent, position_relative_to, arrow_location,
- contents, delegate);
+ window->Init(parent, position_relative_to, contents, delegate);
return window;
}
diff --git a/chrome/browser/views/pinned_contents_info_bubble.h b/chrome/browser/views/pinned_contents_info_bubble.h
index d93b0e2..7ceb89b 100644
--- a/chrome/browser/views/pinned_contents_info_bubble.h
+++ b/chrome/browser/views/pinned_contents_info_bubble.h
@@ -18,8 +18,8 @@ class PinnedContentsBorderContents : public BorderContents {
// BorderContents overrides:
virtual void SizeAndGetBounds(
const gfx::Rect& position_relative_to, // In screen coordinates
- BubbleBorder::ArrowLocation arrow_location,
const gfx::Size& contents_size,
+ bool prefer_arrow_on_right,
gfx::Rect* contents_bounds, // Returned in window coordinates
gfx::Rect* window_bounds); // Returned in screen coordinates
@@ -60,13 +60,11 @@ class PinnedContentsInfoBubble : public InfoBubble {
// order to anchor its contents. Once the InfoBubble has been anchored its
// arrow may be pointing to a slightly different |y| location than specified
// in |position_relative_to|.
- static PinnedContentsInfoBubble* Show(
- views::Widget* parent,
- const gfx::Rect& position_relative_to,
- BubbleBorder::ArrowLocation arrow_location,
- const gfx::Point& bubble_anchor_,
- views::View* contents,
- InfoBubbleDelegate* delegate);
+ static PinnedContentsInfoBubble* Show(views::Window* parent,
+ const gfx::Rect& position_relative_to,
+ const gfx::Point& bubble_anchor_,
+ views::View* contents,
+ InfoBubbleDelegate* delegate);
private:
explicit PinnedContentsInfoBubble(const gfx::Point& bubble_anchor)