// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "views/controls/link.h" #if defined(OS_LINUX) #include #endif #include "base/keyboard_codes.h" #include "base/logging.h" #include "gfx/color_utils.h" #include "gfx/font.h" #include "views/event.h" namespace { void GetColors(const SkColor* background_color, // NULL means "use default" SkColor* highlighted_color, SkColor* disabled_color, SkColor* normal_color) { static SkColor kHighlightedColor, kDisabledColor, kNormalColor; static bool initialized = false; if (!initialized) { #if defined(OS_WIN) kHighlightedColor = color_utils::GetReadableColor( SkColorSetRGB(200, 0, 0), color_utils::GetSysSkColor(COLOR_WINDOW)); kDisabledColor = color_utils::GetSysSkColor(COLOR_WINDOWTEXT); kNormalColor = color_utils::GetSysSkColor(COLOR_HOTLIGHT); #else // TODO(beng): source from theme provider. kHighlightedColor = SK_ColorRED; kDisabledColor = SK_ColorBLACK; kNormalColor = SkColorSetRGB(0, 51, 153); #endif initialized = true; } if (background_color) { *highlighted_color = color_utils::GetReadableColor(kHighlightedColor, *background_color); *disabled_color = color_utils::GetReadableColor(kDisabledColor, *background_color); *normal_color = color_utils::GetReadableColor(kNormalColor, *background_color); } else { *highlighted_color = kHighlightedColor; *disabled_color = kDisabledColor; *normal_color = kNormalColor; } } } namespace views { #if defined(OS_WIN) static HCURSOR g_hand_cursor = NULL; #endif const char Link::kViewClassName[] = "views/Link"; Link::Link() : Label(L""), controller_(NULL), highlighted_(false) { Init(); SetFocusable(true); } Link::Link(const std::wstring& title) : Label(title), controller_(NULL), highlighted_(false) { Init(); SetFocusable(true); } void Link::Init() { GetColors(NULL, &highlighted_color_, &disabled_color_, &normal_color_); SetColor(normal_color_); ValidateStyle(); } Link::~Link() { } void Link::SetController(LinkController* controller) { controller_ = controller; } const LinkController* Link::GetController() { return controller_; } bool Link::OnMousePressed(const MouseEvent& e) { if (!enabled_ || (!e.IsLeftMouseButton() && !e.IsMiddleMouseButton())) return false; SetHighlighted(true); return true; } bool Link::OnMouseDragged(const MouseEvent& e) { SetHighlighted(enabled_ && (e.IsLeftMouseButton() || e.IsMiddleMouseButton()) && HitTest(e.location())); return true; } void Link::OnMouseReleased(const MouseEvent& e, bool canceled) { // Change the highlight first just in case this instance is deleted // while calling the controller SetHighlighted(false); if (enabled_ && !canceled && (e.IsLeftMouseButton() || e.IsMiddleMouseButton()) && HitTest(e.location())) { // Focus the link on click. RequestFocus(); if (controller_) controller_->LinkActivated(this, e.GetFlags()); } } bool Link::OnKeyPressed(const KeyEvent& e) { bool activate = ((e.GetKeyCode() == base::VKEY_SPACE) || (e.GetKeyCode() == base::VKEY_RETURN)); if (!activate) return false; SetHighlighted(false); // Focus the link on key pressed. RequestFocus(); if (controller_) controller_->LinkActivated(this, e.GetFlags()); return true; } bool Link::SkipDefaultKeyEventProcessing(const KeyEvent& e) { // Make sure we don't process space or enter as accelerators. return (e.GetKeyCode() == base::VKEY_SPACE) || (e.GetKeyCode() == base::VKEY_RETURN); } bool Link::GetAccessibleRole(AccessibilityTypes::Role* role) { DCHECK(role); *role = AccessibilityTypes::ROLE_LINK; return true; } bool Link::GetAccessibleName(std::wstring* name) { DCHECK(name); *name = GetText(); return !name->empty(); } void Link::SetFont(const gfx::Font& font) { Label::SetFont(font); ValidateStyle(); } void Link::SetEnabled(bool f) { if (f != enabled_) { enabled_ = f; ValidateStyle(); SchedulePaint(); } } gfx::NativeCursor Link::GetCursorForPoint(Event::EventType event_type, const gfx::Point& p) { if (!enabled_) return NULL; #if defined(OS_WIN) if (!g_hand_cursor) g_hand_cursor = LoadCursor(NULL, IDC_HAND); return g_hand_cursor; #elif defined(OS_LINUX) return gdk_cursor_new(GDK_HAND2); #endif } std::string Link::GetClassName() const { return kViewClassName; } void Link::SetHighlightedColor(const SkColor& color) { normal_color_ = color; ValidateStyle(); } void Link::SetDisabledColor(const SkColor& color) { disabled_color_ = color; ValidateStyle(); } void Link::SetNormalColor(const SkColor& color) { normal_color_ = color; ValidateStyle(); } void Link::MakeReadableOverBackgroundColor(const SkColor& color) { GetColors(&color, &highlighted_color_, &disabled_color_, &normal_color_); ValidateStyle(); } void Link::SetHighlighted(bool f) { if (f != highlighted_) { highlighted_ = f; ValidateStyle(); SchedulePaint(); } } void Link::ValidateStyle() { gfx::Font font = GetFont(); if (enabled_) { if ((font.style() & gfx::Font::UNDERLINED) == 0) Label::SetFont(font.DeriveFont(0, font.style() | gfx::Font::UNDERLINED)); Label::SetColor(highlighted_ ? highlighted_color_ : normal_color_); } else { if ((font.style() & gfx::Font::UNDERLINED) != 0) Label::SetFont(font.DeriveFont(0, font.style() & ~gfx::Font::UNDERLINED)); Label::SetColor(disabled_color_); } } } // namespace views