| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/chromeos/status/status_area_view.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 | |
| 9 #include "base/bind.h" | |
| 10 #include "base/command_line.h" | |
| 11 #include "base/message_loop.h" | |
| 12 #include "chrome/browser/chromeos/view_ids.h" | |
| 13 #include "ui/gfx/canvas.h" | |
| 14 #include "ui/views/border.h" | |
| 15 | |
| 16 #if defined(USE_ASH) | |
| 17 #include "ash/focus_cycler.h" | |
| 18 #include "ash/shell.h" | |
| 19 #endif | |
| 20 | |
| 21 // Number of pixels to separate each icon. | |
| 22 const int kSeparation = 0; | |
| 23 | |
| 24 StatusAreaView::StatusAreaView() | |
| 25 : need_return_focus_(false), | |
| 26 skip_next_focus_return_(true) { | |
| 27 set_id(VIEW_ID_STATUS_AREA); | |
| 28 } | |
| 29 | |
| 30 StatusAreaView::~StatusAreaView() { | |
| 31 } | |
| 32 | |
| 33 void StatusAreaView::AddButton(StatusAreaButton* button, ButtonBorder border) { | |
| 34 buttons_.push_back(button); | |
| 35 if (border == HAS_BORDER) | |
| 36 button->set_border(views::Border::CreateEmptyBorder(0, 1, 0, 0)); | |
| 37 AddChildView(button); | |
| 38 UpdateButtonVisibility(); | |
| 39 } | |
| 40 | |
| 41 void StatusAreaView::RemoveButton(StatusAreaButton* button) { | |
| 42 std::list<StatusAreaButton*>::iterator iter = | |
| 43 std::find(buttons_.begin(), buttons_.end(), button); | |
| 44 if (iter != buttons_.end()) { | |
| 45 RemoveChildView(*iter); | |
| 46 buttons_.erase(iter); | |
| 47 } | |
| 48 UpdateButtonVisibility(); | |
| 49 } | |
| 50 | |
| 51 // views::View* overrides. | |
| 52 | |
| 53 gfx::Size StatusAreaView::GetPreferredSize() { | |
| 54 int result_w = 0; | |
| 55 int result_h = 0; | |
| 56 | |
| 57 for (int i = 0; i < child_count(); i++) { | |
| 58 views::View* cur = child_at(i); | |
| 59 gfx::Size cur_size = cur->GetPreferredSize(); | |
| 60 if (cur->visible() && !cur_size.IsEmpty()) { | |
| 61 if (result_w == 0) | |
| 62 result_w = kSeparation; | |
| 63 | |
| 64 // Add each width. | |
| 65 result_w += cur_size.width() + kSeparation; | |
| 66 // Use max height. | |
| 67 result_h = std::max(result_h, cur_size.height()); | |
| 68 } | |
| 69 } | |
| 70 return gfx::Size(result_w, result_h); | |
| 71 } | |
| 72 | |
| 73 void StatusAreaView::Layout() { | |
| 74 int cur_x = kSeparation; | |
| 75 for (int i = 0; i < child_count(); i++) { | |
| 76 views::View* cur = child_at(i); | |
| 77 gfx::Size cur_size = cur->GetPreferredSize(); | |
| 78 if (cur->visible() && !cur_size.IsEmpty()) { | |
| 79 int cur_y = (height() - cur_size.height()) / 2; | |
| 80 | |
| 81 // Handle odd number of pixels. | |
| 82 cur_y += (height() - cur_size.height()) % 2; | |
| 83 | |
| 84 // Put next in row horizontally, and center vertically. | |
| 85 cur->SetBounds(cur_x, cur_y, cur_size.width(), cur_size.height()); | |
| 86 cur_x += cur_size.width() + kSeparation; | |
| 87 } | |
| 88 } | |
| 89 } | |
| 90 | |
| 91 void StatusAreaView::PreferredSizeChanged() { | |
| 92 if (GetWidget()) | |
| 93 GetWidget()->SetSize(GetPreferredSize()); | |
| 94 views::AccessiblePaneView::PreferredSizeChanged(); | |
| 95 } | |
| 96 | |
| 97 void StatusAreaView::ChildPreferredSizeChanged(View* child) { | |
| 98 // When something like the clock menu button's size changes, we need to | |
| 99 // relayout. Also mark that this view's size has changed. This will let | |
| 100 // BrowserView know to relayout, which will reset the bounds of this view. | |
| 101 Layout(); | |
| 102 PreferredSizeChanged(); | |
| 103 } | |
| 104 | |
| 105 bool StatusAreaView::CanActivate() const { | |
| 106 #if defined(USE_ASH) | |
| 107 // We don't want mouse clicks to activate us, but we need to allow | |
| 108 // activation when the user is using the keyboard, such as by the FocusCycler | |
| 109 // or on the Login screen. | |
| 110 ash::internal::FocusCycler* focus_cycler = | |
| 111 ash::Shell::GetInstance()->focus_cycler(); | |
| 112 return focus_cycler->widget_activating() == GetWidget() || | |
| 113 need_return_focus_; | |
| 114 #else | |
| 115 return false; | |
| 116 #endif | |
| 117 } | |
| 118 | |
| 119 void StatusAreaView::DeleteDelegate() { | |
| 120 #if defined(USE_ASH) | |
| 121 // If this is used as the content-view of the widget, then do nothing, since | |
| 122 // deleting the widget will end up deleting this. But if this is used only as | |
| 123 // the widget-delegate, then delete this now. | |
| 124 if (!GetWidget()) { | |
| 125 delete this; | |
| 126 return; | |
| 127 } | |
| 128 #endif | |
| 129 WidgetDelegate::DeleteDelegate(); | |
| 130 } | |
| 131 | |
| 132 views::Widget* StatusAreaView::GetWidget() { | |
| 133 return View::GetWidget(); | |
| 134 } | |
| 135 | |
| 136 const views::Widget* StatusAreaView::GetWidget() const { | |
| 137 return View::GetWidget(); | |
| 138 } | |
| 139 | |
| 140 void StatusAreaView::MakeButtonsActive(bool active) { | |
| 141 for (std::list<StatusAreaButton*>::iterator iter = buttons_.begin(); | |
| 142 iter != buttons_.end(); ++iter) { | |
| 143 (*iter)->SetMenuActive(active); | |
| 144 } | |
| 145 } | |
| 146 | |
| 147 void StatusAreaView::UpdateButtonVisibility() { | |
| 148 Layout(); | |
| 149 PreferredSizeChanged(); | |
| 150 } | |
| 151 | |
| 152 void StatusAreaView::UpdateButtonTextStyle() { | |
| 153 for (std::list<StatusAreaButton*>::const_iterator it = buttons_.begin(); | |
| 154 it != buttons_.end(); ++it) { | |
| 155 StatusAreaButton* button = *it; | |
| 156 button->UpdateTextStyle(); | |
| 157 } | |
| 158 } | |
| 159 | |
| 160 void StatusAreaView::TakeFocus( | |
| 161 bool reverse, | |
| 162 const ReturnFocusCallback& return_focus_cb) { | |
| 163 SetPaneFocus(reverse ? GetLastFocusableChild() : GetFirstFocusableChild()); | |
| 164 need_return_focus_ = true; | |
| 165 return_focus_cb_ = return_focus_cb; | |
| 166 GetWidget()->AddObserver(this); | |
| 167 } | |
| 168 | |
| 169 void StatusAreaView::ReturnFocus(bool reverse) { | |
| 170 ClearFocus(); | |
| 171 return_focus_cb_.Run(reverse); | |
| 172 } | |
| 173 | |
| 174 void StatusAreaView::ClearFocus() { | |
| 175 GetWidget()->RemoveObserver(this); | |
| 176 RemovePaneFocus(); | |
| 177 focus_manager_->ClearFocus(); | |
| 178 need_return_focus_ = false; | |
| 179 } | |
| 180 | |
| 181 void StatusAreaView::OnDidChangeFocus(views::View* focused_before, | |
| 182 views::View* focused_now) { | |
| 183 views::AccessiblePaneView::OnDidChangeFocus(focused_before, focused_now); | |
| 184 if (need_return_focus_ && !skip_next_focus_return_) { | |
| 185 const views::View* first = GetFirstFocusableChild(); | |
| 186 const views::View* last = GetLastFocusableChild(); | |
| 187 const bool first_to_last = (focused_before == first && focused_now == last); | |
| 188 const bool last_to_first = (focused_now == first && focused_before == last); | |
| 189 | |
| 190 if (first_to_last || last_to_first) | |
| 191 ReturnFocus(first_to_last); | |
| 192 } | |
| 193 skip_next_focus_return_ = false; | |
| 194 } | |
| 195 | |
| 196 void StatusAreaView::OnWidgetActivationChanged(views::Widget* widget, | |
| 197 bool active) { | |
| 198 if (!active) | |
| 199 ClearFocus(); | |
| 200 } | |
| 201 | |
| 202 bool StatusAreaView::AcceleratorPressed(const ui::Accelerator& accelerator) { | |
| 203 if (need_return_focus_ && accelerator.key_code() == ui::VKEY_ESCAPE) { | |
| 204 // Override Escape handling to return focus back. | |
| 205 ReturnFocus(false); | |
| 206 return true; | |
| 207 } else if (accelerator.key_code() == ui::VKEY_HOME || | |
| 208 accelerator.key_code() == ui::VKEY_END) { | |
| 209 // Do not return focus if it wraps right after pressing Home/End. | |
| 210 skip_next_focus_return_ = true; | |
| 211 } | |
| 212 return AccessiblePaneView::AcceleratorPressed(accelerator); | |
| 213 } | |
| OLD | NEW |