| OLD | NEW | 
|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "views/controls/single_split_view.h" | 5 #include "views/controls/single_split_view.h" | 
| 6 | 6 | 
| 7 #if defined(OS_LINUX) | 7 #if defined(OS_LINUX) | 
| 8 #include <gdk/gdk.h> | 8 #include <gdk/gdk.h> | 
| 9 #endif | 9 #endif | 
| 10 | 10 | 
| 11 #include "gfx/canvas.h" | 11 #include "gfx/canvas.h" | 
| 12 #include "skia/ext/skia_utils_win.h" | 12 #include "skia/ext/skia_utils_win.h" | 
| 13 #include "views/background.h" | 13 #include "views/background.h" | 
| 14 | 14 | 
| 15 #if defined(OS_LINUX) | 15 #if defined(OS_LINUX) | 
| 16 #include "gfx/gtk_util.h" | 16 #include "gfx/gtk_util.h" | 
| 17 #endif | 17 #endif | 
| 18 | 18 | 
| 19 namespace views { | 19 namespace views { | 
| 20 | 20 | 
| 21 // Size of the divider in pixels. | 21 // Size of the divider in pixels. | 
| 22 static const int kDividerSize = 4; | 22 static const int kDividerSize = 4; | 
| 23 | 23 | 
| 24 SingleSplitView::SingleSplitView(View* leading, | 24 SingleSplitView::SingleSplitView(View* leading, | 
| 25                                  View* trailing, | 25                                  View* trailing, | 
| 26                                  Orientation orientation) | 26                                  Orientation orientation, | 
|  | 27                                  Observer* observer) | 
| 27     : is_horizontal_(orientation == HORIZONTAL_SPLIT), | 28     : is_horizontal_(orientation == HORIZONTAL_SPLIT), | 
| 28       divider_offset_(-1), | 29       divider_offset_(-1), | 
| 29       resize_leading_on_bounds_change_(true) { | 30       resize_leading_on_bounds_change_(true), | 
|  | 31       observer_(observer) { | 
| 30   AddChildView(leading); | 32   AddChildView(leading); | 
| 31   AddChildView(trailing); | 33   AddChildView(trailing); | 
| 32 #if defined(OS_WIN) | 34 #if defined(OS_WIN) | 
| 33   set_background( | 35   set_background( | 
| 34       views::Background::CreateSolidBackground( | 36       views::Background::CreateSolidBackground( | 
| 35           skia::COLORREFToSkColor(GetSysColor(COLOR_3DFACE)))); | 37           skia::COLORREFToSkColor(GetSysColor(COLOR_3DFACE)))); | 
| 36 #endif | 38 #endif | 
| 37 } | 39 } | 
| 38 | 40 | 
| 39 void SingleSplitView::DidChangeBounds(const gfx::Rect& previous, | 41 void SingleSplitView::DidChangeBounds(const gfx::Rect& previous, | 
| 40                                       const gfx::Rect& current) { | 42                                       const gfx::Rect& current) { | 
| 41   if (resize_leading_on_bounds_change_) { | 43   divider_offset_ = CalculateDividerOffset(divider_offset_, previous, current); | 
| 42     // We do not update divider_offset_ on minimize (to zero) and on restore |  | 
| 43     // (to largest value). As a result we get back to the original value upon |  | 
| 44     // window restore. |  | 
| 45     bool is_minimize_or_restore = |  | 
| 46         previous.height() == 0 || current.height() == 0; |  | 
| 47     if (!is_minimize_or_restore) { |  | 
| 48       if (is_horizontal_) |  | 
| 49         divider_offset_ += current.width() - previous.width(); |  | 
| 50       else |  | 
| 51         divider_offset_ += current.height() - previous.height(); |  | 
| 52 |  | 
| 53       if (divider_offset_ < 0) |  | 
| 54         divider_offset_ = kDividerSize; |  | 
| 55     } |  | 
| 56   } |  | 
| 57   View::DidChangeBounds(previous, current); | 44   View::DidChangeBounds(previous, current); | 
| 58 } | 45 } | 
| 59 | 46 | 
| 60 void SingleSplitView::Layout() { | 47 void SingleSplitView::Layout() { | 
| 61   if (GetChildViewCount() != 2) | 48   gfx::Rect leading_bounds; | 
| 62     return; | 49   gfx::Rect trailing_bounds; | 
|  | 50   CalculateChildrenBounds(bounds(), &leading_bounds, &trailing_bounds); | 
| 63 | 51 | 
| 64   View* leading = GetChildViewAt(0); | 52   if (GetChildViewCount() > 0) { | 
| 65   View* trailing = GetChildViewAt(1); | 53     if (GetChildViewAt(0)->IsVisible()) | 
| 66 | 54       GetChildViewAt(0)->SetBounds(leading_bounds); | 
| 67   if (!leading->IsVisible() && !trailing->IsVisible()) | 55     if (GetChildViewCount() > 1) { | 
| 68     return; | 56       if (GetChildViewAt(1)->IsVisible()) | 
| 69 | 57         GetChildViewAt(1)->SetBounds(trailing_bounds); | 
| 70   if (width() == 0 || height() == 0) { |  | 
| 71     // We are most likely minimized - do not touch divider offset. |  | 
| 72     return; |  | 
| 73   } else if (!trailing->IsVisible()) { |  | 
| 74     leading->SetBounds(0, 0, width(), height()); |  | 
| 75   } else if (!leading->IsVisible()) { |  | 
| 76     trailing->SetBounds(0, 0, width(), height()); |  | 
| 77   } else { |  | 
| 78     if (divider_offset_ < 0) |  | 
| 79       divider_offset_ = (GetPrimaryAxisSize() - kDividerSize) / 2; |  | 
| 80     else |  | 
| 81       divider_offset_ = std::min(divider_offset_, |  | 
| 82                                  GetPrimaryAxisSize() - kDividerSize); |  | 
| 83 |  | 
| 84     if (is_horizontal_) { |  | 
| 85       leading->SetBounds(0, 0, divider_offset_, height()); |  | 
| 86       trailing->SetBounds(divider_offset_ + kDividerSize, 0, |  | 
| 87                           width() - divider_offset_ - kDividerSize, height()); |  | 
| 88     } else { |  | 
| 89       leading->SetBounds(0, 0, width(), divider_offset_); |  | 
| 90       trailing->SetBounds(0, divider_offset_ + kDividerSize, |  | 
| 91                           width(), height() - divider_offset_ - kDividerSize); |  | 
| 92     } | 58     } | 
| 93   } | 59   } | 
| 94 | 60 | 
| 95   SchedulePaint(); | 61   SchedulePaint(); | 
| 96 | 62 | 
| 97   // Invoke super's implementation so that the children are layed out. | 63   // Invoke super's implementation so that the children are layed out. | 
| 98   View::Layout(); | 64   View::Layout(); | 
| 99 } | 65 } | 
| 100 | 66 | 
| 101 AccessibilityTypes::Role SingleSplitView::GetAccessibleRole() { | 67 AccessibilityTypes::Role SingleSplitView::GetAccessibleRole() { | 
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 133     return is_horizontal_ ? we_resize_cursor : ns_resize_cursor; | 99     return is_horizontal_ ? we_resize_cursor : ns_resize_cursor; | 
| 134 #elif defined(OS_LINUX) | 100 #elif defined(OS_LINUX) | 
| 135     return gfx::GetCursor(is_horizontal_ ? | 101     return gfx::GetCursor(is_horizontal_ ? | 
| 136                               GDK_SB_H_DOUBLE_ARROW : | 102                               GDK_SB_H_DOUBLE_ARROW : | 
| 137                               GDK_SB_V_DOUBLE_ARROW); | 103                               GDK_SB_V_DOUBLE_ARROW); | 
| 138 #endif | 104 #endif | 
| 139   } | 105   } | 
| 140   return NULL; | 106   return NULL; | 
| 141 } | 107 } | 
| 142 | 108 | 
|  | 109 void SingleSplitView::CalculateChildrenBounds( | 
|  | 110     const gfx::Rect& bounds, | 
|  | 111     gfx::Rect* leading_bounds, | 
|  | 112     gfx::Rect* trailing_bounds) const { | 
|  | 113   bool is_leading_visible = | 
|  | 114       GetChildViewCount() > 0 && GetChildViewAt(0)->IsVisible(); | 
|  | 115   bool is_trailing_visible = | 
|  | 116       GetChildViewCount() > 1 && GetChildViewAt(1)->IsVisible(); | 
|  | 117 | 
|  | 118   if (!is_leading_visible && !is_trailing_visible) { | 
|  | 119     *leading_bounds = gfx::Rect(); | 
|  | 120     *trailing_bounds = gfx::Rect(); | 
|  | 121     return; | 
|  | 122   } | 
|  | 123 | 
|  | 124   int divider_at; | 
|  | 125 | 
|  | 126   if (!is_trailing_visible) { | 
|  | 127     divider_at = GetPrimaryAxisSize(bounds.width(), bounds.height()); | 
|  | 128   } else if (!is_leading_visible) { | 
|  | 129     divider_at = 0; | 
|  | 130   } else { | 
|  | 131     divider_at = | 
|  | 132         CalculateDividerOffset(divider_offset_, this->bounds(), bounds); | 
|  | 133     divider_at = NormalizeDividerOffset(divider_at, bounds); | 
|  | 134   } | 
|  | 135 | 
|  | 136   int divider_size = | 
|  | 137       !is_leading_visible || !is_trailing_visible ? 0 : kDividerSize; | 
|  | 138 | 
|  | 139   if (is_horizontal_) { | 
|  | 140     *leading_bounds = gfx::Rect(0, 0, divider_at, bounds.height()); | 
|  | 141     *trailing_bounds = | 
|  | 142         gfx::Rect(divider_at + divider_size, 0, | 
|  | 143                   std::max(0, bounds.width() - divider_at - divider_size), | 
|  | 144                   bounds.height()); | 
|  | 145   } else { | 
|  | 146     *leading_bounds = gfx::Rect(0, 0, bounds.width(), divider_at); | 
|  | 147     *trailing_bounds = | 
|  | 148         gfx::Rect(0, divider_at + divider_size, bounds.width(), | 
|  | 149                   std::max(0, bounds.height() - divider_at - divider_size)); | 
|  | 150   } | 
|  | 151 } | 
|  | 152 | 
| 143 bool SingleSplitView::OnMousePressed(const MouseEvent& event) { | 153 bool SingleSplitView::OnMousePressed(const MouseEvent& event) { | 
| 144   if (!IsPointInDivider(event.location())) | 154   if (!IsPointInDivider(event.location())) | 
| 145     return false; | 155     return false; | 
| 146   drag_info_.initial_mouse_offset = GetPrimaryAxisSize(event.x(), event.y()); | 156   drag_info_.initial_mouse_offset = GetPrimaryAxisSize(event.x(), event.y()); | 
| 147   drag_info_.initial_divider_offset = divider_offset_; | 157   drag_info_.initial_divider_offset = | 
|  | 158       NormalizeDividerOffset(divider_offset_, bounds()); | 
| 148   return true; | 159   return true; | 
| 149 } | 160 } | 
| 150 | 161 | 
| 151 bool SingleSplitView::OnMouseDragged(const MouseEvent& event) { | 162 bool SingleSplitView::OnMouseDragged(const MouseEvent& event) { | 
| 152   if (GetChildViewCount() < 2) | 163   if (GetChildViewCount() < 2) | 
| 153     return false; | 164     return false; | 
| 154 | 165 | 
| 155   int delta_offset = GetPrimaryAxisSize(event.x(), event.y()) - | 166   int delta_offset = GetPrimaryAxisSize(event.x(), event.y()) - | 
| 156       drag_info_.initial_mouse_offset; | 167       drag_info_.initial_mouse_offset; | 
| 157   if (is_horizontal_ && base::i18n::IsRTL()) | 168   if (is_horizontal_ && base::i18n::IsRTL()) | 
| 158     delta_offset *= -1; | 169     delta_offset *= -1; | 
| 159   // Honor the minimum size when resizing. | 170   // Honor the minimum size when resizing. | 
| 160   gfx::Size min = GetChildViewAt(0)->GetMinimumSize(); | 171   gfx::Size min = GetChildViewAt(0)->GetMinimumSize(); | 
| 161   int new_size = std::max(GetPrimaryAxisSize(min.width(), min.height()), | 172   int new_size = std::max(GetPrimaryAxisSize(min.width(), min.height()), | 
| 162                           drag_info_.initial_divider_offset + delta_offset); | 173                           drag_info_.initial_divider_offset + delta_offset); | 
| 163 | 174 | 
| 164   // And don't let the view get bigger than our width. | 175   // And don't let the view get bigger than our width. | 
| 165   new_size = std::min(GetPrimaryAxisSize() - kDividerSize, new_size); | 176   new_size = std::min(GetPrimaryAxisSize() - kDividerSize, new_size); | 
| 166 | 177 | 
| 167   if (new_size != divider_offset_) { | 178   if (new_size != divider_offset_) { | 
| 168     set_divider_offset(new_size); | 179     set_divider_offset(new_size); | 
| 169     Layout(); | 180     if (!observer_ || observer_->SplitHandleMoved(this)) | 
|  | 181       Layout(); | 
| 170   } | 182   } | 
| 171   return true; | 183   return true; | 
| 172 } | 184 } | 
| 173 | 185 | 
| 174 void SingleSplitView::OnMouseReleased(const MouseEvent& event, bool canceled) { | 186 void SingleSplitView::OnMouseReleased(const MouseEvent& event, bool canceled) { | 
| 175   if (GetChildViewCount() < 2) | 187   if (GetChildViewCount() < 2) | 
| 176     return; | 188     return; | 
| 177 | 189 | 
| 178   if (canceled && drag_info_.initial_divider_offset != divider_offset_) { | 190   if (canceled && drag_info_.initial_divider_offset != divider_offset_) { | 
| 179     set_divider_offset(drag_info_.initial_divider_offset); | 191     set_divider_offset(drag_info_.initial_divider_offset); | 
| 180     Layout(); | 192     if (!observer_ || observer_->SplitHandleMoved(this)) | 
|  | 193       Layout(); | 
| 181   } | 194   } | 
| 182 } | 195 } | 
| 183 | 196 | 
| 184 bool SingleSplitView::IsPointInDivider(const gfx::Point& p) { | 197 bool SingleSplitView::IsPointInDivider(const gfx::Point& p) { | 
| 185   if (GetChildViewCount() < 2) | 198   if (GetChildViewCount() < 2) | 
| 186     return false; | 199     return false; | 
| 187 | 200 | 
| 188   if (!GetChildViewAt(0)->IsVisible() || !GetChildViewAt(1)->IsVisible()) | 201   if (!GetChildViewAt(0)->IsVisible() || !GetChildViewAt(1)->IsVisible()) | 
| 189     return false; | 202     return false; | 
| 190 | 203 | 
| 191   int divider_relative_offset; | 204   int divider_relative_offset; | 
| 192   if (is_horizontal_) { | 205   if (is_horizontal_) { | 
| 193     divider_relative_offset = | 206     divider_relative_offset = | 
| 194         p.x() - GetChildViewAt(base::i18n::IsRTL() ? 1 : 0)->width(); | 207         p.x() - GetChildViewAt(base::i18n::IsRTL() ? 1 : 0)->width(); | 
| 195   } else { | 208   } else { | 
| 196     divider_relative_offset = p.y() - GetChildViewAt(0)->height(); | 209     divider_relative_offset = p.y() - GetChildViewAt(0)->height(); | 
| 197   } | 210   } | 
| 198   return (divider_relative_offset >= 0 && | 211   return (divider_relative_offset >= 0 && | 
| 199       divider_relative_offset < kDividerSize); | 212       divider_relative_offset < kDividerSize); | 
| 200 } | 213 } | 
| 201 | 214 | 
|  | 215 int SingleSplitView::CalculateDividerOffset( | 
|  | 216     int divider_offset, | 
|  | 217     const gfx::Rect& previous_bounds, | 
|  | 218     const gfx::Rect& new_bounds) const { | 
|  | 219   if (resize_leading_on_bounds_change_ && divider_offset != -1) { | 
|  | 220     // We do not update divider_offset on minimize (to zero) and on restore | 
|  | 221     // (to largest value). As a result we get back to the original value upon | 
|  | 222     // window restore. | 
|  | 223     bool is_minimize_or_restore = | 
|  | 224         previous_bounds.height() == 0 || new_bounds.height() == 0; | 
|  | 225     if (!is_minimize_or_restore) { | 
|  | 226       if (is_horizontal_) | 
|  | 227         divider_offset += new_bounds.width() - previous_bounds.width(); | 
|  | 228       else | 
|  | 229         divider_offset += new_bounds.height() - previous_bounds.height(); | 
|  | 230 | 
|  | 231       if (divider_offset < 0) | 
|  | 232         divider_offset = kDividerSize; | 
|  | 233     } | 
|  | 234   } | 
|  | 235   return divider_offset; | 
|  | 236 } | 
|  | 237 | 
|  | 238 int SingleSplitView::NormalizeDividerOffset(int divider_offset, | 
|  | 239                                             const gfx::Rect& bounds) const { | 
|  | 240   int primary_axis_size = GetPrimaryAxisSize(bounds.width(), bounds.height()); | 
|  | 241   if (divider_offset < 0) | 
|  | 242     return (primary_axis_size - kDividerSize) / 2; | 
|  | 243   return std::min(divider_offset, | 
|  | 244                   std::max(primary_axis_size - kDividerSize, 0)); | 
|  | 245 } | 
|  | 246 | 
| 202 }  // namespace views | 247 }  // namespace views | 
| OLD | NEW | 
|---|