Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(290)

Side by Side Diff: ui/views/controls/scroll_view.cc

Issue 2555213004: Improving the appearance of overlay scrollbars (Closed)
Patch Set: attempt to fix mac Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/views/controls/scroll_view.h ('k') | ui/views/controls/scroll_view_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "ui/views/controls/scroll_view.h" 5 #include "ui/views/controls/scroll_view.h"
6 6
7 #include "base/feature_list.h" 7 #include "base/feature_list.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/macros.h" 9 #include "base/macros.h"
10 #include "ui/events/event.h" 10 #include "ui/events/event.h"
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 gfx::ScrollOffset offset = CurrentOffset(); 236 gfx::ScrollOffset offset = CurrentOffset();
237 return gfx::Rect(offset.x(), offset.y(), contents_viewport_->width(), 237 return gfx::Rect(offset.x(), offset.y(), contents_viewport_->width(),
238 contents_viewport_->height()); 238 contents_viewport_->height());
239 } 239 }
240 240
241 void ScrollView::ClipHeightTo(int min_height, int max_height) { 241 void ScrollView::ClipHeightTo(int min_height, int max_height) {
242 min_height_ = min_height; 242 min_height_ = min_height;
243 max_height_ = max_height; 243 max_height_ = max_height;
244 } 244 }
245 245
246 int ScrollView::GetScrollBarWidth() const { 246 int ScrollView::GetScrollBarLayoutWidth() const {
247 return vert_sb_ ? vert_sb_->GetLayoutSize() : 0; 247 return vert_sb_ && !vert_sb_->OverlapsContent() ? vert_sb_->GetThickness()
248 : 0;
248 } 249 }
249 250
250 int ScrollView::GetScrollBarHeight() const { 251 int ScrollView::GetScrollBarLayoutHeight() const {
251 return horiz_sb_ ? horiz_sb_->GetLayoutSize() : 0; 252 return horiz_sb_ && !horiz_sb_->OverlapsContent() ? horiz_sb_->GetThickness()
253 : 0;
252 } 254 }
253 255
254 void ScrollView::SetHorizontalScrollBar(ScrollBar* horiz_sb) { 256 void ScrollView::SetHorizontalScrollBar(ScrollBar* horiz_sb) {
255 DCHECK(horiz_sb); 257 DCHECK(horiz_sb);
256 horiz_sb->SetVisible(horiz_sb_->visible()); 258 horiz_sb->SetVisible(horiz_sb_->visible());
257 delete horiz_sb_; 259 delete horiz_sb_;
258 horiz_sb->set_controller(this); 260 horiz_sb->set_controller(this);
259 horiz_sb_ = horiz_sb; 261 horiz_sb_ = horiz_sb;
260 } 262 }
261 263
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 if (!is_bounded()) 297 if (!is_bounded())
296 return View::GetHeightForWidth(width); 298 return View::GetHeightForWidth(width);
297 299
298 gfx::Insets insets = GetInsets(); 300 gfx::Insets insets = GetInsets();
299 width = std::max(0, width - insets.width()); 301 width = std::max(0, width - insets.width());
300 int height = contents_->GetHeightForWidth(width) + insets.height(); 302 int height = contents_->GetHeightForWidth(width) + insets.height();
301 return std::min(std::max(height, min_height_), max_height_); 303 return std::min(std::max(height, min_height_), max_height_);
302 } 304 }
303 305
304 void ScrollView::Layout() { 306 void ScrollView::Layout() {
307 #if defined(OS_MACOSX)
308 // On Mac, scrollbars may update their style one at a time, so they may
309 // temporarily be of different types. Refuse to lay out at this point.
310 if (horiz_sb_->OverlapsContent() != vert_sb_->OverlapsContent())
Evan Stade 2016/12/13 00:51:52 Sadrul, do you mind this change that I had to make
311 return;
312 #endif
313 DCHECK_EQ(horiz_sb_->OverlapsContent(), vert_sb_->OverlapsContent());
314
305 if (focus_ring_) 315 if (focus_ring_)
306 focus_ring_->Layout(); 316 focus_ring_->Layout();
307 317
308 gfx::Rect available_rect = GetContentsBounds(); 318 gfx::Rect available_rect = GetContentsBounds();
309 if (is_bounded()) { 319 if (is_bounded()) {
310 int content_width = available_rect.width(); 320 int content_width = available_rect.width();
311 int content_height = contents_->GetHeightForWidth(content_width); 321 int content_height = contents_->GetHeightForWidth(content_width);
312 if (content_height > height()) { 322 if (content_height > height()) {
313 content_width = std::max(content_width - GetScrollBarWidth(), 0); 323 content_width = std::max(content_width - GetScrollBarLayoutWidth(), 0);
314 content_height = contents_->GetHeightForWidth(content_width); 324 content_height = contents_->GetHeightForWidth(content_width);
315 } 325 }
316 contents_->SetSize(gfx::Size(content_width, content_height)); 326 contents_->SetSize(gfx::Size(content_width, content_height));
317 } 327 }
318 328
319 // Most views will want to auto-fit the available space. Most of them want to 329 // Most views will want to auto-fit the available space. Most of them want to
320 // use all available width (without overflowing) and only overflow in 330 // use all available width (without overflowing) and only overflow in
321 // height. Examples are HistoryView, MostVisitedView, DownloadTabView, etc. 331 // height. Examples are HistoryView, MostVisitedView, DownloadTabView, etc.
322 // Other views want to fit in both ways. An example is PrintView. To make both 332 // Other views want to fit in both ways. An example is PrintView. To make both
323 // happy, assume a vertical scrollbar but no horizontal scrollbar. To override 333 // happy, assume a vertical scrollbar but no horizontal scrollbar. To override
(...skipping 11 matching lines...) Expand all
335 const int header_height = 345 const int header_height =
336 std::min(viewport_bounds.height(), 346 std::min(viewport_bounds.height(),
337 header_ ? header_->GetPreferredSize().height() : 0); 347 header_ ? header_->GetPreferredSize().height() : 0);
338 viewport_bounds.set_height( 348 viewport_bounds.set_height(
339 std::max(0, viewport_bounds.height() - header_height)); 349 std::max(0, viewport_bounds.height() - header_height));
340 viewport_bounds.set_y(viewport_bounds.y() + header_height); 350 viewport_bounds.set_y(viewport_bounds.y() + header_height);
341 // viewport_size is the total client space available. 351 // viewport_size is the total client space available.
342 gfx::Size viewport_size = viewport_bounds.size(); 352 gfx::Size viewport_size = viewport_bounds.size();
343 // Assumes a vertical scrollbar since most of the current views are designed 353 // Assumes a vertical scrollbar since most of the current views are designed
344 // for this. 354 // for this.
345 int horiz_sb_height = GetScrollBarHeight(); 355 const int horiz_sb_layout_height = GetScrollBarLayoutHeight();
346 int vert_sb_width = GetScrollBarWidth(); 356 const int vert_sb_layout_width = GetScrollBarLayoutWidth();
347 viewport_bounds.set_width(viewport_bounds.width() - vert_sb_width); 357 viewport_bounds.set_width(viewport_bounds.width() - vert_sb_layout_width);
348 // Update the bounds right now so the inner views can fit in it. 358 // Update the bounds right now so the inner views can fit in it.
349 contents_viewport_->SetBoundsRect(viewport_bounds); 359 contents_viewport_->SetBoundsRect(viewport_bounds);
350 360
351 // Give |contents_| a chance to update its bounds if it depends on the 361 // Give |contents_| a chance to update its bounds if it depends on the
352 // viewport. 362 // viewport.
353 if (contents_) 363 if (contents_)
354 contents_->Layout(); 364 contents_->Layout();
355 365
356 bool should_layout_contents = false; 366 bool should_layout_contents = false;
357 bool horiz_sb_required = false; 367 bool horiz_sb_required = false;
358 bool vert_sb_required = false; 368 bool vert_sb_required = false;
359 if (contents_) { 369 if (contents_) {
360 gfx::Size content_size = contents_->size(); 370 gfx::Size content_size = contents_->size();
361 ComputeScrollBarsVisibility(viewport_size, 371 ComputeScrollBarsVisibility(viewport_size,
362 content_size, 372 content_size,
363 &horiz_sb_required, 373 &horiz_sb_required,
364 &vert_sb_required); 374 &vert_sb_required);
365 } 375 }
366 bool corner_view_required = horiz_sb_required && vert_sb_required; 376 // Overlay scrollbars don't need a corner view.
377 bool corner_view_required =
378 horiz_sb_required && vert_sb_required && !vert_sb_->OverlapsContent();
367 // Take action. 379 // Take action.
368 SetControlVisibility(horiz_sb_, horiz_sb_required); 380 SetControlVisibility(horiz_sb_, horiz_sb_required);
369 SetControlVisibility(vert_sb_, vert_sb_required); 381 SetControlVisibility(vert_sb_, vert_sb_required);
370 SetControlVisibility(corner_view_, corner_view_required); 382 SetControlVisibility(corner_view_, corner_view_required);
371 383
372 // Non-default. 384 // Non-default.
373 if (horiz_sb_required) { 385 if (horiz_sb_required) {
374 viewport_bounds.set_height( 386 viewport_bounds.set_height(
375 std::max(0, viewport_bounds.height() - horiz_sb_height)); 387 std::max(0, viewport_bounds.height() - horiz_sb_layout_height));
376 should_layout_contents = true; 388 should_layout_contents = true;
377 } 389 }
378 // Default. 390 // Default.
379 if (!vert_sb_required) { 391 if (!vert_sb_required) {
380 viewport_bounds.set_width(viewport_bounds.width() + vert_sb_width); 392 viewport_bounds.set_width(viewport_bounds.width() + vert_sb_layout_width);
381 should_layout_contents = true; 393 should_layout_contents = true;
382 } 394 }
383 395
384 int height_offset = horiz_sb_required ? 396 if (horiz_sb_required) {
385 horiz_sb_->GetContentOverlapSize() : 0; 397 gfx::Rect horiz_sb_bounds(contents_x, viewport_bounds.bottom(),
386 int width_offset = vert_sb_required ? 398 viewport_bounds.right() - contents_x,
387 vert_sb_->GetContentOverlapSize() : 0; 399 horiz_sb_layout_height);
400 if (horiz_sb_->OverlapsContent()) {
401 horiz_sb_bounds.Inset(
402 gfx::Insets(-horiz_sb_->GetThickness(), 0, 0,
403 vert_sb_required ? vert_sb_->GetThickness() : 0));
404 }
388 405
389 if (horiz_sb_required) { 406 horiz_sb_->SetBoundsRect(horiz_sb_bounds);
390 horiz_sb_->SetBounds(contents_x,
391 viewport_bounds.bottom() - height_offset,
392 viewport_bounds.right() - contents_x - width_offset,
393 horiz_sb_height + height_offset);
394 } 407 }
395 if (vert_sb_required) { 408 if (vert_sb_required) {
396 int width_offset = vert_sb_->GetContentOverlapSize(); 409 gfx::Rect vert_sb_bounds(viewport_bounds.right(), contents_y,
397 vert_sb_->SetBounds(viewport_bounds.right() - width_offset, 410 vert_sb_layout_width,
398 contents_y, 411 viewport_bounds.bottom() - contents_y);
399 vert_sb_width + width_offset, 412 if (vert_sb_->OverlapsContent()) {
400 viewport_bounds.bottom() - contents_y - height_offset); 413 // In the overlay scrollbar case, the scrollbar only covers the viewport
414 // (and not the header).
415 vert_sb_bounds.Inset(
416 gfx::Insets(header_height, -vert_sb_->GetThickness(),
417 horiz_sb_required ? horiz_sb_->GetThickness() : 0, 0));
418 }
419
420 vert_sb_->SetBoundsRect(vert_sb_bounds);
401 } 421 }
402 if (corner_view_required) { 422 if (corner_view_required) {
403 // Show the resize corner. 423 // Show the resize corner.
404 corner_view_->SetBounds(vert_sb_->bounds().x(), horiz_sb_->bounds().y(), 424 corner_view_->SetBounds(vert_sb_->bounds().x(), horiz_sb_->bounds().y(),
405 vert_sb_width, horiz_sb_height); 425 vert_sb_layout_width, horiz_sb_layout_height);
406 } 426 }
407 427
408 // Update to the real client size with the visible scrollbars. 428 // Update to the real client size with the visible scrollbars.
409 contents_viewport_->SetBoundsRect(viewport_bounds); 429 contents_viewport_->SetBoundsRect(viewport_bounds);
410 if (should_layout_contents && contents_) 430 if (should_layout_contents && contents_)
411 contents_->Layout(); 431 contents_->Layout();
412 432
413 // Even when |contents_| needs to scroll, it can still be narrower or wider 433 // Even when |contents_| needs to scroll, it can still be narrower or wider
414 // the viewport. So ensure the scrolling layer can fill the viewport, so that 434 // the viewport. So ensure the scrolling layer can fill the viewport, so that
415 // events will correctly hit it, and overscroll looks correct. 435 // events will correctly hit it, and overscroll looks correct.
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
612 *vert_is_shown = content_size.height() > vp_size.height(); 632 *vert_is_shown = content_size.height() > vp_size.height();
613 return; 633 return;
614 } 634 }
615 635
616 // Try to fit both ways first, then try vertical bar only, then horizontal 636 // Try to fit both ways first, then try vertical bar only, then horizontal
617 // bar only, then defaults to both shown. 637 // bar only, then defaults to both shown.
618 if (content_size.width() <= vp_size.width() && 638 if (content_size.width() <= vp_size.width() &&
619 content_size.height() <= vp_size.height()) { 639 content_size.height() <= vp_size.height()) {
620 *horiz_is_shown = false; 640 *horiz_is_shown = false;
621 *vert_is_shown = false; 641 *vert_is_shown = false;
622 } else if (content_size.width() <= vp_size.width() - GetScrollBarWidth()) { 642 } else if (content_size.width() <=
643 vp_size.width() - GetScrollBarLayoutWidth()) {
623 *horiz_is_shown = false; 644 *horiz_is_shown = false;
624 *vert_is_shown = true; 645 *vert_is_shown = true;
625 } else if (content_size.height() <= vp_size.height() - GetScrollBarHeight()) { 646 } else if (content_size.height() <=
647 vp_size.height() - GetScrollBarLayoutHeight()) {
626 *horiz_is_shown = true; 648 *horiz_is_shown = true;
627 *vert_is_shown = false; 649 *vert_is_shown = false;
628 } else { 650 } else {
629 *horiz_is_shown = true; 651 *horiz_is_shown = true;
630 *vert_is_shown = true; 652 *vert_is_shown = true;
631 } 653 }
632 } 654 }
633 655
634 // Make sure that a single scrollbar is created and visible as needed 656 // Make sure that a single scrollbar is created and visible as needed
635 void ScrollView::SetControlVisibility(View* control, bool should_show) { 657 void ScrollView::SetControlVisibility(View* control, bool should_show) {
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
781 803
782 VariableRowHeightScrollHelper::RowInfo 804 VariableRowHeightScrollHelper::RowInfo
783 FixedRowHeightScrollHelper::GetRowInfo(int y) { 805 FixedRowHeightScrollHelper::GetRowInfo(int y) {
784 if (y < top_margin_) 806 if (y < top_margin_)
785 return RowInfo(0, top_margin_); 807 return RowInfo(0, top_margin_);
786 return RowInfo((y - top_margin_) / row_height_ * row_height_ + top_margin_, 808 return RowInfo((y - top_margin_) / row_height_ * row_height_ + top_margin_,
787 row_height_); 809 row_height_);
788 } 810 }
789 811
790 } // namespace views 812 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/controls/scroll_view.h ('k') | ui/views/controls/scroll_view_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698