| Index: chrome/browser/views/bubble_border.cc
|
| ===================================================================
|
| --- chrome/browser/views/bubble_border.cc (revision 26373)
|
| +++ chrome/browser/views/bubble_border.cc (working copy)
|
| @@ -20,7 +20,15 @@
|
| SkBitmap* BubbleBorder::bottom_right_ = NULL;
|
| SkBitmap* BubbleBorder::bottom_ = NULL;
|
| SkBitmap* BubbleBorder::bottom_left_ = NULL;
|
| +SkBitmap* BubbleBorder::top_arrow_ = NULL;
|
| +SkBitmap* BubbleBorder::bottom_arrow_ = NULL;
|
|
|
| +//static
|
| +int BubbleBorder::arrow_x_offset_;
|
| +
|
| +// The height inside the arrow image, in pixels.
|
| +static const int kArrowInteriorHeight = 7;
|
| +
|
| gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& position_relative_to,
|
| const gfx::Size& contents_size) const {
|
| // The spacing (in pixels) between |position_relative_to| and the bubble
|
| @@ -34,16 +42,35 @@
|
| border_size.Enlarge(insets.left() + insets.right(),
|
| insets.top() + insets.bottom());
|
|
|
| - int x = position_relative_to.x() + (position_relative_to.width() / 2) -
|
| - (contents_size.width() / 2) - insets.left();
|
| - int y = position_relative_to.bottom() - (top_->height() - kBubbleSpacing);
|
| + // Screen position depends on the arrow location.
|
| + int x = position_relative_to.x() + (position_relative_to.width() / 2);
|
| + if (arrow_is_left())
|
| + x -= arrow_x_offset_;
|
| + else if (arrow_location_ == NONE)
|
| + x -= ((contents_size.width() / 2) + insets.left());
|
| + else
|
| + x += (arrow_x_offset_ - border_size.width() + 1);
|
| + int y = position_relative_to.y();
|
| + if (arrow_is_top()) {
|
| + y += (position_relative_to.height() -
|
| + (top_arrow_->height() - kBubbleSpacing));
|
| + } else if (arrow_location_ == NONE) {
|
| + y += (position_relative_to.height() - (top_->height() - kBubbleSpacing));
|
| + } else {
|
| + y += ((bottom_arrow_->height() - kBubbleSpacing) - border_size.height());
|
| + }
|
|
|
| return gfx::Rect(x, y, border_size.width(), border_size.height());
|
| }
|
|
|
| void BubbleBorder::GetInsets(gfx::Insets* insets) const {
|
| - insets->Set(top_->height(), left_->width(), bottom_->height(),
|
| - right_->width());
|
| + int top = top_->height();
|
| + int bottom = bottom_->height();
|
| + if (arrow_is_top())
|
| + top = std::max(top, top_arrow_->height());
|
| + else if (arrow_location_ != NONE)
|
| + bottom = std::max(bottom, bottom_arrow_->height());
|
| + insets->Set(top, left_->width(), bottom, right_->width());
|
| }
|
|
|
| // static
|
| @@ -60,7 +87,16 @@
|
| bottom_right_ = rb.GetBitmapNamed(IDR_BUBBLE_BR);
|
| bottom_ = rb.GetBitmapNamed(IDR_BUBBLE_B);
|
| bottom_left_ = rb.GetBitmapNamed(IDR_BUBBLE_BL);
|
| + top_arrow_ = rb.GetBitmapNamed(IDR_BUBBLE_T_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_ =
|
| + (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()));
|
| +
|
| initialized = true;
|
| }
|
| }
|
| @@ -82,17 +118,21 @@
|
|
|
| /* The variables below can be confusing; here's what they mean:
|
| *
|
| - * border_top∙∙∙∙∙∙∙┌────┬────────┬────┐
|
| - * │ / │--------│ \ │
|
| - * top∙∙∙∙∙∙∙∙∙∙∙∙∙∙│ / ├────────┤ \ │
|
| - * tl_bottom∙∙∙∙∙∙├───┬┘ └┬───┤∙∙∙∙∙∙tr_bottom
|
| - * │ | │ │ | │
|
| - * │ | │ │ | │
|
| - * │ | │ │ | │
|
| - * bl_y∙∙∙∙∙∙∙∙∙∙∙├───┴┐ ┌┴───┤∙∙∙∙∙∙br_y
|
| - * bottom∙∙∙∙∙∙∙∙∙∙∙│ \ ├────────┤ / │
|
| - * │ \ │--------│ / │
|
| - * border_bottom∙∙∙∙└────┴────────┴────┘
|
| + * 0∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙∙┌───┐ ┌───┐
|
| + * border_top∙∙∙∙∙∙∙┌────┬─┤ ▲ ├──────┤ ▲ ├─┬────┐
|
| + * │ / │-│∙ ∙│------│∙ ∙│-│ \ │
|
| + * top∙∙∙∙∙∙∙∙∙∙∙∙∙∙│ / ├─┴───┴──────┴───┴─┤ \ │
|
| + * tl_bottom∙∙∙∙∙∙├───┬┘ └┬───┤∙∙∙∙∙∙tr_bottom
|
| + * │ | │ │ | │
|
| + * │ | │ │ | │
|
| + * │ | │ │ | │
|
| + * bl_y∙∙∙∙∙∙∙∙∙∙∙├───┴┐ ┌┴───┤∙∙∙∙∙∙br_y
|
| + * bottom∙∙∙∙∙∙∙∙∙∙∙│ \ ├─┬───┬──────┬───┬─┤ / │
|
| + * │ \ │-│. .│------│. .│-│ / │
|
| + * border_bottom∙∙∙∙└────┴─┤ ▼ ├──────┤ ▼ ├─┴────┘
|
| + * view.height()∙∙∙∙∙∙∙∙∙∙∙└───┘ └───┘
|
| + *
|
| + * (At most one of the arrows will be drawn)
|
| */
|
|
|
| gfx::Insets insets;
|
| @@ -109,10 +149,6 @@
|
| // Top left corner
|
| canvas->DrawBitmapInt(*top_left_, 0, border_top);
|
|
|
| - // Top edge
|
| - canvas->TileImageInt(*top_, tl_width, border_top, width - tl_width - tr_width,
|
| - t_height);
|
| -
|
| // Top right corner
|
| canvas->DrawBitmapInt(*top_right_, width - tr_width, border_top);
|
|
|
| @@ -123,13 +159,109 @@
|
| // Bottom right corner
|
| canvas->DrawBitmapInt(*bottom_right_, width - br_width, br_y);
|
|
|
| - // Bottom edge
|
| - canvas->TileImageInt(*bottom_, bl_width, bottom, width - bl_width - br_width,
|
| - b_height);
|
|
|
| // Bottom left corner
|
| canvas->DrawBitmapInt(*bottom_left_, 0, bl_y);
|
|
|
| // Left edge
|
| canvas->TileImageInt(*left_, 0, tl_bottom, left_->width(), bl_y - tl_bottom);
|
| +
|
| + // Arrow edge, if necessary
|
| + bool should_draw_top_edge = true;
|
| + 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_top()) {
|
| + should_draw_top_edge = false;
|
| + 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);
|
| + } else {
|
| + 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);
|
| + }
|
| + int arrow_width = (arrow_is_top() ? top_arrow_ : bottom_arrow_)->width();
|
| + int arrow_center = arrow_is_left() ?
|
| + arrow_x_offset_ : width - arrow_x_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);
|
| + }
|
| +
|
| + // 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 edge, if not already drawn
|
| + if (should_draw_top_edge) {
|
| + canvas->TileImageInt(*top_, tl_width, border_top,
|
| + width - tl_width - tr_width, t_height);
|
| + }
|
| +
|
| + // Bottom edge, if not already drawn
|
| + if (should_draw_bottom_edge) {
|
| + canvas->TileImageInt(*bottom_, bl_width, bottom,
|
| + width - bl_width - br_width, b_height);
|
| + }
|
| }
|
|
|