blob: 97dc01fc5355a15be59355e5b3f0199ff9e06d0b [file] [log] [blame]
// 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 <gdk/gdk.h>
#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;
}
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() {
if (enabled_) {
if (!(font().GetStyle() & gfx::Font::UNDERLINED)) {
Label::SetFont(
font().DeriveFont(0, font().GetStyle() | gfx::Font::UNDERLINED));
}
Label::SetColor(highlighted_ ? highlighted_color_ : normal_color_);
} else {
if (font().GetStyle() & gfx::Font::UNDERLINED) {
Label::SetFont(
font().DeriveFont(0, font().GetStyle() & ~gfx::Font::UNDERLINED));
}
Label::SetColor(disabled_color_);
}
}
} // namespace views