tray_display.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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 "ash/system/chromeos/tray_display.h" 6 7#include "ash/display/display_controller.h" 8#include "ash/display/display_manager.h" 9#include "ash/screen_ash.h" 10#include "ash/shell.h" 11#include "ash/system/tray/fixed_sized_image_view.h" 12#include "ash/system/tray/system_tray.h" 13#include "ash/system/tray/system_tray_delegate.h" 14#include "ash/system/tray/tray_constants.h" 15#include "ash/system/tray/tray_views.h" 16#include "base/chromeos/chromeos_version.h" 17#include "base/utf_string_conversions.h" 18#include "grit/ash_resources.h" 19#include "grit/ash_strings.h" 20#include "ui/aura/env.h" 21#include "ui/base/l10n/l10n_util.h" 22#include "ui/base/resource/resource_bundle.h" 23#include "ui/gfx/image/image.h" 24#include "ui/views/controls/image_view.h" 25#include "ui/views/controls/label.h" 26#include "ui/views/layout/box_layout.h" 27 28#if defined(USE_X11) 29#include "chromeos/display/output_configurator.h" 30#include "ui/base/x/x11_util.h" 31#endif 32 33namespace ash { 34namespace internal { 35 36class DisplayView : public ash::internal::ActionableView { 37 public: 38 explicit DisplayView(user::LoginStatus login_status) 39 : login_status_(login_status) { 40 SetLayoutManager(new 41 views::BoxLayout(views::BoxLayout::kHorizontal, 42 ash::kTrayPopupPaddingHorizontal, 0, 43 ash::kTrayPopupPaddingBetweenItems)); 44 45 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); 46 image_ = 47 new ash::internal::FixedSizedImageView(0, ash::kTrayPopupItemHeight); 48 image_->SetImage( 49 bundle.GetImageNamed(IDR_AURA_UBER_TRAY_DISPLAY).ToImageSkia()); 50 AddChildView(image_); 51 label_ = new views::Label(); 52 label_->SetMultiLine(true); 53 label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 54 AddChildView(label_); 55 Update(); 56 } 57 58 virtual ~DisplayView() {} 59 60 void Update() { 61 chromeos::OutputState state = 62 base::chromeos::IsRunningOnChromeOS() ? 63 Shell::GetInstance()->output_configurator()->output_state() : 64 InferOutputState(); 65 switch (state) { 66 case chromeos::STATE_INVALID: 67 case chromeos::STATE_HEADLESS: 68 case chromeos::STATE_SINGLE: 69 SetVisible(false); 70 return; 71 case chromeos::STATE_DUAL_MIRROR: { 72 label_->SetText(l10n_util::GetStringFUTF16( 73 IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, GetExternalDisplayName())); 74 SetVisible(true); 75 return; 76 } 77 case chromeos::STATE_DUAL_EXTENDED: 78 case chromeos::STATE_DUAL_UNKNOWN: { 79 label_->SetText(l10n_util::GetStringFUTF16( 80 IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED, GetExternalDisplayName())); 81 SetVisible(true); 82 return; 83 } 84 default: 85 NOTREACHED(); 86 } 87 } 88 89 chromeos::OutputState InferOutputState() const { 90 return Shell::GetScreen()->GetNumDisplays() == 1 ? 91 chromeos::STATE_SINGLE : chromeos::STATE_DUAL_EXTENDED; 92 } 93 94 private: 95 // Returns the name of the currently connected external display. 96 string16 GetExternalDisplayName() const { 97 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); 98 int64 external_id = display_manager->mirrored_display_id(); 99 100 if (external_id == gfx::Display::kInvalidDisplayID) { 101 int64 internal_display_id = gfx::Display::InternalDisplayId(); 102 int64 first_display_id = display_manager->first_display_id(); 103 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) { 104 int64 id = display_manager->GetDisplayAt(i)->id(); 105 if (id != internal_display_id && id != first_display_id) { 106 external_id = id; 107 break; 108 } 109 } 110 } 111 if (external_id != gfx::Display::kInvalidDisplayID) 112 return UTF8ToUTF16(display_manager->GetDisplayNameForId(external_id)); 113 return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_UNKNOWN_DISPLAY_NAME); 114 } 115 116 // Overridden from ActionableView. 117 virtual bool PerformAction(const ui::Event& event) OVERRIDE { 118 if (login_status_ == ash::user::LOGGED_IN_USER || 119 login_status_ == ash::user::LOGGED_IN_OWNER || 120 login_status_ == ash::user::LOGGED_IN_GUEST) { 121 ash::Shell::GetInstance()->system_tray_delegate()->ShowDisplaySettings(); 122 } 123 124 return true; 125 } 126 127 virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE { 128 int label_max_width = bounds().width() - kTrayPopupPaddingHorizontal * 2 - 129 kTrayPopupPaddingBetweenItems - image_->GetPreferredSize().width(); 130 label_->SizeToFit(label_max_width); 131 PreferredSizeChanged(); 132 } 133 134 user::LoginStatus login_status_; 135 views::ImageView* image_; 136 views::Label* label_; 137 138 DISALLOW_COPY_AND_ASSIGN(DisplayView); 139}; 140 141TrayDisplay::TrayDisplay(SystemTray* system_tray) 142 : SystemTrayItem(system_tray), 143 default_(NULL) { 144 Shell::GetScreen()->AddObserver(this); 145 Shell::GetInstance()->output_configurator()->AddObserver(this); 146} 147 148TrayDisplay::~TrayDisplay() { 149 Shell::GetScreen()->RemoveObserver(this); 150 Shell::GetInstance()->output_configurator()->RemoveObserver(this); 151} 152 153views::View* TrayDisplay::CreateDefaultView(user::LoginStatus status) { 154 default_ = new DisplayView(status); 155 return default_; 156} 157 158void TrayDisplay::DestroyDefaultView() { 159 default_ = NULL; 160} 161 162void TrayDisplay::OnDisplayBoundsChanged(const gfx::Display& display) { 163 if (default_) 164 default_->Update(); 165} 166 167void TrayDisplay::OnDisplayAdded(const gfx::Display& new_display) { 168 if (default_) 169 default_->Update(); 170} 171 172void TrayDisplay::OnDisplayRemoved(const gfx::Display& old_display) { 173 if (default_) 174 default_->Update(); 175} 176 177#if defined(OS_CHROMEOS) 178void TrayDisplay::OnDisplayModeChanged() { 179 if (default_) 180 default_->Update(); 181} 182#endif 183 184} // namespace internal 185} // namespace ash 186