Skip to content
Snippets Groups Projects
Commit 2689f76a authored by varunjain@chromium.org's avatar varunjain@chromium.org
Browse files

Implement clipboard features in views textfield.

BUG=none
TEST=Added new test.

Review URL: http://codereview.chromium.org/6004010

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@71136 0039d316-1c4b-4281-b951-d872f2087c98
parent 8f5e1aa2
No related branches found
No related tags found
No related merge requests found
......@@ -445,6 +445,18 @@ bool NativeTextfieldViews::HandleKeyEvent(const KeyEvent& key_event) {
cursor_changed = true;
}
break;
case app::VKEY_X:
if (control)
text_changed = model_->Cut();
break;
case app::VKEY_C:
if (control)
model_->Copy();
break;
case app::VKEY_V:
if (control)
text_changed = model_->Paste();
break;
case app::VKEY_RIGHT:
control ? model_->MoveCursorToNextWord(selection)
: model_->MoveCursorRight(selection);
......
......@@ -26,7 +26,6 @@ class TextfieldViewsModel;
// No platform specific code is used.
// Following features are not yet supported.
// * BIDI
// * Clipboard (Cut & Paste).
// * Context Menu.
// * IME/i18n support.
// * X selection (only if we want to support).
......
......@@ -10,6 +10,9 @@
#include "base/logging.h"
#include "base/utf_string_conversions.h"
#include "gfx/font.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "views/views_delegate.h"
namespace views {
......@@ -225,6 +228,38 @@ void TextfieldViewsModel::ClearSelection() {
selection_begin_ = cursor_pos_;
}
bool TextfieldViewsModel::Cut() {
if (HasSelection()) {
ui::ScopedClipboardWriter(views::ViewsDelegate::views_delegate
->GetClipboard()).WriteText(GetSelectedText());
DeleteSelection();
return true;
}
return false;
}
void TextfieldViewsModel::Copy() {
if (HasSelection()) {
ui::ScopedClipboardWriter(views::ViewsDelegate::views_delegate
->GetClipboard()).WriteText(GetSelectedText());
}
}
bool TextfieldViewsModel::Paste() {
string16 result;
views::ViewsDelegate::views_delegate->GetClipboard()
->ReadText(ui::Clipboard::BUFFER_STANDARD, &result);
if (!result.empty()) {
if (HasSelection())
DeleteSelection();
text_.insert(cursor_pos_, result);
cursor_pos_ += result.length();
ClearSelection();
return true;
}
return false;
}
bool TextfieldViewsModel::HasSelection() const {
return selection_begin_ != cursor_pos_;
}
......
......@@ -126,6 +126,17 @@ class TextfieldViewsModel {
return GetVisibleText(0U, text_.length());
}
// Cuts the currently selected text and puts it to clipboard. Returns true
// if text has changed after cutting.
bool Cut();
// Copies the currently selected text and puts it to clipboard.
void Copy();
// Pastes text from the clipboard at current cursor position. Returns true
// if text has changed after pasting.
bool Paste();
private:
friend class NativeTextfieldViews;
......
......@@ -2,9 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/message_loop.h"
#include "base/scoped_ptr.h"
#include "base/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "views/controls/textfield/textfield_views_model.h"
#include "views/test/test_views_delegate.h"
#include "views/views_delegate.h"
namespace views {
......@@ -282,4 +288,57 @@ TEST(TextfieldViewsModelTest, SetText) {
EXPECT_EQ(0U, model.cursor_pos());
}
TEST(TextfieldViewsModelTest, Clipboard) {
views::ViewsDelegate::views_delegate = new TestViewsDelegate();
ui::Clipboard* clipboard
= views::ViewsDelegate::views_delegate->GetClipboard();
string16 initial_clipboard_text;
clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &initial_clipboard_text);
string16 clipboard_text;
TextfieldViewsModel model;
model.Append(ASCIIToUTF16("HELLO WORLD"));
model.MoveCursorToEnd(false);
// Test for cut: Empty selection.
EXPECT_FALSE(model.Cut());
clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text);
EXPECT_STR_EQ(UTF16ToUTF8(initial_clipboard_text), clipboard_text);
EXPECT_STR_EQ("HELLO WORLD", model.text());
EXPECT_EQ(11U, model.cursor_pos());
// Test for cut: Non-empty selection.
model.MoveCursorToPreviousWord(true);
EXPECT_TRUE(model.Cut());
clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text);
EXPECT_STR_EQ("WORLD", clipboard_text);
EXPECT_STR_EQ("HELLO ", model.text());
EXPECT_EQ(6U, model.cursor_pos());
// Test for copy: Empty selection.
model.Copy();
clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text);
EXPECT_STR_EQ("WORLD", clipboard_text);
EXPECT_STR_EQ("HELLO ", model.text());
EXPECT_EQ(6U, model.cursor_pos());
// Test for copy: Non-empty selection.
model.Append(ASCIIToUTF16("HELLO WORLD"));
model.SelectAll();
model.Copy();
clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text);
EXPECT_STR_EQ("HELLO HELLO WORLD", clipboard_text);
EXPECT_STR_EQ("HELLO HELLO WORLD", model.text());
EXPECT_EQ(0U, model.cursor_pos());
// Test for paste.
model.ClearSelection();
model.MoveCursorToEnd(false);
model.MoveCursorToPreviousWord(true);
EXPECT_TRUE(model.Paste());
clipboard->ReadText(ui::Clipboard::BUFFER_STANDARD, &clipboard_text);
EXPECT_STR_EQ("HELLO HELLO WORLD", clipboard_text);
EXPECT_STR_EQ("HELLO HELLO HELLO HELLO WORLD", model.text());
EXPECT_EQ(29U, model.cursor_pos());
}
} // namespace views
// 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 "base/scoped_ptr.h"
#include "ui/base/clipboard/clipboard.h"
#include "views/views_delegate.h"
class TestViewsDelegate : public views::ViewsDelegate {
public:
TestViewsDelegate() {}
virtual ~TestViewsDelegate() {}
// Overridden from views::ViewsDelegate:
virtual ui::Clipboard* GetClipboard() const {
if (!clipboard_.get()) {
// Note that we need a MessageLoop for the next call to work.
clipboard_.reset(new ui::Clipboard);
}
return clipboard_.get();
}
virtual void SaveWindowPlacement(const std::wstring& window_name,
const gfx::Rect& bounds,
bool maximized) {
}
virtual bool GetSavedWindowBounds(const std::wstring& window_name,
gfx::Rect* bounds) const {
return false;
}
virtual bool GetSavedMaximizedState(const std::wstring& window_name,
bool* maximized) const {
return false;
}
virtual void NotifyAccessibilityEvent(
views::View* view, AccessibilityTypes::Event event_type) {}
#if defined(OS_WIN)
virtual HICON GetDefaultWindowIcon() const {
return NULL;
}
#endif
virtual void AddRef() {}
virtual void ReleaseRef() {}
private:
mutable scoped_ptr<ui::Clipboard> clipboard_;
DISALLOW_COPY_AND_ASSIGN(TestViewsDelegate);
};
......@@ -29,6 +29,7 @@
#if defined(OS_WIN)
#include "views/widget/widget_win.h"
#include "views/controls/button/native_button_win.h"
#include "views/test/test_views_delegate.h"
#elif defined(OS_LINUX)
#include "views/widget/widget_gtk.h"
#include "views/window/window_gtk.h"
......@@ -840,44 +841,6 @@ TEST_F(ViewTest, Textfield) {
}
#if defined(OS_WIN)
class TestViewsDelegate : public views::ViewsDelegate {
public:
TestViewsDelegate() {}
virtual ~TestViewsDelegate() {}
// Overridden from views::ViewsDelegate:
virtual ui::Clipboard* GetClipboard() const {
if (!clipboard_.get()) {
// Note that we need a MessageLoop for the next call to work.
clipboard_.reset(new ui::Clipboard);
}
return clipboard_.get();
}
virtual void SaveWindowPlacement(const std::wstring& window_name,
const gfx::Rect& bounds,
bool maximized) {
}
virtual bool GetSavedWindowBounds(const std::wstring& window_name,
gfx::Rect* bounds) const {
return false;
}
virtual bool GetSavedMaximizedState(const std::wstring& window_name,
bool* maximized) const {
return false;
}
virtual void NotifyAccessibilityEvent(
views::View* view, AccessibilityTypes::Event event_type) {}
virtual HICON GetDefaultWindowIcon() const {
return NULL;
}
virtual void AddRef() {}
virtual void ReleaseRef() {}
private:
mutable scoped_ptr<ui::Clipboard> clipboard_;
DISALLOW_COPY_AND_ASSIGN(TestViewsDelegate);
};
// Tests that the Textfield view respond appropiately to cut/copy/paste.
TEST_F(ViewTest, TextfieldCutCopyPaste) {
......
......@@ -441,6 +441,7 @@
'focus/focus_manager_unittest.cc',
'grid_layout_unittest.cc',
'run_all_unittests.cc',
'test/test_views_delegate.h',
'view_unittest.cc',
'<(SHARED_INTERMEDIATE_DIR)/app/app_resources/app_resources.rc',
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment