This source file includes following definitions.
- state
 
- SetKeyState
 
- PaintText
 
- OnPaint
 
- SetKeyState
 
- GetKeyState
 
- SetModifierVisible
 
- AddKeyLabel
 
- widget_size_
 
- Show
 
- SetModifierVisible
 
- SetModifierKeyState
 
- GetModifierKeyState
 
- CalculateOverlayBounds
 
- OnLayerAnimationEnded
 
- OnLayerAnimationAborted
 
- OnLayerAnimationScheduled
 
#include "ash/sticky_keys/sticky_keys_overlay.h"
#include "ash/shell.h"
#include "ash/shell_window_ids.h"
#include "ash/sticky_keys/sticky_keys_controller.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "grit/ash_strings.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/font_list.h"
#include "ui/views/border.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
namespace ash {
namespace {
const int kHorizontalOverlayOffset = 18;
const int kVerticalOverlayOffset = 18;
const ui::ResourceBundle::FontStyle kKeyLabelFontStyle =
    ui::ResourceBundle::LargeFont;
const int kSlideAnimationDurationMs = 100;
}
class StickyKeyOverlayLabel : public views::Label {
 public:
  explicit StickyKeyOverlayLabel(const std::string& key_name);
  virtual ~StickyKeyOverlayLabel();
  StickyKeyState state() const { return state_; }
  void SetKeyState(StickyKeyState state);
 private:
  
