summaryrefslogtreecommitdiffstats
path: root/ui/views/bubble/bubble_frame_view.cc
blob: 85e1f6ee17d95440ab30e17b5056b3e259cb167a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "views/bubble/bubble_frame_view.h"

#include <algorithm>

#include "ui/views/window/client_view.h"
#include "views/bubble/border_contents_view.h"
#include "views/bubble/bubble_border.h"
#include "views/layout/fill_layout.h"
#include "views/widget/widget.h"

namespace views {

BubbleFrameView::BubbleFrameView(BubbleBorder::ArrowLocation location,
                                 const gfx::Size& client_size,
                                 SkColor color,
                                 bool allow_bubble_offscreen)
    : border_contents_(new BorderContentsView()),
      location_(location),
      allow_bubble_offscreen_(allow_bubble_offscreen) {
  border_contents_->Init();
  bubble_border()->set_arrow_location(location_);
  bubble_border()->set_background_color(color);
  SetLayoutManager(new views::FillLayout());
  AddChildView(border_contents_);
  gfx::Rect bounds(gfx::Point(), client_size);
  gfx::Rect windows_bounds = GetWindowBoundsForClientBounds(bounds);
  border_contents_->SetBoundsRect(
      gfx::Rect(gfx::Point(), windows_bounds.size()));
  SetBoundsRect(windows_bounds);
}

BubbleFrameView::~BubbleFrameView() {}

gfx::Rect BubbleFrameView::GetBoundsForClientView() const {
  gfx::Insets margin;
  bubble_border()->GetInsets(&margin);
  margin += border_contents_->content_margins();
  return gfx::Rect(margin.left(),
                   margin.top(),
                   std::max(width() - margin.width(), 0),
                   std::max(height() - margin.height(), 0));
}

gfx::Rect BubbleFrameView::GetWindowBoundsForClientBounds(
    const gfx::Rect& client_bounds) const {
  // The |client_bounds| origin is the bubble arrow anchor point.
  gfx::Rect position_relative_to(client_bounds.origin(), gfx::Size());
  // The |client_bounds| size is the bubble client view size.
  gfx::Rect content_bounds;
  gfx::Rect window_bounds;
  border_contents_->SizeAndGetBounds(position_relative_to,
                                     location_,
                                     allow_bubble_offscreen_,
                                     client_bounds.size(),
                                     &content_bounds,
                                     &window_bounds);
  return window_bounds;
}

int BubbleFrameView::NonClientHitTest(const gfx::Point& point) {
  return GetWidget()->client_view()->NonClientHitTest(point);
}

gfx::Size BubbleFrameView::GetPreferredSize() {
  Widget* widget = GetWidget();
  gfx::Rect rect(gfx::Point(), widget->client_view()->GetPreferredSize());
  return widget->non_client_view()->GetWindowBoundsForClientBounds(rect).size();
}

BubbleBorder* BubbleFrameView::bubble_border() const {
  return static_cast<BubbleBorder*>(border_contents_->border());
}

}  // namespace views