summaryrefslogtreecommitdiffstats
path: root/chrome/views/single_split_view.cc
blob: 845d98036e5c7ee36112d693ead13165a248dcc4 (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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// Copyright (c) 2006-2008 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 "chrome/views/single_split_view.h"

#include "chrome/common/gfx/chrome_canvas.h"
#include "chrome/views/background.h"
#include "skia/ext/skia_utils_win.h"

namespace views {

// Size of the divider in pixels.
static const int kDividerSize = 4;

SingleSplitView::SingleSplitView(View* leading, View* trailing)
    : divider_x_(-1) {
  AddChildView(leading);
  AddChildView(trailing);
  set_background(
      views::Background::CreateSolidBackground(
          skia::COLORREFToSkColor(GetSysColor(COLOR_3DFACE))));
}

void SingleSplitView::Layout() {
  if (GetChildViewCount() != 2)
    return;

  View* leading = GetChildViewAt(0);
  View* trailing = GetChildViewAt(1);
  if (divider_x_ < 0)
    divider_x_ = (width() - kDividerSize) / 2;
  else
    divider_x_ = std::min(divider_x_, width() - kDividerSize);
  leading->SetBounds(0, 0, divider_x_, height());
  trailing->SetBounds(divider_x_ + kDividerSize, 0,
                      width() - divider_x_ - kDividerSize, height());

  SchedulePaint();

  // Invoke super's implementation so that the children are layed out.
  View::Layout();
}

gfx::Size SingleSplitView::GetPreferredSize() {
  int width = 0;
  int height = 0;
  for (int i = 0; i < 2 && i < GetChildViewCount(); ++i) {
    View* view = GetChildViewAt(i);
    gfx::Size pref = view->GetPreferredSize();
    width += pref.width();
    height = std::max(height, pref.height());
  }
  width += kDividerSize;
  return gfx::Size(width, height);
}

HCURSOR SingleSplitView::GetCursorForPoint(Event::EventType event_type,
                                           int x,
                                           int y) {
  if (IsPointInDivider(x)) {
    static HCURSOR resize_cursor = LoadCursor(NULL, IDC_SIZEWE);
    return resize_cursor;
  }
  return NULL;
}

bool SingleSplitView::OnMousePressed(const MouseEvent& event) {
  if (!IsPointInDivider(event.x()))
    return false;
  drag_info_.initial_mouse_x = event.x();
  drag_info_.initial_divider_x = divider_x_;
  return true;
}

bool SingleSplitView::OnMouseDragged(const MouseEvent& event) {
  if (GetChildViewCount() < 2)
    return false;

  int delta_x = event.x() - drag_info_.initial_mouse_x;
  if (UILayoutIsRightToLeft())
    delta_x *= -1;
  // Honor the minimum size when resizing.
  int new_width = std::max(GetChildViewAt(0)->GetMinimumSize().width(),
                           drag_info_.initial_divider_x + delta_x);

  // And don't let the view get bigger than our width.
  new_width = std::min(width() - kDividerSize, new_width);

  if (new_width != divider_x_) {
    set_divider_x(new_width);
    Layout();
  }
  return true;
}

void SingleSplitView::OnMouseReleased(const MouseEvent& event, bool canceled) {
  if (GetChildViewCount() < 2)
    return;

  if (canceled && drag_info_.initial_divider_x != divider_x_) {
    set_divider_x(drag_info_.initial_divider_x);
    Layout();
  }
}

bool SingleSplitView::IsPointInDivider(int x) {
  if (GetChildViewCount() < 2)
    return false;

  int divider_relative_x =
      x - GetChildViewAt(UILayoutIsRightToLeft() ? 1 : 0)->width();
  return (divider_relative_x >= 0 && divider_relative_x < kDividerSize);
}

}  // namespace views