  virtual void PaintText(gfx::Canvas* canvas,
                         const base::string16& text,
                         const gfx::Rect& text_bounds,
                         int flags) OVERRIDE;
  StickyKeyState state_;
  DISALLOW_COPY_AND_ASSIGN(StickyKeyOverlayLabel);
};
StickyKeyOverlayLabel::StickyKeyOverlayLabel(const std::string& key_name)
    : state_(STICKY_KEY_STATE_DISABLED) {
  ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
  SetText(base::UTF8ToUTF16(key_name));
  SetHorizontalAlignment(gfx::ALIGN_LEFT);
  SetFontList(rb->GetFontList(kKeyLabelFontStyle));
  SetAutoColorReadabilityEnabled(false);
  SetFocusable(false);
  SetEnabledColor(SkColorSetARGB(0x80, 0xFF, 0xFF, 0xFF));
  SetDisabledColor(SkColorSetARGB(0x80, 0xFF, 0xFF, 0xFF));
}
StickyKeyOverlayLabel::~StickyKeyOverlayLabel() {
}
void StickyKeyOverlayLabel::SetKeyState(StickyKeyState state) {
  state_ = state;
  SkColor label_color;
  int style;
  switch (state) {
    case STICKY_KEY_STATE_ENABLED:
      style = gfx::Font::NORMAL;
      label_color = SkColorSetA(enabled_color(), 0xFF);
      break;
    case STICKY_KEY_STATE_LOCKED:
      style = gfx::Font::UNDERLINE;
      label_color = SkColorSetA(enabled_color(), 0xFF);
      break;
    default:
      style = gfx::Font::NORMAL;
      label_color = SkColorSetA(enabled_color(), 0x80);
  }
  SetEnabledColor(label_color);
  SetDisabledColor(label_color);
  SetFontList(font_list().DeriveWithStyle(style));
}
void StickyKeyOverlayLabel::PaintText(gfx::Canvas* canvas,
                                      const base::string16& text,
                                      const gfx::Rect& text_bounds,
                                      int flags) {
  views::Label::PaintText(canvas,
                          text,
                          text_bounds,
                          flags | gfx::Canvas::NO_SUBPIXEL_RENDERING);
}
class StickyKeysOverlayView : public views::WidgetDelegateView {
 public:
  StickyKeysOverlayView();
  virtual ~StickyKeysOverlayView();
  
  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
  void SetKeyState(ui::EventFlags modifier, StickyKeyState state);
  StickyKeyState GetKeyState(ui::EventFlags modifier);
  void SetModifierVisible(ui::EventFlags modifier, bool visible);
 private:
  void AddKeyLabel(ui::EventFlags modifier, const std::string& key_label);
  typedef std::map<ui::EventFlags, StickyKeyOverlayLabel*> ModifierLabelMap;
  ModifierLabelMap modifier_label_map_;
  DISALLOW_COPY_AND_ASSIGN(StickyKeysOverlayView);
};
StickyKeysOverlayView::StickyKeysOverlayView() {
  const gfx::Font& font =
      ui::ResourceBundle::GetSharedInstance().GetFont(kKeyLabelFontStyle);
  int font_size = font.GetFontSize();
  int font_padding = font.GetHeight() - font.GetBaseline();
  
  
  int horizontal_spacing = font_size / 2;
  int vertical_spacing = font_size / 2 - font_padding;
  int child_spacing = font_size - 2 * font_padding;
  SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical,
                                        horizontal_spacing,
                                        vertical_spacing,
                                        child_spacing));
  AddKeyLabel(ui::EF_CONTROL_DOWN,
              l10n_util::GetStringUTF8(IDS_ASH_CONTROL_KEY));
  AddKeyLabel(ui::EF_ALT_DOWN,
              l10n_util::GetStringUTF8(IDS_ASH_ALT_KEY));
  AddKeyLabel(ui::EF_SHIFT_DOWN,
              l10n_util::GetStringUTF8(IDS_ASH_SHIFT_KEY));
  AddKeyLabel(ui::EF_ALTGR_DOWN,
              l10n_util::GetStringUTF8(IDS_ASH_ALTGR_KEY));
}
StickyKeysOverlayView::~StickyKeysOverlayView() {}
void StickyKeysOverlayView::OnPaint(gfx::Canvas* canvas) {
  SkPaint paint;
  paint.setStyle(SkPaint::kFill_Style);
  paint.setColor(SkColorSetARGB(0xB3, 0x55, 0x55, 0x55));
  canvas->DrawRoundRect(GetLocalBounds(), 2, paint);
  views::WidgetDelegateView::OnPaint(canvas);
}
void StickyKeysOverlayView::SetKeyState(ui::EventFlags modifier,
                                        StickyKeyState state) {
  ModifierLabelMap::iterator it = modifier_label_map_.find(modifier);
  DCHECK(it != modifier_label_map_.end());
  if (it != modifier_label_map_.end()) {
    StickyKeyOverlayLabel* label = it->second;
    label->SetKeyState(state);
  }
}
StickyKeyState StickyKeysOverlayView::GetKeyState(ui::EventFlags modifier) {
  ModifierLabelMap::iterator it = modifier_label_map_.find(modifier);
  DCHECK(it != modifier_label_map_.end());
  return it->second->state();
}
void StickyKeysOverlayView::SetModifierVisible(ui::EventFlags modifier,
                                               bool visible) {
  ModifierLabelMap::iterator it = modifier_label_map_.find(modifier);
  DCHECK(it != modifier_label_map_.end());
  it->second->SetVisible(visible);
}
void StickyKeysOverlayView::AddKeyLabel(ui::EventFlags modifier,
                                        const std::string& key_label) {
  StickyKeyOverlayLabel* label = new StickyKeyOverlayLabel(key_label);
  AddChildView(label);
  modifier_label_map_[modifier] = label;
}
StickyKeysOverlay::StickyKeysOverlay()
    : is_visible_(false),
      overlay_view_(new StickyKeysOverlayView),
      widget_size_(overlay_view_->GetPreferredSize()) {
  views::Widget::InitParams params;
  params.type = views::Widget::InitParams::TYPE_POPUP;
  params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
  params.accept_events = false;
  params.can_activate = false;
  params.keep_on_top = true;
  params.remove_standard_frame = true;
  params.delegate = overlay_view_;
  params.bounds = CalculateOverlayBounds();
  params.parent = Shell::GetContainer(Shell::GetTargetRootWindow(),
                                      kShellWindowId_OverlayContainer);
  overlay_widget_.reset(new views::Widget);
  overlay_widget_->Init(params);
  overlay_widget_->SetVisibilityChangedAnimationsEnabled(false);
  overlay_widget_->SetContentsView(overlay_view_);
  overlay_widget_->GetNativeView()->SetName("StickyKeysOverlay");
}
StickyKeysOverlay::~StickyKeysOverlay() {}
void StickyKeysOverlay::Show(bool visible) {
  if (is_visible_ == visible)
    return;
  is_visible_ = visible;
  if (is_visible_)
    overlay_widget_->Show();
  overlay_widget_->SetBounds(CalculateOverlayBounds());
  ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator();
  animator->AddObserver(this);
  
  if (!animator->is_animating()) {
    int sign = is_visible_ ? -1 : 1;
    gfx::Transform transform;
    transform.Translate(
        sign * (widget_size_.width() + kHorizontalOverlayOffset), 0);
    overlay_widget_->GetLayer()->SetTransform(transform);
  }
  ui::ScopedLayerAnimationSettings settings(animator);
  settings.SetPreemptionStrategy(
      ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
  settings.SetTweenType(visible ? gfx::Tween::EASE_OUT : gfx::Tween::EASE_IN);
  settings.SetTransitionDuration(
      base::TimeDelta::FromMilliseconds(kSlideAnimationDurationMs));
  overlay_widget_->GetLayer()->SetTransform(gfx::Transform());
}
void StickyKeysOverlay::SetModifierVisible(ui::EventFlags modifier,
                                           bool visible) {
  overlay_view_->SetModifierVisible(modifier, visible);
  widget_size_ = overlay_view_->GetPreferredSize();
}
void StickyKeysOverlay::SetModifierKeyState(ui::EventFlags modifier,
                                            StickyKeyState state) {
  overlay_view_->SetKeyState(modifier, state);
}
StickyKeyState StickyKeysOverlay::GetModifierKeyState(
    ui::EventFlags modifier) {
  return overlay_view_->GetKeyState(modifier);
}
gfx::Rect StickyKeysOverlay::CalculateOverlayBounds() {
  int x = is_visible_ ? kHorizontalOverlayOffset : -widget_size_.width();
  return gfx::Rect(gfx::Point(x, kVerticalOverlayOffset), widget_size_);
}
void StickyKeysOverlay::OnLayerAnimationEnded(
    ui::LayerAnimationSequence* sequence) {
  ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator();
  if (animator)
    animator->RemoveObserver(this);
  if (!is_visible_)
    overlay_widget_->Hide();
}
void StickyKeysOverlay::OnLayerAnimationAborted(
    ui::LayerAnimationSequence* sequence) {
  ui::LayerAnimator* animator = overlay_widget_->GetLayer()->GetAnimator();
  if (animator)
    animator->RemoveObserver(this);
}
void StickyKeysOverlay::OnLayerAnimationScheduled(
    ui::LayerAnimationSequence* sequence) {
}
}