Made the clipboard-related functionality in TextInput more testable. Added test_clipboard_paste to the "test-unit" suite.

This commit is contained in:
Avi Weinstock 2015-04-22 13:25:05 -04:00
parent 387836c42e
commit b742eeca05
11 changed files with 532 additions and 436 deletions

View file

@ -4,17 +4,17 @@
//! Common handling of keyboard input and state management for text input controls
use dom::bindings::codegen::Bindings::KeyboardEventBinding::KeyboardEventMethods;
use clipboard_provider::ClipboardProvider;
use dom::bindings::js::JSRef;
use msg::constellation_msg::ConstellationChan;
use msg::constellation_msg::Msg as ConstellationMsg;
use dom::keyboardevent::KeyboardEvent;
use dom::keyboardevent::{KeyboardEvent, KeyboardEventHelpers, key_value};
use msg::constellation_msg::{SHIFT, CONTROL, ALT, SUPER};
use msg::constellation_msg::{Key, KeyModifiers};
use util::str::DOMString;
use std::borrow::ToOwned;
use std::cmp::{min, max};
use std::default::Default;
use std::sync::mpsc::channel;
#[derive(Copy, Clone, PartialEq)]
pub enum Selection {
@ -33,7 +33,7 @@ pub struct TextPoint {
/// Encapsulated state for handling keyboard input in a single or multiline text input control.
#[jstraceable]
pub struct TextInput {
pub struct TextInput<T: ClipboardProvider> {
/// Current text input content, split across lines without trailing '\n'
lines: Vec<DOMString>,
/// Current cursor input point
@ -42,7 +42,7 @@ pub struct TextInput {
selection_begin: Option<TextPoint>,
/// Is this a multiline input?
multiline: bool,
constellation_channel: Option<ConstellationChan>
clipboard_provider: T,
}
/// Resulting action to be taken by the owner of a text input that is handling an event.
@ -79,24 +79,24 @@ pub enum DeleteDir {
/// Was the keyboard event accompanied by the standard control modifier,
/// i.e. cmd on Mac OS or ctrl on other platforms.
#[cfg(target_os="macos")]
fn is_control_key(event: JSRef<KeyboardEvent>) -> bool {
event.MetaKey() && !event.CtrlKey() && !event.AltKey()
fn is_control_key(mods: KeyModifiers) -> bool {
mods.contains(SUPER) && !mods.contains(CONTROL | ALT)
}
#[cfg(not(target_os="macos"))]
fn is_control_key(event: JSRef<KeyboardEvent>) -> bool {
event.CtrlKey() && !event.MetaKey() && !event.AltKey()
fn is_control_key(mods: KeyModifiers) -> bool {
mods.contains(CONTROL) && !mods.contains(SUPER | ALT)
}
impl TextInput {
impl<T: ClipboardProvider> TextInput<T> {
/// Instantiate a new text input control
pub fn new(lines: Lines, initial: DOMString, cc: Option<ConstellationChan>) -> TextInput {
pub fn new(lines: Lines, initial: DOMString, clipboard_provider: T) -> TextInput<T> {
let mut i = TextInput {
lines: vec!(),
edit_point: Default::default(),
selection_begin: None,
multiline: lines == Lines::Multiple,
constellation_channel: cc,
clipboard_provider: clipboard_provider
};
i.set_content(initial);
i
@ -283,28 +283,22 @@ impl TextInput {
/// Process a given `KeyboardEvent` and return an action for the caller to execute.
pub fn handle_keydown(&mut self, event: JSRef<KeyboardEvent>) -> KeyReaction {
//A simple way to convert an event to a selection
fn maybe_select(event: JSRef<KeyboardEvent>) -> Selection {
if event.ShiftKey() {
return Selection::Selected
}
return Selection::NotSelected
if let Some(key) = event.get_key() {
self.handle_keydown_aux(key, event.get_key_modifiers())
} else {
KeyReaction::Nothing
}
match &*event.Key() {
"a" if is_control_key(event) => {
}
pub fn handle_keydown_aux(&mut self, key: Key, mods: KeyModifiers) -> KeyReaction {
let maybe_select = if mods.contains(SHIFT) { Selection::Selected } else { Selection::NotSelected };
match key_value(key, mods) {
"a" if is_control_key(mods) => {
self.select_all();
KeyReaction::Nothing
},
"v" if is_control_key(event) => {
let (tx, rx) = channel();
let mut contents = None;
if let Some(ref cc) = self.constellation_channel {
cc.0.send(ConstellationMsg::GetClipboardContents(tx)).unwrap();
contents = Some(rx.recv().unwrap());
}
if let Some(contents) = contents {
self.insert_string(&contents);
}
"v" if is_control_key(mods) => {
let contents = self.clipboard_provider.get_clipboard_contents();
self.insert_string(&contents);
KeyReaction::DispatchInput
},
// printable characters have single-character key values
@ -325,19 +319,19 @@ impl TextInput {
KeyReaction::DispatchInput
}
"ArrowLeft" => {
self.adjust_horizontal(-1, maybe_select(event));
self.adjust_horizontal(-1, maybe_select);
KeyReaction::Nothing
}
"ArrowRight" => {
self.adjust_horizontal(1, maybe_select(event));
self.adjust_horizontal(1, maybe_select);
KeyReaction::Nothing
}
"ArrowUp" => {
self.adjust_vertical(-1, maybe_select(event));
self.adjust_vertical(-1, maybe_select);
KeyReaction::Nothing
}
"ArrowDown" => {
self.adjust_vertical(1, maybe_select(event));
self.adjust_vertical(1, maybe_select);
KeyReaction::Nothing
}
"Enter" => self.handle_return(),
@ -350,11 +344,11 @@ impl TextInput {
KeyReaction::Nothing
}
"PageUp" => {
self.adjust_vertical(-28, maybe_select(event));
self.adjust_vertical(-28, maybe_select);
KeyReaction::Nothing
}
"PageDown" => {
self.adjust_vertical(28, maybe_select(event));
self.adjust_vertical(28, maybe_select);
KeyReaction::Nothing
}
"Tab" => KeyReaction::TriggerDefaultAction,