diff options
author | dpolukhin@chromium.org <dpolukhin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-06 12:36:01 +0000 |
---|---|---|
committer | dpolukhin@chromium.org <dpolukhin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-06 12:36:01 +0000 |
commit | 6c70e1efa665b0cbd13f79597de27ecca7fa4854 (patch) | |
tree | 76ac328f8111134d7698ae0fc92efc99039b3f49 /chrome/browser/views | |
parent | 41fa44caf6cf4e7c789af0db508ef64efb20a53d (diff) | |
download | chromium_src-6c70e1efa665b0cbd13f79597de27ecca7fa4854.zip chromium_src-6c70e1efa665b0cbd13f79597de27ecca7fa4854.tar.gz chromium_src-6c70e1efa665b0cbd13f79597de27ecca7fa4854.tar.bz2 |
Add ability to place bubble arrow on left and right side of the bubble or make it float with top edge.
BUG=crosbug.com/2800
TEST=Should be no visible changes with info bubble, everything should work as before. Bubble is used for example in bookmarking.
Review URL: http://codereview.chromium.org/1820002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@46564 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/views')
-rw-r--r-- | chrome/browser/views/app_launcher.cc | 6 | ||||
-rw-r--r-- | chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc | 2 | ||||
-rw-r--r-- | chrome/browser/views/bookmark_bubble_view.cc | 5 | ||||
-rw-r--r-- | chrome/browser/views/bubble_border.cc | 521 | ||||
-rw-r--r-- | chrome/browser/views/bubble_border.h | 104 | ||||
-rw-r--r-- | chrome/browser/views/extensions/extension_installed_bubble.cc | 3 | ||||
-rw-r--r-- | chrome/browser/views/extensions/extension_installed_bubble.h | 4 | ||||
-rw-r--r-- | chrome/browser/views/extensions/extension_popup.cc | 4 | ||||
-rw-r--r-- | chrome/browser/views/first_run_bubble.cc | 5 | ||||
-rw-r--r-- | chrome/browser/views/first_run_bubble.h | 3 | ||||
-rw-r--r-- | chrome/browser/views/info_bubble.cc | 82 | ||||
-rw-r--r-- | chrome/browser/views/info_bubble.h | 44 | ||||
-rw-r--r-- | chrome/browser/views/location_bar/content_setting_image_view.cc | 3 | ||||
-rw-r--r-- | chrome/browser/views/location_bar/location_bar_view.cc | 4 | ||||
-rw-r--r-- | chrome/browser/views/pinned_contents_info_bubble.cc | 13 | ||||
-rw-r--r-- | chrome/browser/views/pinned_contents_info_bubble.h | 14 |
16 files changed, 499 insertions, 318 deletions
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) |