Chromium Code Reviews| 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 #import "chrome/browser/cocoa/tabpose_window.h" | 5 #import "chrome/browser/cocoa/tabpose_window.h" |
| 6 | 6 |
| 7 #import <QuartzCore/QuartzCore.h> | 7 #import <QuartzCore/QuartzCore.h> |
| 8 | 8 |
| 9 #include "app/resource_bundle.h" | 9 #include "app/resource_bundle.h" |
| 10 #include "base/mac_util.h" | 10 #include "base/mac_util.h" |
| 11 #include "base/scoped_callback_factory.h" | 11 #include "base/scoped_callback_factory.h" |
| 12 #include "base/sys_string_conversions.h" | 12 #include "base/sys_string_conversions.h" |
| 13 #include "chrome/app/chrome_dll_resource.h" | |
| 13 #include "chrome/browser/browser_process.h" | 14 #include "chrome/browser/browser_process.h" |
| 14 #import "chrome/browser/cocoa/bookmark_bar_constants.h" | 15 #import "chrome/browser/cocoa/bookmark_bar_constants.h" |
| 15 #import "chrome/browser/cocoa/browser_window_controller.h" | 16 #import "chrome/browser/cocoa/browser_window_controller.h" |
| 16 #import "chrome/browser/cocoa/tab_strip_controller.h" | 17 #import "chrome/browser/cocoa/tab_strip_controller.h" |
| 17 #import "chrome/browser/cocoa/tab_strip_model_observer_bridge.h" | 18 #import "chrome/browser/cocoa/tab_strip_model_observer_bridge.h" |
| 18 #import "chrome/browser/debugger/devtools_window.h" | 19 #import "chrome/browser/debugger/devtools_window.h" |
| 19 #include "chrome/browser/prefs/pref_service.h" | 20 #include "chrome/browser/prefs/pref_service.h" |
| 20 #include "chrome/browser/renderer_host/backing_store_mac.h" | 21 #include "chrome/browser/renderer_host/backing_store_mac.h" |
| 21 #include "chrome/browser/renderer_host/render_view_host.h" | 22 #include "chrome/browser/renderer_host/render_view_host.h" |
| 22 #include "chrome/browser/renderer_host/render_widget_host_view_mac.h" | 23 #include "chrome/browser/renderer_host/render_widget_host_view_mac.h" |
| (...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 455 // Computes coordinates for |tiles_|. | 456 // Computes coordinates for |tiles_|. |
| 456 void Layout(NSRect containing_rect); | 457 void Layout(NSRect containing_rect); |
| 457 | 458 |
| 458 int selected_index() const { return selected_index_; } | 459 int selected_index() const { return selected_index_; } |
| 459 void set_selected_index(int index); | 460 void set_selected_index(int index); |
| 460 | 461 |
| 461 const Tile& selected_tile() const { return *tiles_[selected_index()]; } | 462 const Tile& selected_tile() const { return *tiles_[selected_index()]; } |
| 462 Tile& tile_at(int index) { return *tiles_[index]; } | 463 Tile& tile_at(int index) { return *tiles_[index]; } |
| 463 const Tile& tile_at(int index) const { return *tiles_[index]; } | 464 const Tile& tile_at(int index) const { return *tiles_[index]; } |
| 464 | 465 |
| 466 // These return which index needs to be selected when the user presses | |
| 467 // up, down, left, or right respectively. | |
| 468 int up_index() const; | |
| 469 int down_index() const; | |
| 470 int left_index() const; | |
| 471 int right_index() const; | |
| 472 | |
| 473 // These return which index needs to be selected on tab / shift-tab. | |
| 474 int next_index() const; | |
| 475 int previous_index() const; | |
| 476 | |
| 465 // Inserts a new Tile object containing |contents| at |index|. Does no | 477 // Inserts a new Tile object containing |contents| at |index|. Does no |
| 466 // relayout. | 478 // relayout. |
| 467 void InsertTileAt(int index, TabContents* contents); | 479 void InsertTileAt(int index, TabContents* contents); |
| 468 | 480 |
| 469 // Removes the Tile object at |index|. Does no relayout. | 481 // Removes the Tile object at |index|. Does no relayout. |
| 470 void RemoveTileAt(int index); | 482 void RemoveTileAt(int index); |
| 471 | 483 |
| 472 // Moves the Tile object at |from_index| to |to_index|. Since this doesn't | 484 // Moves the Tile object at |from_index| to |to_index|. Since this doesn't |
| 473 // change the number of tiles, relayout can be done just by swapping the | 485 // change the number of tiles, relayout can be done just by swapping the |
| 474 // tile rectangles in the index interval [from_index, to_index], so this does | 486 // tile rectangles in the index interval [from_index, to_index], so this does |
| 475 // layout. | 487 // layout. |
| 476 void MoveTileFromTo(int from_index, int to_index); | 488 void MoveTileFromTo(int from_index, int to_index); |
| 477 | 489 |
| 478 private: | 490 private: |
| 491 int count_x() const { | |
| 492 return ceilf(tiles_.size() / static_cast<float>(count_y_)); | |
| 493 } | |
| 494 int count_y() const { | |
| 495 return count_y_; | |
| 496 } | |
| 497 int last_row_count_x() const { | |
| 498 return tiles_.size() - count_x() * (count_y() - 1); | |
| 499 } | |
| 500 int tiles_in_row(int row) const { | |
| 501 return row != count_y() - 1 ? count_x() : last_row_count_x(); | |
| 502 } | |
| 503 void index_to_tile_xy(int index, int* tile_x, int* tile_y) const { | |
| 504 *tile_x = index % count_x(); | |
| 505 *tile_y = index / count_x(); | |
| 506 } | |
| 507 int tile_xy_to_index(int tile_x, int tile_y) const { | |
| 508 return tile_y * count_x() + tile_x; | |
| 509 } | |
| 510 | |
| 479 ScopedVector<Tile> tiles_; | 511 ScopedVector<Tile> tiles_; |
| 480 int selected_index_; | 512 int selected_index_; |
| 513 int count_y_; | |
| 481 | 514 |
| 482 DISALLOW_COPY_AND_ASSIGN(TileSet); | 515 DISALLOW_COPY_AND_ASSIGN(TileSet); |
| 483 }; | 516 }; |
| 484 | 517 |
| 485 void TileSet::Build(TabStripModel* source_model) { | 518 void TileSet::Build(TabStripModel* source_model) { |
| 486 selected_index_ = source_model->selected_index(); | 519 selected_index_ = source_model->selected_index(); |
| 487 tiles_.resize(source_model->count()); | 520 tiles_.resize(source_model->count()); |
| 488 for (size_t i = 0; i < tiles_.size(); ++i) { | 521 for (size_t i = 0; i < tiles_.size(); ++i) { |
| 489 tiles_[i] = new Tile; | 522 tiles_[i] = new Tile; |
| 490 tiles_[i]->contents_ = source_model->GetTabContentsAt(i); | 523 tiles_[i]->contents_ = source_model->GetTabContentsAt(i); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 535 // |count_x * count_y >= tile_count|, and such that wasted space is minimized. | 568 // |count_x * count_y >= tile_count|, and such that wasted space is minimized. |
| 536 // See the comments in | 569 // See the comments in |
| 537 // |FitNRectsWithAspectIntoBoundingSizeWithConstantPadding()| for a more | 570 // |FitNRectsWithAspectIntoBoundingSizeWithConstantPadding()| for a more |
| 538 // detailed discussion. | 571 // detailed discussion. |
| 539 // TODO(thakis): It might be good enough to choose |count_x| and |count_y| | 572 // TODO(thakis): It might be good enough to choose |count_x| and |count_y| |
| 540 // such that count_x / count_y is roughly equal to |aspect|? | 573 // such that count_x / count_y is roughly equal to |aspect|? |
| 541 double fny = FitNRectsWithAspectIntoBoundingSizeWithConstantPadding( | 574 double fny = FitNRectsWithAspectIntoBoundingSizeWithConstantPadding( |
| 542 tile_count, aspect, | 575 tile_count, aspect, |
| 543 container_width, container_height - kFooterExtraHeight, | 576 container_width, container_height - kFooterExtraHeight, |
| 544 kSmallPaddingX, kSmallPaddingY + kFooterExtraHeight); | 577 kSmallPaddingX, kSmallPaddingY + kFooterExtraHeight); |
| 545 int count_y(roundf(fny)); | 578 count_y_ = roundf(fny); |
| 546 int count_x(ceilf(tile_count / float(count_y))); | |
| 547 int last_row_count_x = tile_count - count_x * (count_y - 1); | |
| 548 | 579 |
| 549 // Now that |count_x| and |count_y| are known, it's straightforward to compute | 580 // Now that |count_x()| and |count_y_| are known, it's straightforward to |
| 550 // thumbnail width/height. See comment in | 581 // compute thumbnail width/height. See comment in |
| 551 // |FitNRectsWithAspectIntoBoundingSizeWithConstantPadding| for the derivation | 582 // |FitNRectsWithAspectIntoBoundingSizeWithConstantPadding| for the derivation |
| 552 // of these two formulas. | 583 // of these two formulas. |
| 553 int small_width = | 584 int small_width = |
| 554 floor((container_width + kSmallPaddingX) / float(count_x) - | 585 floor((container_width + kSmallPaddingX) / static_cast<float>(count_x()) - |
| 555 kSmallPaddingX); | 586 kSmallPaddingX); |
| 556 int small_height = | 587 int small_height = |
| 557 floor((container_height + kSmallPaddingY) / float(count_y) - | 588 floor((container_height + kSmallPaddingY) / static_cast<float>(count_y_) - |
| 558 (kSmallPaddingY + kFooterExtraHeight)); | 589 (kSmallPaddingY + kFooterExtraHeight)); |
| 559 | 590 |
| 560 // |small_width / small_height| has only roughly an aspect ratio of |aspect|. | 591 // |small_width / small_height| has only roughly an aspect ratio of |aspect|. |
| 561 // Shrink the thumbnail rect to make the aspect ratio fit exactly, and add | 592 // Shrink the thumbnail rect to make the aspect ratio fit exactly, and add |
| 562 // the extra space won by shrinking to the outer padding. | 593 // the extra space won by shrinking to the outer padding. |
| 563 int smallExtraPaddingLeft = 0; | 594 int smallExtraPaddingLeft = 0; |
| 564 int smallExtraPaddingTop = 0; | 595 int smallExtraPaddingTop = 0; |
| 565 if (aspect > small_width/float(small_height)) { | 596 if (aspect > small_width/static_cast<float>(small_height)) { |
| 566 small_height = small_width / aspect; | 597 small_height = small_width / aspect; |
| 567 CGFloat all_tiles_height = | 598 CGFloat all_tiles_height = |
| 568 (small_height + kSmallPaddingY + kFooterExtraHeight) * count_y - | 599 (small_height + kSmallPaddingY + kFooterExtraHeight) * count_y() - |
| 569 (kSmallPaddingY + kFooterExtraHeight); | 600 (kSmallPaddingY + kFooterExtraHeight); |
| 570 smallExtraPaddingTop = (container_height - all_tiles_height)/2; | 601 smallExtraPaddingTop = (container_height - all_tiles_height)/2; |
| 571 } else { | 602 } else { |
| 572 small_width = small_height * aspect; | 603 small_width = small_height * aspect; |
| 573 CGFloat all_tiles_width = | 604 CGFloat all_tiles_width = |
| 574 (small_width + kSmallPaddingX) * count_x - kSmallPaddingX; | 605 (small_width + kSmallPaddingX) * count_x() - kSmallPaddingX; |
| 575 smallExtraPaddingLeft = (container_width - all_tiles_width)/2; | 606 smallExtraPaddingLeft = (container_width - all_tiles_width)/2; |
| 576 } | 607 } |
| 577 | 608 |
| 578 // Compute inter-tile padding in the zoomed-out view. | 609 // Compute inter-tile padding in the zoomed-out view. |
| 579 CGFloat scale_small_to_big = NSWidth(containing_rect) / float(small_width); | 610 CGFloat scale_small_to_big = |
| 611 NSWidth(containing_rect) / static_cast<float>(small_width); | |
| 580 CGFloat big_padding_x = kSmallPaddingX * scale_small_to_big; | 612 CGFloat big_padding_x = kSmallPaddingX * scale_small_to_big; |
| 581 CGFloat big_padding_y = | 613 CGFloat big_padding_y = |
| 582 (kSmallPaddingY + kFooterExtraHeight) * scale_small_to_big; | 614 (kSmallPaddingY + kFooterExtraHeight) * scale_small_to_big; |
| 583 | 615 |
| 584 // Now all dimensions are known. Lay out all tiles on a regular grid: | 616 // Now all dimensions are known. Lay out all tiles on a regular grid: |
| 585 // X X X X | 617 // X X X X |
| 586 // X X X X | 618 // X X X X |
| 587 // X X | 619 // X X |
| 588 for (int row = 0, i = 0; i < tile_count; ++row) { | 620 for (int row = 0, i = 0; i < tile_count; ++row) { |
| 589 for (int col = 0; col < count_x && i < tile_count; ++col, ++i) { | 621 for (int col = 0; col < count_x() && i < tile_count; ++col, ++i) { |
| 590 // Compute the smalled, zoomed-out thumbnail rect. | 622 // Compute the smalled, zoomed-out thumbnail rect. |
| 591 tiles_[i]->thumb_rect_.size = NSMakeSize(small_width, small_height); | 623 tiles_[i]->thumb_rect_.size = NSMakeSize(small_width, small_height); |
| 592 | 624 |
| 593 int small_x = col * (small_width + kSmallPaddingX) + | 625 int small_x = col * (small_width + kSmallPaddingX) + |
| 594 kSmallPaddingLeft + smallExtraPaddingLeft; | 626 kSmallPaddingLeft + smallExtraPaddingLeft; |
| 595 int small_y = row * (small_height + kSmallPaddingY + kFooterExtraHeight) + | 627 int small_y = row * (small_height + kSmallPaddingY + kFooterExtraHeight) + |
| 596 kSmallPaddingTop + smallExtraPaddingTop; | 628 kSmallPaddingTop + smallExtraPaddingTop; |
| 597 | 629 |
| 598 tiles_[i]->thumb_rect_.origin = NSMakePoint( | 630 tiles_[i]->thumb_rect_.origin = NSMakePoint( |
| 599 small_x, NSHeight(containing_rect) - small_y - small_height); | 631 small_x, NSHeight(containing_rect) - small_y - small_height); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 622 int big_x = col * (NSWidth(containing_rect) + big_padding_x); | 654 int big_x = col * (NSWidth(containing_rect) + big_padding_x); |
| 623 int big_y = row * (NSHeight(containing_rect) + big_padding_y); | 655 int big_y = row * (NSHeight(containing_rect) + big_padding_y); |
| 624 tiles_[i]->start_thumb_rect_.origin = NSMakePoint(big_x, -big_y); | 656 tiles_[i]->start_thumb_rect_.origin = NSMakePoint(big_x, -big_y); |
| 625 } | 657 } |
| 626 } | 658 } |
| 627 | 659 |
| 628 // Go through last row and center it: | 660 // Go through last row and center it: |
| 629 // X X X X | 661 // X X X X |
| 630 // X X X X | 662 // X X X X |
| 631 // X X | 663 // X X |
| 632 int last_row_empty_tiles_x = count_x - last_row_count_x; | 664 int last_row_empty_tiles_x = count_x() - last_row_count_x(); |
| 633 CGFloat small_last_row_shift_x = | 665 CGFloat small_last_row_shift_x = |
| 634 last_row_empty_tiles_x * (small_width + kSmallPaddingX) / 2; | 666 last_row_empty_tiles_x * (small_width + kSmallPaddingX) / 2; |
| 635 CGFloat big_last_row_shift_x = | 667 CGFloat big_last_row_shift_x = |
| 636 last_row_empty_tiles_x * (NSWidth(containing_rect) + big_padding_x) / 2; | 668 last_row_empty_tiles_x * (NSWidth(containing_rect) + big_padding_x) / 2; |
| 637 for (int i = tile_count - last_row_count_x; i < tile_count; ++i) { | 669 for (int i = tile_count - last_row_count_x(); i < tile_count; ++i) { |
| 638 tiles_[i]->thumb_rect_.origin.x += small_last_row_shift_x; | 670 tiles_[i]->thumb_rect_.origin.x += small_last_row_shift_x; |
| 639 tiles_[i]->start_thumb_rect_.origin.x += big_last_row_shift_x; | 671 tiles_[i]->start_thumb_rect_.origin.x += big_last_row_shift_x; |
| 640 tiles_[i]->favicon_rect_.origin.x += small_last_row_shift_x; | 672 tiles_[i]->favicon_rect_.origin.x += small_last_row_shift_x; |
| 641 tiles_[i]->title_rect_.origin.x += small_last_row_shift_x; | 673 tiles_[i]->title_rect_.origin.x += small_last_row_shift_x; |
| 642 } | 674 } |
| 643 } | 675 } |
| 644 | 676 |
| 645 void TileSet::set_selected_index(int index) { | 677 void TileSet::set_selected_index(int index) { |
| 646 CHECK_GE(index, 0); | 678 CHECK_GE(index, 0); |
| 647 CHECK_LT(index, static_cast<int>(tiles_.size())); | 679 CHECK_LT(index, static_cast<int>(tiles_.size())); |
| 648 selected_index_ = index; | 680 selected_index_ = index; |
| 649 } | 681 } |
| 650 | 682 |
| 683 // Given a |value| in [0, from_scale), map it into [0, to_scale) such that: | |
| 684 // * [0, from_scale) ends up in the middle of [0, to_scale) if the latter is | |
| 685 // a bigger range | |
| 686 // * The middle of [0, from_scale) is mapped to [0, to_scale), and the parts | |
| 687 // of the former that don't fit are mapped to 0 and to_scale - respectively | |
| 688 // if the former is a bigger range. | |
| 689 static int rescale(int value, int from_scale, int to_scale) { | |
| 690 int left = (to_scale - from_scale) / 2; | |
| 691 int result = value + left; | |
| 692 if (result < 0) | |
| 693 return 0; | |
| 694 if (result >= to_scale) | |
| 695 return to_scale - 1; | |
| 696 return result; | |
| 697 } | |
| 698 | |
| 699 int TileSet::up_index() const { | |
| 700 int tile_x, tile_y; | |
| 701 index_to_tile_xy(selected_index(), &tile_x, &tile_y); | |
| 702 tile_y -= 1; | |
| 703 if (tile_y == count_y() - 2) { | |
| 704 // Transition from last row to second-to-last row. | |
| 705 tile_x = rescale(tile_x, last_row_count_x(), count_x()); | |
| 706 } else if (tile_y < 0) { | |
| 707 // Transition from first row to last row. | |
| 708 tile_x = rescale(tile_x, count_x(), last_row_count_x()); | |
| 709 tile_y = count_y() - 1; | |
| 710 } | |
| 711 return tile_xy_to_index(tile_x, tile_y); | |
| 712 } | |
| 713 | |
| 714 int TileSet::down_index() const { | |
| 715 int tile_x, tile_y; | |
| 716 index_to_tile_xy(selected_index(), &tile_x, &tile_y); | |
| 717 tile_y += 1; | |
| 718 if (tile_y == count_y() - 1) { | |
| 719 // Transition from second-to-last row to last row. | |
| 720 tile_x = rescale(tile_x, count_x(), last_row_count_x()); | |
| 721 } else if (tile_y >= count_y()) { | |
| 722 // Transition from last row to first row. | |
| 723 tile_x = rescale(tile_x, last_row_count_x(), count_x()); | |
| 724 tile_y = 0; | |
| 725 } | |
| 726 return tile_xy_to_index(tile_x, tile_y); | |
| 727 } | |
| 728 | |
| 729 int TileSet::left_index() const { | |
| 730 int tile_x, tile_y; | |
| 731 index_to_tile_xy(selected_index(), &tile_x, &tile_y); | |
| 732 tile_x -= 1; | |
| 733 if (tile_x < 0) | |
| 734 tile_x = tiles_in_row(tile_y) - 1; | |
| 735 return tile_xy_to_index(tile_x, tile_y); | |
| 736 } | |
| 737 | |
| 738 int TileSet::right_index() const { | |
| 739 int tile_x, tile_y; | |
| 740 index_to_tile_xy(selected_index(), &tile_x, &tile_y); | |
| 741 tile_x += 1; | |
| 742 if (tile_x >= tiles_in_row(tile_y)) | |
| 743 tile_x = 0; | |
| 744 return tile_xy_to_index(tile_x, tile_y); | |
| 745 } | |
| 746 | |
| 747 int TileSet::next_index() const { | |
| 748 int new_index = selected_index() + 1; | |
| 749 if (new_index >= static_cast<int>(tiles_.size())) | |
|
viettrungluu
2010/09/16 20:07:21
I think this would be a fine place to use ?:.
Nico
2010/09/16 20:08:54
but then i need to write "+1" twice!
| |
| 750 new_index = 0; | |
| 751 return new_index; | |
| 752 } | |
| 753 | |
| 754 int TileSet::previous_index() const { | |
| 755 int new_index = selected_index() - 1; | |
| 756 if (new_index < 0) | |
|
viettrungluu
2010/09/16 20:07:21
Ditto.
| |
| 757 new_index = tiles_.size() - 1; | |
| 758 return new_index; | |
| 759 } | |
| 760 | |
| 651 void TileSet::InsertTileAt(int index, TabContents* contents) { | 761 void TileSet::InsertTileAt(int index, TabContents* contents) { |
| 652 tiles_.insert(tiles_.begin() + index, new Tile); | 762 tiles_.insert(tiles_.begin() + index, new Tile); |
| 653 tiles_[index]->contents_ = contents; | 763 tiles_[index]->contents_ = contents; |
| 654 } | 764 } |
| 655 | 765 |
| 656 void TileSet::RemoveTileAt(int index) { | 766 void TileSet::RemoveTileAt(int index) { |
| 657 tiles_.erase(tiles_.begin() + index); | 767 tiles_.erase(tiles_.begin() + index); |
| 658 } | 768 } |
| 659 | 769 |
| 660 // Moves the Tile object at |from_index| to |to_index|. Also updates rectangles | 770 // Moves the Tile object at |from_index| to |to_index|. Also updates rectangles |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 928 // there's a one frame flash of grey at the beginning of the animation | 1038 // there's a one frame flash of grey at the beginning of the animation |
| 929 // (|bgLayer_| showing through with none of its children visible yet). | 1039 // (|bgLayer_| showing through with none of its children visible yet). |
| 930 [[self contentView] setLayer:rootLayer_]; | 1040 [[self contentView] setLayer:rootLayer_]; |
| 931 [[self contentView] setWantsLayer:YES]; | 1041 [[self contentView] setWantsLayer:YES]; |
| 932 } | 1042 } |
| 933 | 1043 |
| 934 - (BOOL)canBecomeKeyWindow { | 1044 - (BOOL)canBecomeKeyWindow { |
| 935 return YES; | 1045 return YES; |
| 936 } | 1046 } |
| 937 | 1047 |
| 1048 // Handle key events that should be executed repeatedly while the key is down. | |
| 938 - (void)keyDown:(NSEvent*)event { | 1049 - (void)keyDown:(NSEvent*)event { |
| 939 // Overridden to prevent beeps. | 1050 if (state_ == tabpose::kFadingOut) |
| 1051 return; | |
| 1052 NSString* characters = [event characters]; | |
| 1053 if ([characters length] < 1) | |
| 1054 return; | |
| 1055 | |
| 1056 unichar character = [characters characterAtIndex:0]; | |
| 1057 int newIndex = -1; | |
| 1058 switch (character) { | |
| 1059 case NSUpArrowFunctionKey: | |
| 1060 newIndex = tileSet_->up_index(); | |
| 1061 break; | |
| 1062 case NSDownArrowFunctionKey: | |
| 1063 newIndex = tileSet_->down_index(); | |
| 1064 break; | |
| 1065 case NSLeftArrowFunctionKey: | |
| 1066 newIndex = tileSet_->left_index(); | |
| 1067 break; | |
| 1068 case NSRightArrowFunctionKey: | |
| 1069 newIndex = tileSet_->right_index(); | |
| 1070 break; | |
| 1071 case NSTabCharacter: | |
| 1072 newIndex = tileSet_->next_index(); | |
| 1073 break; | |
| 1074 case NSBackTabCharacter: | |
| 1075 newIndex = tileSet_->previous_index(); | |
| 1076 break; | |
| 1077 } | |
| 1078 if (newIndex != -1) | |
| 1079 [self selectTileAtIndexWithoutAnimation:newIndex]; | |
| 940 } | 1080 } |
| 941 | 1081 |
| 1082 // Handle keyboard events that should be executed once when the key is released. | |
| 942 - (void)keyUp:(NSEvent*)event { | 1083 - (void)keyUp:(NSEvent*)event { |
| 943 if (state_ == tabpose::kFadingOut) | 1084 if (state_ == tabpose::kFadingOut) |
| 944 return; | 1085 return; |
| 945 | |
| 946 NSString* characters = [event characters]; | 1086 NSString* characters = [event characters]; |
| 947 if ([characters length] < 1) | 1087 if ([characters length] < 1) |
| 948 return; | 1088 return; |
| 949 | 1089 |
| 950 unichar character = [characters characterAtIndex:0]; | 1090 unichar character = [characters characterAtIndex:0]; |
| 951 switch (character) { | 1091 switch (character) { |
| 952 case NSEnterCharacter: | 1092 case NSEnterCharacter: |
| 953 case NSNewlineCharacter: | 1093 case NSNewlineCharacter: |
| 954 case NSCarriageReturnCharacter: | 1094 case NSCarriageReturnCharacter: |
| 955 case ' ': | 1095 case ' ': |
| 956 [self fadeAway:([event modifierFlags] & NSShiftKeyMask) != 0]; | 1096 [self fadeAway:([event modifierFlags] & NSShiftKeyMask) != 0]; |
| 957 break; | 1097 break; |
| 958 case '\e': // Escape | 1098 case '\e': // Escape |
| 959 tileSet_->set_selected_index(tabStripModel_->selected_index()); | 1099 tileSet_->set_selected_index(tabStripModel_->selected_index()); |
| 960 [self fadeAway:([event modifierFlags] & NSShiftKeyMask) != 0]; | 1100 [self fadeAway:([event modifierFlags] & NSShiftKeyMask) != 0]; |
| 961 break; | 1101 break; |
| 962 // TODO(thakis): Support moving the selection via arrow keys. | |
| 963 } | 1102 } |
| 964 } | 1103 } |
| 965 | 1104 |
| 1105 // Handle keyboard events that contain cmd or ctrl. | |
| 1106 - (BOOL)performKeyEquivalent:(NSEvent*)event { | |
| 1107 if (state_ == tabpose::kFadingOut) | |
| 1108 return NO; | |
| 1109 NSString* characters = [event characters]; | |
| 1110 if ([characters length] < 1) | |
| 1111 return NO; | |
| 1112 unichar character = [characters characterAtIndex:0]; | |
| 1113 if ([event modifierFlags] & NSCommandKeyMask) { | |
| 1114 if (character >= '1' && character <= '9') { | |
| 1115 int index = | |
| 1116 character == '9' ? tabStripModel_->count() - 1 : character - '1'; | |
| 1117 if (index < tabStripModel_->count()) { | |
| 1118 tileSet_->set_selected_index(index); | |
| 1119 [self fadeAway:([event modifierFlags] & NSShiftKeyMask) != 0]; | |
| 1120 return YES; | |
| 1121 } | |
| 1122 } | |
| 1123 } | |
| 1124 return NO; | |
| 1125 } | |
| 1126 | |
| 966 - (void)mouseMoved:(NSEvent*)event { | 1127 - (void)mouseMoved:(NSEvent*)event { |
| 967 int newIndex = -1; | 1128 int newIndex = -1; |
| 968 CGPoint p = NSPointToCGPoint([event locationInWindow]); | 1129 CGPoint p = NSPointToCGPoint([event locationInWindow]); |
| 969 for (NSUInteger i = 0; i < [allThumbnailLayers_ count]; ++i) { | 1130 for (NSUInteger i = 0; i < [allThumbnailLayers_ count]; ++i) { |
| 970 CALayer* layer = [allThumbnailLayers_ objectAtIndex:i]; | 1131 CALayer* layer = [allThumbnailLayers_ objectAtIndex:i]; |
| 971 CGPoint lp = [layer convertPoint:p fromLayer:rootLayer_]; | 1132 CGPoint lp = [layer convertPoint:p fromLayer:rootLayer_]; |
| 972 if ([static_cast<CALayer*>([layer presentationLayer]) containsPoint:lp]) | 1133 if ([static_cast<CALayer*>([layer presentationLayer]) containsPoint:lp]) |
| 973 newIndex = i; | 1134 newIndex = i; |
| 974 } | 1135 } |
| 975 if (newIndex >= 0) | 1136 if (newIndex >= 0) |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 990 [[self parentWindow] removeChildWindow:self]; | 1151 [[self parentWindow] removeChildWindow:self]; |
| 991 | 1152 |
| 992 // We're dealloc'd in an autorelease pool – by then the observer registry | 1153 // We're dealloc'd in an autorelease pool – by then the observer registry |
| 993 // might be dead, so explicitly reset the observer now. | 1154 // might be dead, so explicitly reset the observer now. |
| 994 tabStripModelObserverBridge_.reset(); | 1155 tabStripModelObserverBridge_.reset(); |
| 995 | 1156 |
| 996 [super close]; | 1157 [super close]; |
| 997 } | 1158 } |
| 998 | 1159 |
| 999 - (void)commandDispatch:(id)sender { | 1160 - (void)commandDispatch:(id)sender { |
| 1000 // Without this, -validateUserInterfaceItem: is not called. | 1161 if ([sender tag] == IDC_TABPOSE) |
| 1162 [self fadeAway:NO]; | |
| 1001 } | 1163 } |
| 1002 | 1164 |
| 1003 - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item { | 1165 - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item { |
| 1004 // Disable all browser-related menu items. | 1166 // Disable all browser-related menu items except the tab overview toggle. |
| 1005 return NO; | 1167 SEL action = [item action]; |
| 1168 NSInteger tag = [item tag]; | |
| 1169 return action == @selector(commandDispatch:) && tag == IDC_TABPOSE; | |
| 1006 } | 1170 } |
| 1007 | 1171 |
| 1008 - (void)fadeAway:(BOOL)slomo { | 1172 - (void)fadeAway:(BOOL)slomo { |
| 1009 if (state_ == tabpose::kFadingOut) | 1173 if (state_ == tabpose::kFadingOut) |
| 1010 return; | 1174 return; |
| 1011 | 1175 |
| 1012 state_ = tabpose::kFadingOut; | 1176 state_ = tabpose::kFadingOut; |
| 1013 [self setAcceptsMouseMovedEvents:NO]; | 1177 [self setAcceptsMouseMovedEvents:NO]; |
| 1014 | 1178 |
| 1015 // Select chosen tab. | 1179 // Select chosen tab. |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1253 tile.set_tab_contents(contents); | 1417 tile.set_tab_contents(contents); |
| 1254 ThumbnailLayer* thumbLayer = [allThumbnailLayers_ objectAtIndex:index]; | 1418 ThumbnailLayer* thumbLayer = [allThumbnailLayers_ objectAtIndex:index]; |
| 1255 [thumbLayer setTabContents:contents]; | 1419 [thumbLayer setTabContents:contents]; |
| 1256 } | 1420 } |
| 1257 | 1421 |
| 1258 - (void)tabStripModelDeleted { | 1422 - (void)tabStripModelDeleted { |
| 1259 [self close]; | 1423 [self close]; |
| 1260 } | 1424 } |
| 1261 | 1425 |
| 1262 @end | 1426 @end |
| OLD | NEW |