summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xchrome/app/theme/bubble_l_arrow.pngbin0 -> 328 bytes
-rwxr-xr-xchrome/app/theme/bubble_r_arrow.pngbin0 -> 324 bytes
-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
19 files changed, 501 insertions, 318 deletions
diff --git a/chrome/app/theme/bubble_l_arrow.png b/chrome/app/theme/bubble_l_arrow.png
new file mode 100755
index 0000000..9663076
--- /dev/null
+++ b/chrome/app/theme/bubble_l_arrow.png
Binary files differ
diff --git a/chrome/app/theme/bubble_r_arrow.png b/chrome/app/theme/bubble_r_arrow.png
new file mode 100755
index 0000000..fab4def
--- /dev/null
+++ b/chrome/app/theme/bubble_r_arrow.png
Binary files differ
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd
index cfa5851..beeb4e9 100644
--- a/chrome/app/theme/theme_resources.grd
+++ b/chrome/app/theme/theme_resources.grd
@@ -304,6 +304,8 @@
<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 87c6bb9..7b15433 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->frame()->GetWindow(),
- bounds, bubble_anchor, app_launcher->info_bubble_content_,
- app_launcher);
+ PinnedContentsInfoBubble::Show(browser_view->GetWidget(),
+ bounds, BubbleBorder::TOP_LEFT, 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 f569ff9..4542d3a 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* bubble_border = new BubbleBorder(BubbleBorder::NONE);
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 837969c..101ae5a 100644
--- a/chrome/browser/views/bookmark_bubble_view.cc
+++ b/chrome/browser/views/bookmark_bubble_view.cc
@@ -25,6 +25,8 @@
#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;
@@ -146,7 +148,8 @@ void BookmarkBubbleView::Show(views::Window* parent,
return;
bubble_ = new BookmarkBubbleView(delegate, profile, url, newly_bookmarked);
- InfoBubble::Show(parent, bounds, bubble_, bubble_);
+ InfoBubble::Show(parent->GetClientView()->GetWidget(), bounds,
+ BubbleBorder::TOP_LEFT, 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 3548286..468026e 100644
--- a/chrome/browser/views/bubble_border.cc
+++ b/chrome/browser/views/bubble_border.cc
@@ -22,9 +22,11 @@ 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_x_offset_;
+int BubbleBorder::arrow_offset_;
// The height inside the arrow image, in pixels.
static const int kArrowInteriorHeight = 7;
@@ -39,41 +41,126 @@ 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 the bottom arrow
- // has lots of shadow below it and the top arrow is given an equivalent amount
- // of padding.
+ // The arrow should overlap the target by some amount since there is space
+ // for shadow between arrow tip and bitmap bounds.
const int kArrowOverlap = 3;
- 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 x = position_relative_to.x();
int y = position_relative_to.y();
- 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);
+ 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;
+ }
return gfx::Rect(x, y, border_size.width(), border_size.height());
}
void BubbleBorder::GetInsets(gfx::Insets* insets) const {
- 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();
+ 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;
}
- insets->Set(top, left_->width(), bottom, right_->width());
+ 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_;
}
// static
@@ -90,15 +177,22 @@ 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 inset for arrow by ensuring that the widest arrow
- // and corner images will have enough room to avoid overlap.
- arrow_x_offset_ =
+ // 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 =
(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;
}
@@ -106,177 +200,232 @@ void BubbleBorder::InitClass() {
void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const {
// Convenience shorthand variables.
- 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.
- */
+ // 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();
gfx::Insets insets;
GetInsets(&insets);
- 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 {
- 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);
+ 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;
}
- // 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);
+ // 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());
+ } else {
+ canvas->TileImageInt(*left_, left, top + tl_height, l_width,
+ height - tl_height - bl_height);
+ }
- // Arrow edge, if necessary
- bool should_draw_top_edge = false;
- bool should_draw_bottom_edge = true;
if (arrow_location_ != NONE) {
- /* 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);
+ // 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());
} else {
- 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);
+ canvas->TileImageInt(*top_, left + tl_width, top,
+ width - tl_width - tr_width, t_height);
}
- // 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);
+ // Top right corner.
+ canvas->DrawBitmapInt(*top_right_, right - tr_width, top);
}
- // 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);
+ // 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);
}
- // Bottom edge, if not already drawn
- if (should_draw_bottom_edge) {
- canvas->TileImageInt(*bottom_, bl_width, bottom,
+ // 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,
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 3670503..753d1e6 100644
--- a/chrome/browser/views/bubble_border.h
+++ b/chrome/browser/views/bubble_border.h
@@ -11,25 +11,31 @@
class SkBitmap;
-// 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.
+// Renders a border, with optional arrow, and a custom dropshadow.
+// This can be used to produce floating "bubble" objects with rounded corners.
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 {
- NONE,
- TOP_LEFT,
- TOP_RIGHT,
- BOTTOM_LEFT,
- BOTTOM_RIGHT
+ 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.
};
- BubbleBorder() : override_arrow_x_offset_(0),
- arrow_location_(NONE),
- background_color_(SK_ColorWHITE) {
+ explicit BubbleBorder(ArrowLocation arrow_location)
+ : override_arrow_offset_(0),
+ arrow_location_(arrow_location),
+ background_color_(SK_ColorWHITE) {
InitClass();
}
@@ -47,10 +53,28 @@ class BubbleBorder : public views::Border {
arrow_location_ = arrow_location;
}
- // 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;
+ 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 the background color for the arrow body. This is irrelevant if you do
@@ -64,12 +88,15 @@ 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;
@@ -79,20 +106,26 @@ 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_;
@@ -102,13 +135,16 @@ 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_;
- static int arrow_x_offset_;
+ // Minimal offset of the arrow from the closet edge of bounding rect.
+ static int arrow_offset_;
- // If specified, overrides the pre-calculated |arrow_x_offset_| of the arrow.
- int override_arrow_x_offset_;
+ // If specified, overrides the pre-calculated |arrow_offset_| of the arrow.
+ int override_arrow_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 b02b56d..36fd253 100644
--- a/chrome/browser/views/extensions/extension_installed_bubble.cc
+++ b/chrome/browser/views/extensions/extension_installed_bubble.cc
@@ -332,7 +332,8 @@ void ExtensionInstalledBubble::ShowInternal() {
bubble_content_ = new InstalledBubbleContent(extension_, type_,
&icon_);
- InfoBubble::Show(browser_view->GetWindow(), bounds, bubble_content_, this);
+ InfoBubble::Show(browser_view->GetWidget(), bounds, BubbleBorder::TOP_RIGHT,
+ 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 c49515d..b4ee946 100644
--- a/chrome/browser/views/extensions/extension_installed_bubble.h
+++ b/chrome/browser/views/extensions/extension_installed_bubble.h
@@ -67,10 +67,6 @@ 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 3e91205a..f30aac9 100644
--- a/chrome/browser/views/extensions/extension_popup.cc
+++ b/chrome/browser/views/extensions/extension_popup.cc
@@ -114,9 +114,7 @@ ExtensionPopup::ExtensionPopup(ExtensionHost* host,
chromeos::WM_IPC_WINDOW_CHROME_INFO_BUBBLE,
NULL);
#endif
- border_ = new BubbleBorder;
- border_->set_arrow_location(arrow_location);
-
+ border_ = new BubbleBorder(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 692650c..7728888 100644
--- a/chrome/browser/views/first_run_bubble.cc
+++ b/chrome/browser/views/first_run_bubble.cc
@@ -471,8 +471,9 @@ void FirstRunMinimalBubbleView::FocusWillChange(View* focused_before,
// static
FirstRunBubble* FirstRunBubble::Show(Profile* profile,
- views::Window* parent,
+ views::Widget* parent,
const gfx::Rect& position_relative_to,
+ BubbleBorder::ArrowLocation arrow_location,
FirstRun::BubbleType bubble_type) {
FirstRunBubble* window = new FirstRunBubble();
FirstRunBubbleViewBase* view = NULL;
@@ -491,7 +492,7 @@ FirstRunBubble* FirstRunBubble::Show(Profile* profile,
NOTREACHED();
}
window->set_view(view);
- window->Init(parent, position_relative_to, view, window);
+ window->Init(parent, position_relative_to, arrow_location, 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 cccce32..65752db 100644
--- a/chrome/browser/views/first_run_bubble.h
+++ b/chrome/browser/views/first_run_bubble.h
@@ -16,8 +16,9 @@ class Profile;
class FirstRunBubble : public InfoBubble,
public InfoBubbleDelegate {
public:
- static FirstRunBubble* Show(Profile* profile, views::Window* window,
+ static FirstRunBubble* Show(Profile* profile, views::Widget* parent,
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 3a69a1b..8d30c83 100644
--- a/chrome/browser/views/info_bubble.cc
+++ b/chrome/browser/views/info_bubble.cc
@@ -5,7 +5,6 @@
#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"
@@ -14,6 +13,8 @@
#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)
@@ -32,26 +33,30 @@ const SkColor InfoBubble::kBackgroundColor = SK_ColorWHITE;
void BorderContents::Init() {
DCHECK(!bubble_border_);
- bubble_border_ = new BubbleBorder();
+ bubble_border_ = new BubbleBorder(BubbleBorder::LEFT_TOP);
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);
@@ -62,16 +67,14 @@ 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.
- 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;
+ 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);
}
+
bubble_border_->set_arrow_location(arrow_location);
// Now get the recalculated bounds.
@@ -134,13 +137,13 @@ void BorderWidget::Init(HWND owner) {
gfx::Rect BorderWidget::SizeAndGetBounds(
const gfx::Rect& position_relative_to,
- const gfx::Size& contents_size,
- bool prefer_arrow_on_right) {
+ BubbleBorder::ArrowLocation arrow_location,
+ const gfx::Size& contents_size) {
// 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, contents_size,
- prefer_arrow_on_right, &contents_bounds,
+ border_contents_->SizeAndGetBounds(position_relative_to, arrow_location,
+ contents_size, &contents_bounds,
&window_bounds);
SetBounds(window_bounds);
@@ -174,12 +177,14 @@ LRESULT BorderWidget::OnMouseActivate(HWND window,
// InfoBubble -----------------------------------------------------------------
// static
-InfoBubble* InfoBubble::Show(views::Window* parent,
+InfoBubble* InfoBubble::Show(views::Widget* 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, contents, delegate);
+ window->Init(parent, position_relative_to, arrow_location,
+ contents, delegate);
return window;
}
@@ -194,29 +199,33 @@ InfoBubble::InfoBubble()
border_contents_(NULL),
#endif
delegate_(NULL),
- parent_(NULL),
closed_(false) {
}
-void InfoBubble::Init(views::Window* parent,
+void InfoBubble::Init(views::Widget* 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)
- parent_->DisableInactiveRendering();
+ views::Window* parent_window = parent->GetWindow();
+ if (parent_window)
+ parent_window->DisableInactiveRendering();
set_window_style(WS_POPUP | WS_CLIPCHILDREN);
set_window_ex_style(WS_EX_TOOLWINDOW);
- WidgetWin::Init(parent->GetNativeWindow(), gfx::Rect());
+ WidgetWin::Init(parent->GetNativeView(), gfx::Rect());
#elif defined(OS_LINUX)
MakeTransparent();
make_transient_to_parent();
- WidgetGtk::Init(GTK_WIDGET(parent->GetNativeWindow()), gfx::Rect());
+ WidgetGtk::Init(
+ GTK_WIDGET(static_cast<WidgetGtk*>(parent)->GetNativeView()),
+ gfx::Rect());
#if defined(OS_CHROMEOS)
chromeos::WmIpc::instance()->SetWindowType(
GetNativeView(),
@@ -240,9 +249,6 @@ void InfoBubble::Init(views::Window* 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());
@@ -250,8 +256,8 @@ void InfoBubble::Init(views::Window* parent,
// Initialize and position the border window.
window_bounds = border_->SizeAndGetBounds(position_relative_to,
- contents->GetPreferredSize(),
- prefer_arrow_on_right);
+ arrow_location,
+ contents->GetPreferredSize());
// Make |contents| take up the entire contents view.
contents_view->SetLayoutManager(new views::FillLayout);
@@ -265,7 +271,7 @@ void InfoBubble::Init(views::Window* parent,
border_contents_->Init();
gfx::Rect contents_bounds;
border_contents_->SizeAndGetBounds(position_relative_to,
- contents->GetPreferredSize(), prefer_arrow_on_right,
+ arrow_location, contents->GetPreferredSize(),
&contents_bounds, &window_bounds);
// This new view must be added before |contents| so it will paint under it.
contents_view->AddChildView(0, border_contents_);
@@ -304,19 +310,15 @@ 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_,
- contents_->GetPreferredSize(),
- prefer_arrow_on_right);
+ arrow_location_,
+ contents_->GetPreferredSize());
#else
gfx::Rect contents_bounds;
border_contents_->SizeAndGetBounds(position_relative_to_,
- contents_->GetPreferredSize(), prefer_arrow_on_right,
+ arrow_location_, contents_->GetPreferredSize(),
&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 4b76507..fa15bf7 100644
--- a/chrome/browser/views/info_bubble.h
+++ b/chrome/browser/views/info_bubble.h
@@ -8,6 +8,7 @@
#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)
@@ -26,11 +27,10 @@
#if defined(OS_WIN)
class BorderWidget;
#endif
-class BubbleBorder;
class InfoBubble;
namespace views {
-class Window;
+class Widget;
}
namespace gfx {
@@ -48,16 +48,13 @@ 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.
- // |prefer_arrow_on_right| specifies the preferred location for the arrow
+ // |arrow_location| 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.
- //
- // TODO(pkasting): Maybe this should use mirroring transformations instead,
- // which would hopefully simplify this code.
+ // changed so it can. In case of RTL arrow is mirrored.
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
@@ -96,11 +93,12 @@ 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. |is_rtl| is supplied to
- // BorderContents::InitAndGetBounds(), see its declaration for details.
+ // 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.
virtual gfx::Rect SizeAndGetBounds(const gfx::Rect& position_relative_to,
- const gfx::Size& contents_size,
- bool is_rtl);
+ BubbleBorder::ArrowLocation arrow_location,
+ const gfx::Size& contents_size);
protected:
// Instanciates and returns the BorderContents this BorderWidget should use.
@@ -129,12 +127,6 @@ 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
@@ -153,15 +145,14 @@ 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(). You may provide an optional |delegate| to:
+ // Close(). |arrow_location| specifies prefered bubble alignment.
+ // 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).
- // - 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,
+ static InfoBubble* Show(views::Widget* parent,
const gfx::Rect& position_relative_to,
+ BubbleBorder::ArrowLocation arrow_location,
views::View* contents,
InfoBubbleDelegate* delegate);
@@ -179,8 +170,9 @@ class InfoBubble
virtual ~InfoBubble() {}
// Creates the InfoBubble.
- virtual void Init(views::Window* parent,
+ virtual void Init(views::Widget* parent,
const gfx::Rect& position_relative_to,
+ BubbleBorder::ArrowLocation arrow_location,
views::View* contents,
InfoBubbleDelegate* delegate);
@@ -217,13 +209,11 @@ 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 03b30eb..747af48 100644
--- a/chrome/browser/views/location_bar/content_setting_image_view.cc
+++ b/chrome/browser/views/location_bar/content_setting_image_view.cc
@@ -72,7 +72,8 @@ void ContentSettingImageView::OnMouseReleased(const views::MouseEvent& event,
profile_, tab_contents);
DCHECK(!info_bubble_);
info_bubble_ =
- InfoBubble::Show(GetWindow(), screen_bounds, bubble_contents, this);
+ InfoBubble::Show(GetWidget(), screen_bounds, BubbleBorder::TOP_LEFT,
+ 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 16ea52f..1d75f3a 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_, GetWindow(), gfx::Rect(origin, gfx::Size()),
- bubble_type);
+ FirstRunBubble::Show(profile_, GetWidget(), gfx::Rect(origin, gfx::Size()),
+ BubbleBorder::TOP_LEFT, bubble_type);
#endif
}
diff --git a/chrome/browser/views/pinned_contents_info_bubble.cc b/chrome/browser/views/pinned_contents_info_bubble.cc
index a4edcf1..8f6c1636 100644
--- a/chrome/browser/views/pinned_contents_info_bubble.cc
+++ b/chrome/browser/views/pinned_contents_info_bubble.cc
@@ -5,15 +5,14 @@
#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|.
@@ -23,10 +22,10 @@ void PinnedContentsBorderContents::SizeAndGetBounds(
gfx::Insets insets;
bubble_border_->GetInsets(&insets);
offset += kLeftMargin + insets.left() + 1;
- bubble_border_->set_arrow_offset(offset);
+ bubble_border_->SetArrowOffset(offset, contents_size);
BorderContents::SizeAndGetBounds(
- position_relative_to, contents_size, prefer_arrow_on_right,
+ position_relative_to, arrow_location, contents_size,
contents_bounds, window_bounds);
// Now move the y position to make sure the bubble contents overlap the view.
@@ -42,14 +41,16 @@ BorderContents* PinnedContentsBorderWidget::CreateBorderContents() {
// static
PinnedContentsInfoBubble* PinnedContentsInfoBubble::Show(
- views::Window* parent,
+ views::Widget* 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, contents, delegate);
+ window->Init(parent, position_relative_to, arrow_location,
+ 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 7ceb89b..d93b0e2 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,11 +60,13 @@ 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::Window* parent,
- const gfx::Rect& position_relative_to,
- const gfx::Point& bubble_anchor_,
- views::View* contents,
- InfoBubbleDelegate* delegate);
+ 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);
private:
explicit PinnedContentsInfoBubble(const gfx::Point& bubble_anchor)