1// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/views/reload_button.h" 6 7#include "base/utf_string_conversions.h" 8#include "chrome/app/chrome_command_ids.h" 9#include "chrome/browser/ui/browser.h" 10#include "chrome/browser/ui/views/event_utils.h" 11#include "chrome/browser/ui/views/location_bar/location_bar_view.h" 12#include "grit/generated_resources.h" 13#include "ui/base/l10n/l10n_util.h" 14#include "views/metrics.h" 15 16//////////////////////////////////////////////////////////////////////////////// 17// ReloadButton, public: 18 19ReloadButton::ReloadButton(LocationBarView* location_bar, Browser* browser) 20 : ALLOW_THIS_IN_INITIALIZER_LIST(ToggleImageButton(this)), 21 location_bar_(location_bar), 22 browser_(browser), 23 intended_mode_(MODE_RELOAD), 24 visible_mode_(MODE_RELOAD), 25 double_click_timer_delay_( 26 base::TimeDelta::FromMilliseconds(views::GetDoubleClickInterval())), 27 stop_to_reload_timer_delay_(base::TimeDelta::FromMilliseconds(1350)), 28 testing_mouse_hovered_(false), 29 testing_reload_count_(0) { 30} 31 32ReloadButton::~ReloadButton() { 33} 34 35void ReloadButton::ChangeMode(Mode mode, bool force) { 36 intended_mode_ = mode; 37 38 // If the change is forced, or the user isn't hovering the icon, or it's safe 39 // to change it to the other image type, make the change immediately; 40 // otherwise we'll let it happen later. 41 if (force || (!IsMouseHovered() && !testing_mouse_hovered_) || 42 ((mode == MODE_STOP) ? 43 !double_click_timer_.IsRunning() : (visible_mode_ != MODE_STOP))) { 44 double_click_timer_.Stop(); 45 stop_to_reload_timer_.Stop(); 46 SetToggled(mode == MODE_STOP); 47 visible_mode_ = mode; 48 SetEnabled(true); 49 50 // We want to disable the button if we're preventing a change from stop to 51 // reload due to hovering, but not if we're preventing a change from reload to 52 // stop due to the double-click timer running. (There is no disabled reload 53 // state.) 54 } else if (visible_mode_ != MODE_RELOAD) { 55 SetEnabled(false); 56 57 // Go ahead and change to reload after a bit, which allows repeated reloads 58 // without moving the mouse. 59 if (!stop_to_reload_timer_.IsRunning()) { 60 stop_to_reload_timer_.Start(stop_to_reload_timer_delay_, this, 61 &ReloadButton::OnStopToReloadTimer); 62 } 63 } 64} 65 66//////////////////////////////////////////////////////////////////////////////// 67// ReloadButton, views::ButtonListener implementation: 68 69void ReloadButton::ButtonPressed(views::Button* /* button */, 70 const views::Event& event) { 71 if (visible_mode_ == MODE_STOP) { 72 if (browser_) 73 browser_->Stop(); 74 // The user has clicked, so we can feel free to update the button, 75 // even if the mouse is still hovering. 76 ChangeMode(MODE_RELOAD, true); 77 } else if (!double_click_timer_.IsRunning()) { 78 // Shift-clicking or ctrl-clicking the reload button means we should ignore 79 // any cached content. 80 // TODO(avayvod): eliminate duplication of this logic in 81 // CompactLocationBarView. 82 int command; 83 int flags = mouse_event_flags(); 84 if (event.IsShiftDown() || event.IsControlDown()) { 85 command = IDC_RELOAD_IGNORING_CACHE; 86 // Mask off Shift and Control so they don't affect the disposition below. 87 flags &= ~(ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN); 88 } else { 89 command = IDC_RELOAD; 90 } 91 92 WindowOpenDisposition disposition = 93 event_utils::DispositionFromEventFlags(flags); 94 if ((disposition == CURRENT_TAB) && location_bar_) { 95 // Forcibly reset the location bar, since otherwise it won't discard any 96 // ongoing user edits, since it doesn't realize this is a user-initiated 97 // action. 98 location_bar_->Revert(); 99 } 100 101 // Start a timer - while this timer is running, the reload button cannot be 102 // changed to a stop button. We do not set |intended_mode_| to MODE_STOP 103 // here as the browser will do that when it actually starts loading (which 104 // may happen synchronously, thus the need to do this before telling the 105 // browser to execute the reload command). 106 double_click_timer_.Start(double_click_timer_delay_, this, 107 &ReloadButton::OnDoubleClickTimer); 108 109 if (browser_) 110 browser_->ExecuteCommandWithDisposition(command, disposition); 111 ++testing_reload_count_; 112 } 113} 114 115//////////////////////////////////////////////////////////////////////////////// 116// ReloadButton, View overrides: 117 118void ReloadButton::OnMouseExited(const views::MouseEvent& event) { 119 ChangeMode(intended_mode_, true); 120 if (state() != BS_DISABLED) 121 SetState(BS_NORMAL); 122} 123 124bool ReloadButton::GetTooltipText(const gfx::Point& p, std::wstring* tooltip) { 125 int text_id = visible_mode_ == MODE_RELOAD ? IDS_TOOLTIP_RELOAD 126 : IDS_TOOLTIP_STOP; 127 tooltip->assign(UTF16ToWide(l10n_util::GetStringUTF16(text_id))); 128 return true; 129} 130 131//////////////////////////////////////////////////////////////////////////////// 132// ReloadButton, private: 133 134void ReloadButton::OnDoubleClickTimer() { 135 ChangeMode(intended_mode_, false); 136} 137 138void ReloadButton::OnStopToReloadTimer() { 139 ChangeMode(intended_mode_, true); 140} 141