1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_H_ 6 #define UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_H_ 7 8 #include <string> 9 10 #include "base/basictypes.h" 11 #include "base/compiler_specific.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/memory/weak_ptr.h" 14 #include "base/strings/string16.h" 15 #include "base/timer/timer.h" 16 #include "third_party/skia/include/core/SkColor.h" 17 #include "ui/base/ime/text_input_client.h" 18 #include "ui/base/ime/text_input_type.h" 19 #include "ui/base/models/simple_menu_model.h" 20 #include "ui/base/touch/touch_editing_controller.h" 21 #include "ui/events/keycodes/keyboard_codes.h" 22 #include "ui/gfx/font_list.h" 23 #include "ui/gfx/range/range.h" 24 #include "ui/gfx/selection_model.h" 25 #include "ui/gfx/text_constants.h" 26 #include "ui/views/context_menu_controller.h" 27 #include "ui/views/controls/textfield/textfield_model.h" 28 #include "ui/views/drag_controller.h" 29 #include "ui/views/view.h" 30 31 namespace views { 32 33 class MenuRunner; 34 class Painter; 35 class TextfieldController; 36 37 // A views/skia textfield implementation. No platform-specific code is used. 38 class VIEWS_EXPORT Textfield : public View, 39 public TextfieldModel::Delegate, 40 public ContextMenuController, 41 public DragController, 42 public ui::TouchEditable, 43 public ui::TextInputClient { 44 public: 45 // The textfield's class name. 46 static const char kViewClassName[]; 47 48 // The preferred size of the padding to be used around textfield text. 49 static const int kTextPadding; 50 51 // Returns the text cursor blink time in milliseconds, or 0 for no blinking. 52 static size_t GetCaretBlinkMs(); 53 54 Textfield(); 55 virtual ~Textfield(); 56 57 // Set the controller for this textfield. set_controller(TextfieldController * controller)58 void set_controller(TextfieldController* controller) { 59 controller_ = controller; 60 } 61 62 // Gets/Sets whether or not the Textfield is read-only. read_only()63 bool read_only() const { return read_only_; } 64 void SetReadOnly(bool read_only); 65 66 // Sets the input type; displays only asterisks for TEXT_INPUT_TYPE_PASSWORD. 67 void SetTextInputType(ui::TextInputType type); 68 69 // Gets the text currently displayed in the Textfield. text()70 const base::string16& text() const { return model_->text(); } 71 72 // Sets the text currently displayed in the Textfield. This doesn't 73 // change the cursor position if the current cursor is within the 74 // new text's range, or moves the cursor to the end if the cursor is 75 // out of the new text's range. 76 void SetText(const base::string16& new_text); 77 78 // Appends the given string to the previously-existing text in the field. 79 void AppendText(const base::string16& new_text); 80 81 // Inserts |new_text| at the cursor position, replacing any selected text. 82 void InsertOrReplaceText(const base::string16& new_text); 83 84 // Returns the text direction. 85 base::i18n::TextDirection GetTextDirection() const; 86 87 // Returns the text that is currently selected. 88 base::string16 GetSelectedText() const; 89 90 // Select the entire text range. If |reversed| is true, the range will end at 91 // the logical beginning of the text; this generally shows the leading portion 92 // of text that overflows its display area. 93 void SelectAll(bool reversed); 94 95 // A convenience method to select the word closest to |point|. 96 void SelectWordAt(const gfx::Point& point); 97 98 // Clears the selection within the edit field and sets the caret to the end. 99 void ClearSelection(); 100 101 // Checks if there is any selected text. 102 bool HasSelection() const; 103 104 // Gets/sets the text color to be used when painting the Textfield. 105 // Call UseDefaultTextColor() to restore the default system color. 106 SkColor GetTextColor() const; 107 void SetTextColor(SkColor color); 108 void UseDefaultTextColor(); 109 110 // Gets/sets the background color to be used when painting the Textfield. 111 // Call UseDefaultBackgroundColor() to restore the default system color. 112 SkColor GetBackgroundColor() const; 113 void SetBackgroundColor(SkColor color); 114 void UseDefaultBackgroundColor(); 115 116 // Gets/sets the selection text color to be used when painting the Textfield. 117 // Call UseDefaultSelectionTextColor() to restore the default system color. 118 SkColor GetSelectionTextColor() const; 119 void SetSelectionTextColor(SkColor color); 120 void UseDefaultSelectionTextColor(); 121 122 // Gets/sets the selection background color to be used when painting the 123 // Textfield. Call UseDefaultSelectionBackgroundColor() to restore the default 124 // system color. 125 SkColor GetSelectionBackgroundColor() const; 126 void SetSelectionBackgroundColor(SkColor color); 127 void UseDefaultSelectionBackgroundColor(); 128 129 // Set drop shadows underneath the text. 130 void SetShadows(const gfx::ShadowValues& shadows); 131 132 // Gets/Sets whether or not the cursor is enabled. 133 bool GetCursorEnabled() const; 134 void SetCursorEnabled(bool enabled); 135 136 // Gets/Sets the fonts used when rendering the text within the Textfield. 137 const gfx::FontList& GetFontList() const; 138 void SetFontList(const gfx::FontList& font_list); 139 140 // Sets the default width of the text control. See default_width_in_chars_. set_default_width_in_chars(int default_width)141 void set_default_width_in_chars(int default_width) { 142 default_width_in_chars_ = default_width; 143 } 144 145 // Sets the text to display when empty. set_placeholder_text(const base::string16 & text)146 void set_placeholder_text(const base::string16& text) { 147 placeholder_text_ = text; 148 } 149 virtual base::string16 GetPlaceholderText() const; 150 placeholder_text_color()151 SkColor placeholder_text_color() const { return placeholder_text_color_; } set_placeholder_text_color(SkColor color)152 void set_placeholder_text_color(SkColor color) { 153 placeholder_text_color_ = color; 154 } 155 156 // Get or set the horizontal alignment used for the button from the underlying 157 // RenderText object. 158 gfx::HorizontalAlignment GetHorizontalAlignment() const; 159 void SetHorizontalAlignment(gfx::HorizontalAlignment alignment); 160 161 // Displays a virtual keyboard or alternate input view if enabled. 162 void ShowImeIfNeeded(); 163 164 // Returns whether or not an IME is composing text. 165 bool IsIMEComposing() const; 166 167 // Gets the selected logical text range. 168 const gfx::Range& GetSelectedRange() const; 169 170 // Selects the specified logical text range. 171 void SelectRange(const gfx::Range& range); 172 173 // Gets the text selection model. 174 const gfx::SelectionModel& GetSelectionModel() const; 175 176 // Sets the specified text selection model. 177 void SelectSelectionModel(const gfx::SelectionModel& sel); 178 179 // Returns the current cursor position. 180 size_t GetCursorPosition() const; 181 182 // Set the text color over the entire text or a logical character range. 183 // Empty and invalid ranges are ignored. 184 void SetColor(SkColor value); 185 void ApplyColor(SkColor value, const gfx::Range& range); 186 187 // Set various text styles over the entire text or a logical character range. 188 // The respective |style| is applied if |value| is true, or removed if false. 189 // Empty and invalid ranges are ignored. 190 void SetStyle(gfx::TextStyle style, bool value); 191 void ApplyStyle(gfx::TextStyle style, bool value, const gfx::Range& range); 192 193 // Clears Edit history. 194 void ClearEditHistory(); 195 196 // Set the accessible name of the text field. 197 void SetAccessibleName(const base::string16& name); 198 199 // Performs the action associated with the specified command id. 200 void ExecuteCommand(int command_id); 201 202 void SetFocusPainter(scoped_ptr<Painter> focus_painter); 203 204 // Returns whether there is a drag operation originating from the textfield. 205 bool HasTextBeingDragged(); 206 207 // View overrides: 208 virtual gfx::Insets GetInsets() const OVERRIDE; 209 virtual int GetBaseline() const OVERRIDE; 210 virtual gfx::Size GetPreferredSize() const OVERRIDE; 211 virtual const char* GetClassName() const OVERRIDE; 212 virtual gfx::NativeCursor GetCursor(const ui::MouseEvent& event) OVERRIDE; 213 virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE; 214 virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE; 215 virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE; 216 virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE; 217 virtual ui::TextInputClient* GetTextInputClient() OVERRIDE; 218 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; 219 virtual void AboutToRequestFocusFromTabTraversal(bool reverse) OVERRIDE; 220 virtual bool SkipDefaultKeyEventProcessing( 221 const ui::KeyEvent& event) OVERRIDE; 222 virtual bool GetDropFormats( 223 int* formats, 224 std::set<ui::OSExchangeData::CustomFormat>* custom_formats) OVERRIDE; 225 virtual bool CanDrop(const ui::OSExchangeData& data) OVERRIDE; 226 virtual int OnDragUpdated(const ui::DropTargetEvent& event) OVERRIDE; 227 virtual void OnDragExited() OVERRIDE; 228 virtual int OnPerformDrop(const ui::DropTargetEvent& event) OVERRIDE; 229 virtual void OnDragDone() OVERRIDE; 230 virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE; 231 virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE; 232 virtual bool GetNeedsNotificationWhenVisibleBoundsChange() const OVERRIDE; 233 virtual void OnVisibleBoundsChanged() OVERRIDE; 234 virtual void OnEnabledChanged() OVERRIDE; 235 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; 236 virtual void OnFocus() OVERRIDE; 237 virtual void OnBlur() OVERRIDE; 238 virtual gfx::Point GetKeyboardContextMenuLocation() OVERRIDE; 239 virtual void OnNativeThemeChanged(const ui::NativeTheme* theme) OVERRIDE; 240 241 // TextfieldModel::Delegate overrides: 242 virtual void OnCompositionTextConfirmedOrCleared() OVERRIDE; 243 244 // ContextMenuController overrides: 245 virtual void ShowContextMenuForView(View* source, 246 const gfx::Point& point, 247 ui::MenuSourceType source_type) OVERRIDE; 248 249 // DragController overrides: 250 virtual void WriteDragDataForView(View* sender, 251 const gfx::Point& press_pt, 252 ui::OSExchangeData* data) OVERRIDE; 253 virtual int GetDragOperationsForView(View* sender, 254 const gfx::Point& p) OVERRIDE; 255 virtual bool CanStartDragForView(View* sender, 256 const gfx::Point& press_pt, 257 const gfx::Point& p) OVERRIDE; 258 259 // ui::TouchEditable overrides: 260 virtual void SelectRect(const gfx::Point& start, 261 const gfx::Point& end) OVERRIDE; 262 virtual void MoveCaretTo(const gfx::Point& point) OVERRIDE; 263 virtual void GetSelectionEndPoints(gfx::Rect* p1, gfx::Rect* p2) OVERRIDE; 264 virtual gfx::Rect GetBounds() OVERRIDE; 265 virtual gfx::NativeView GetNativeView() const OVERRIDE; 266 virtual void ConvertPointToScreen(gfx::Point* point) OVERRIDE; 267 virtual void ConvertPointFromScreen(gfx::Point* point) OVERRIDE; 268 virtual bool DrawsHandles() OVERRIDE; 269 virtual void OpenContextMenu(const gfx::Point& anchor) OVERRIDE; 270 virtual void DestroyTouchSelection() OVERRIDE; 271 272 // ui::SimpleMenuModel::Delegate overrides: 273 virtual bool IsCommandIdChecked(int command_id) const OVERRIDE; 274 virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE; 275 virtual bool GetAcceleratorForCommandId( 276 int command_id, 277 ui::Accelerator* accelerator) OVERRIDE; 278 virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE; 279 280 // ui::TextInputClient overrides: 281 virtual void SetCompositionText( 282 const ui::CompositionText& composition) OVERRIDE; 283 virtual void ConfirmCompositionText() OVERRIDE; 284 virtual void ClearCompositionText() OVERRIDE; 285 virtual void InsertText(const base::string16& text) OVERRIDE; 286 virtual void InsertChar(base::char16 ch, int flags) OVERRIDE; 287 virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE; 288 virtual ui::TextInputType GetTextInputType() const OVERRIDE; 289 virtual ui::TextInputMode GetTextInputMode() const OVERRIDE; 290 virtual bool CanComposeInline() const OVERRIDE; 291 virtual gfx::Rect GetCaretBounds() const OVERRIDE; 292 virtual bool GetCompositionCharacterBounds(uint32 index, 293 gfx::Rect* rect) const OVERRIDE; 294 virtual bool HasCompositionText() const OVERRIDE; 295 virtual bool GetTextRange(gfx::Range* range) const OVERRIDE; 296 virtual bool GetCompositionTextRange(gfx::Range* range) const OVERRIDE; 297 virtual bool GetSelectionRange(gfx::Range* range) const OVERRIDE; 298 virtual bool SetSelectionRange(const gfx::Range& range) OVERRIDE; 299 virtual bool DeleteRange(const gfx::Range& range) OVERRIDE; 300 virtual bool GetTextFromRange(const gfx::Range& range, 301 base::string16* text) const OVERRIDE; 302 virtual void OnInputMethodChanged() OVERRIDE; 303 virtual bool ChangeTextDirectionAndLayoutAlignment( 304 base::i18n::TextDirection direction) OVERRIDE; 305 virtual void ExtendSelectionAndDelete(size_t before, size_t after) OVERRIDE; 306 virtual void EnsureCaretInRect(const gfx::Rect& rect) OVERRIDE; 307 virtual void OnCandidateWindowShown() OVERRIDE; 308 virtual void OnCandidateWindowUpdated() OVERRIDE; 309 virtual void OnCandidateWindowHidden() OVERRIDE; 310 virtual bool IsEditingCommandEnabled(int command_id) OVERRIDE; 311 virtual void ExecuteEditingCommand(int command_id) OVERRIDE; 312 313 protected: 314 // Returns the TextfieldModel's text/cursor/selection rendering model. 315 gfx::RenderText* GetRenderText() const; 316 last_click_location()317 gfx::Point last_click_location() const { return last_click_location_; } 318 319 // Get the text from the selection clipboard. 320 virtual base::string16 GetSelectionClipboardText() const; 321 322 private: 323 friend class TextfieldTestApi; 324 325 // Handles a request to change the value of this text field from software 326 // using an accessibility API (typically automation software, screen readers 327 // don't normally use this). Sets the value and clears the selection. 328 void AccessibilitySetValue(const base::string16& new_value); 329 330 // Updates the painted background color. 331 void UpdateBackgroundColor(); 332 333 // Does necessary updates when the text and/or cursor position changes. 334 void UpdateAfterChange(bool text_changed, bool cursor_changed); 335 336 // A callback function to periodically update the cursor state. 337 void UpdateCursor(); 338 339 // Repaint the cursor. 340 void RepaintCursor(); 341 342 void PaintTextAndCursor(gfx::Canvas* canvas); 343 344 // Helper function to call MoveCursorTo on the TextfieldModel. 345 void MoveCursorTo(const gfx::Point& point, bool select); 346 347 // Helper function to update the selection on a mouse drag. 348 void SelectThroughLastDragLocation(); 349 350 // Convenience method to notify the InputMethod and TouchSelectionController. 351 void OnCaretBoundsChanged(); 352 353 // Convenience method to call TextfieldController::OnBeforeUserAction(); 354 void OnBeforeUserAction(); 355 356 // Convenience method to call TextfieldController::OnAfterUserAction(); 357 void OnAfterUserAction(); 358 359 // Calls |model_->Cut()| and notifies TextfieldController on success. 360 bool Cut(); 361 362 // Calls |model_->Copy()| and notifies TextfieldController on success. 363 bool Copy(); 364 365 // Calls |model_->Paste()| and calls TextfieldController::ContentsChanged() 366 // explicitly if paste succeeded. 367 bool Paste(); 368 369 // Utility function to prepare the context menu. 370 void UpdateContextMenu(); 371 372 // Tracks the mouse clicks for single/double/triple clicks. 373 void TrackMouseClicks(const ui::MouseEvent& event); 374 375 // Returns true if the current text input type allows access by the IME. 376 bool ImeEditingAllowed() const; 377 378 // Reveals the password character at |index| for a set duration. 379 // If |index| is -1, the existing revealed character will be reset. 380 void RevealPasswordChar(int index); 381 382 void CreateTouchSelectionControllerAndNotifyIt(); 383 384 // Updates the selection clipboard to any non-empty text selection. 385 void UpdateSelectionClipboard() const; 386 387 // Pastes the selection clipboard for the specified mouse event. 388 void PasteSelectionClipboard(const ui::MouseEvent& event); 389 390 // The text model. 391 scoped_ptr<TextfieldModel> model_; 392 393 // This is the current listener for events from this Textfield. 394 TextfieldController* controller_; 395 396 // True if this Textfield cannot accept input and is read-only. 397 bool read_only_; 398 399 // The default number of average characters for the width of this text field. 400 // This will be reported as the "desired size". Defaults to 0. 401 int default_width_in_chars_; 402 403 scoped_ptr<Painter> focus_painter_; 404 405 // Flags indicating whether various system colors should be used, and if not, 406 // what overriding color values should be used instead. 407 bool use_default_text_color_; 408 bool use_default_background_color_; 409 bool use_default_selection_text_color_; 410 bool use_default_selection_background_color_; 411 SkColor text_color_; 412 SkColor background_color_; 413 SkColor selection_text_color_; 414 SkColor selection_background_color_; 415 416 // Text to display when empty. 417 base::string16 placeholder_text_; 418 419 // Placeholder text color. 420 SkColor placeholder_text_color_; 421 422 // The accessible name of the text field. 423 base::string16 accessible_name_; 424 425 // The input type of this text field. 426 ui::TextInputType text_input_type_; 427 428 // The duration and timer to reveal the last typed password character. 429 base::TimeDelta password_reveal_duration_; 430 base::OneShotTimer<Textfield> password_reveal_timer_; 431 432 // Tracks whether a user action is being performed; i.e. OnBeforeUserAction() 433 // has been called, but OnAfterUserAction() has not yet been called. 434 bool performing_user_action_; 435 436 // True if InputMethod::CancelComposition() should not be called. 437 bool skip_input_method_cancel_composition_; 438 439 // The text editing cursor repaint timer and visibility. 440 base::RepeatingTimer<Textfield> cursor_repaint_timer_; 441 bool cursor_visible_; 442 443 // The drop cursor is a visual cue for where dragged text will be dropped. 444 bool drop_cursor_visible_; 445 gfx::SelectionModel drop_cursor_position_; 446 447 // Is the user potentially dragging and dropping from this view? 448 bool initiating_drag_; 449 450 // A timer and point used to modify the selection when dragging. 451 base::RepeatingTimer<Textfield> drag_selection_timer_; 452 gfx::Point last_drag_location_; 453 454 // State variables used to track double and triple clicks. 455 size_t aggregated_clicks_; 456 base::TimeDelta last_click_time_; 457 gfx::Point last_click_location_; 458 gfx::Range double_click_word_; 459 460 scoped_ptr<ui::TouchSelectionController> touch_selection_controller_; 461 462 // Used to track touch drag starting location and offset to enable touch 463 // scrolling. 464 gfx::Point drag_start_location_; 465 int drag_start_display_offset_; 466 467 // Tracks if touch editing handles are hidden because user has started 468 // scrolling. If |true|, handles are shown after scrolling ends. 469 bool touch_handles_hidden_due_to_scroll_; 470 471 // Context menu related members. 472 scoped_ptr<ui::SimpleMenuModel> context_menu_contents_; 473 scoped_ptr<views::MenuRunner> context_menu_runner_; 474 475 // Used to bind callback functions to this object. 476 base::WeakPtrFactory<Textfield> weak_ptr_factory_; 477 478 DISALLOW_COPY_AND_ASSIGN(Textfield); 479 }; 480 481 } // namespace views 482 483 #endif // UI_VIEWS_CONTROLS_TEXTFIELD_TEXTFIELD_H_ 484