blob: 3230fb4d6c80c3e0ff284ca543b546ad54ac0df3 [file] [log] [blame]
// Copyright (c) 2013 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.
#ifndef UI_VIEWS_CONTROLS_TEXTFIELD_NATIVE_TEXTFIELD_VIEWS_H_
#define UI_VIEWS_CONTROLS_TEXTFIELD_NATIVE_TEXTFIELD_VIEWS_H_
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "base/timer/timer.h"
#include "ui/base/events/event_constants.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/base/models/simple_menu_model.h"
#include "ui/base/touch/touch_editing_controller.h"
#include "ui/gfx/font.h"
#include "ui/views/border.h"
#include "ui/views/context_menu_controller.h"
#include "ui/views/controls/textfield/native_textfield_wrapper.h"
#include "ui/views/controls/textfield/textfield_views_model.h"
#include "ui/views/drag_controller.h"
#include "ui/views/view.h"
namespace base {
class Time;
}
namespace gfx {
class Canvas;
}
namespace views {
class FocusableBorder;
class MenuModelAdapter;
class MenuRunner;
// A views/skia only implementation of NativeTextfieldWrapper.
// No platform specific code is used.
// Following features are not yet supported.
// * BIDI/Complex script.
// * Support surrogate pair, or maybe we should just use UTF32 internally.
// * X selection (only if we want to support).
// Once completed, this will replace Textfield, NativeTextfieldWin and
// NativeTextfieldGtk.
class VIEWS_EXPORT NativeTextfieldViews : public View,
public ui::TouchEditable,
public ContextMenuController,
public DragController,
public NativeTextfieldWrapper,
public ui::TextInputClient,
public TextfieldViewsModel::Delegate {
public:
// Interval over which the cursor/caret blinks. This represents the full
// cycle; the caret is shown for half of this time and hidden for the other
// half.
static const int kCursorBlinkCycleMs;
explicit NativeTextfieldViews(Textfield* parent);
virtual ~NativeTextfieldViews();
// View overrides:
virtual gfx::NativeCursor GetCursor(const ui::MouseEvent& event) OVERRIDE;
virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE;
virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE;
virtual bool GetDropFormats(
int* formats,
std::set<ui::OSExchangeData::CustomFormat>* custom_formats) OVERRIDE;
virtual bool CanDrop(const ui::OSExchangeData& data) OVERRIDE;
virtual int OnDragUpdated(const ui::DropTargetEvent& event) OVERRIDE;
virtual void OnDragExited() OVERRIDE;
virtual int OnPerformDrop(const ui::DropTargetEvent& event) OVERRIDE;
virtual void OnDragDone() OVERRIDE;
virtual bool OnKeyReleased(const ui::KeyEvent& event) OVERRIDE;
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
virtual void OnFocus() OVERRIDE;
virtual void OnBlur() OVERRIDE;
virtual void OnNativeThemeChanged(const ui::NativeTheme* theme) OVERRIDE;
// ui::TouchEditable overrides:
virtual void SelectRect(const gfx::Point& start,
const gfx::Point& end) OVERRIDE;
virtual void MoveCaretTo(const gfx::Point& point) OVERRIDE;
virtual void GetSelectionEndPoints(gfx::Rect* p1, gfx::Rect* p2) OVERRIDE;
virtual gfx::Rect GetBounds() OVERRIDE;
virtual gfx::NativeView GetNativeView() OVERRIDE;
virtual void ConvertPointToScreen(gfx::Point* point) OVERRIDE;
virtual void ConvertPointFromScreen(gfx::Point* point) OVERRIDE;
virtual bool DrawsHandles() OVERRIDE;
virtual void OpenContextMenu(const gfx::Point& anchor) OVERRIDE;
// ContextMenuController overrides:
virtual void ShowContextMenuForView(View* source,
const gfx::Point& point,
ui::MenuSourceType source_type) OVERRIDE;
// Overridden from DragController:
virtual void WriteDragDataForView(View* sender,
const gfx::Point& press_pt,
ui::OSExchangeData* data) OVERRIDE;
virtual int GetDragOperationsForView(View* sender,
const gfx::Point& p) OVERRIDE;
virtual bool CanStartDragForView(View* sender,
const gfx::Point& press_pt,
const gfx::Point& p) OVERRIDE;
// NativeTextfieldWrapper overrides:
virtual string16 GetText() const OVERRIDE;
virtual void UpdateText() OVERRIDE;
virtual void AppendText(const string16& text) OVERRIDE;
virtual void InsertOrReplaceText(const string16& text) OVERRIDE;
virtual base::i18n::TextDirection GetTextDirection() const OVERRIDE;
virtual string16 GetSelectedText() const OVERRIDE;
virtual void SelectAll(bool reversed) OVERRIDE;
virtual void ClearSelection() OVERRIDE;
virtual void UpdateBorder() OVERRIDE;
virtual void UpdateTextColor() OVERRIDE;
virtual void UpdateBackgroundColor() OVERRIDE;
virtual void UpdateReadOnly() OVERRIDE;
virtual void UpdateFont() OVERRIDE;
virtual void UpdateIsObscured() OVERRIDE;
virtual void UpdateEnabled() OVERRIDE;
virtual gfx::Insets CalculateInsets() OVERRIDE;
virtual void UpdateHorizontalMargins() OVERRIDE;
virtual void UpdateVerticalMargins() OVERRIDE;
virtual void UpdateVerticalAlignment() OVERRIDE;
virtual bool SetFocus() OVERRIDE;
virtual View* GetView() OVERRIDE;
virtual gfx::NativeView GetTestingHandle() const OVERRIDE;
virtual bool IsIMEComposing() const OVERRIDE;
virtual ui::Range GetSelectedRange() const OVERRIDE;
virtual void SelectRange(const ui::Range& range) OVERRIDE;
virtual gfx::SelectionModel GetSelectionModel() const OVERRIDE;
virtual void SelectSelectionModel(const gfx::SelectionModel& sel) OVERRIDE;
virtual size_t GetCursorPosition() const OVERRIDE;
virtual bool GetCursorEnabled() const OVERRIDE;
virtual void SetCursorEnabled(bool enabled) OVERRIDE;
virtual bool HandleKeyPressed(const ui::KeyEvent& e) OVERRIDE;
virtual bool HandleKeyReleased(const ui::KeyEvent& e) OVERRIDE;
virtual void HandleFocus() OVERRIDE;
virtual void HandleBlur() OVERRIDE;
virtual ui::TextInputClient* GetTextInputClient() OVERRIDE;
virtual void SetColor(SkColor value) OVERRIDE;
virtual void ApplyColor(SkColor value, const ui::Range& range) OVERRIDE;
virtual void SetStyle(gfx::TextStyle style, bool value) OVERRIDE;
virtual void ApplyStyle(gfx::TextStyle style,
bool value,
const ui::Range& range) OVERRIDE;
virtual void ClearEditHistory() OVERRIDE;
virtual int GetFontHeight() OVERRIDE;
virtual int GetTextfieldBaseline() const OVERRIDE;
virtual int GetWidthNeededForText() const OVERRIDE;
virtual void ExecuteTextCommand(int command_id) OVERRIDE;
virtual bool HasTextBeingDragged() OVERRIDE;
// ui::SimpleMenuModel::Delegate overrides
virtual bool IsCommandIdChecked(int command_id) const OVERRIDE;
virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE;
virtual bool GetAcceleratorForCommandId(
int command_id,
ui::Accelerator* accelerator) OVERRIDE;
virtual bool IsItemForCommandIdDynamic(int command_id) const OVERRIDE;
virtual string16 GetLabelForCommandId(int command_id) const OVERRIDE;
virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE;
// class name of internal
static const char kViewClassName[];
protected:
// View override.
virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE;
private:
friend class NativeTextfieldViewsTest;
friend class TouchSelectionControllerImplTest;
// Overridden from ui::TextInputClient:
virtual void SetCompositionText(
const ui::CompositionText& composition) OVERRIDE;
virtual void ConfirmCompositionText() OVERRIDE;
virtual void ClearCompositionText() OVERRIDE;
virtual void InsertText(const string16& text) OVERRIDE;
virtual void InsertChar(char16 ch, int flags) OVERRIDE;
virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE;
virtual ui::TextInputType GetTextInputType() const OVERRIDE;
virtual ui::TextInputMode GetTextInputMode() const OVERRIDE;
virtual bool CanComposeInline() const OVERRIDE;
virtual gfx::Rect GetCaretBounds() OVERRIDE;
virtual bool GetCompositionCharacterBounds(uint32 index,
gfx::Rect* rect) OVERRIDE;
virtual bool HasCompositionText() OVERRIDE;
virtual bool GetTextRange(ui::Range* range) OVERRIDE;
virtual bool GetCompositionTextRange(ui::Range* range) OVERRIDE;
virtual bool GetSelectionRange(ui::Range* range) OVERRIDE;
virtual bool SetSelectionRange(const ui::Range& range) OVERRIDE;
virtual bool DeleteRange(const ui::Range& range) OVERRIDE;
virtual bool GetTextFromRange(const ui::Range& range,
string16* text) OVERRIDE;
virtual void OnInputMethodChanged() OVERRIDE;
virtual bool ChangeTextDirectionAndLayoutAlignment(
base::i18n::TextDirection direction) OVERRIDE;
virtual void ExtendSelectionAndDelete(size_t before, size_t after) OVERRIDE;
virtual void EnsureCaretInRect(const gfx::Rect& rect) OVERRIDE;
// Overridden from TextfieldViewsModel::Delegate:
virtual void OnCompositionTextConfirmedOrCleared() OVERRIDE;
// Returns the TextfieldViewsModel's text/cursor/selection rendering model.
gfx::RenderText* GetRenderText() const;
// Converts |text| according to textfield style, e.g. lower case if
// |textfield_| has STYLE_LOWERCASE style.
string16 GetTextForDisplay(const string16& text);
// Updates any colors that have not been explicitly set from the theme.
void UpdateColorsFromTheme(const ui::NativeTheme* theme);
// A callback function to periodically update the cursor state.
void UpdateCursor();
// Repaint the cursor.
void RepaintCursor();
// Update the cursor_bounds and text_offset.
void UpdateCursorBoundsAndTextOffset(size_t cursor_pos, bool insert_mode);
void PaintTextAndCursor(gfx::Canvas* canvas);
// Handle the keyevent.
bool HandleKeyEvent(const ui::KeyEvent& key_event);
// Helper function to call MoveCursorTo on the TextfieldViewsModel.
bool MoveCursorTo(const gfx::Point& point, bool select);
// Utility function to inform the parent textfield (and its controller if any)
// that the text in the textfield has changed.
void PropagateTextChange();
// Does necessary updates when the text and/or the position of the cursor
// changed.
void UpdateAfterChange(bool text_changed, bool cursor_changed);
// Utility function to prepare the context menu.
void UpdateContextMenu();
// Convenience method to call InputMethod::OnTextInputTypeChanged();
void OnTextInputTypeChanged();
// Convenience method to call InputMethod::OnCaretBoundsChanged();
void OnCaretBoundsChanged();
// Convenience method to call TextfieldController::OnBeforeUserAction();
void OnBeforeUserAction();
// Convenience method to call TextfieldController::OnAfterUserAction();
void OnAfterUserAction();
// Calls |model_->Cut()| and notifies TextfieldController on success.
bool Cut();
// Calls |model_->Copy()| and notifies TextfieldController on success.
bool Copy();
// Calls |model_->Paste()| and calls TextfieldController::ContentsChanged()
// explicitly if paste succeeded.
bool Paste();
// Tracks the mouse clicks for single/double/triple clicks.
void TrackMouseClicks(const ui::MouseEvent& event);
// Handles mouse press events.
void HandleMousePressEvent(const ui::MouseEvent& event);
// Returns true if the current text input type allows access by the IME.
bool ImeEditingAllowed() const;
// Returns true if distance between |event| and |last_click_location_|
// exceeds the drag threshold.
bool ExceededDragThresholdFromLastClickLocation(const ui::MouseEvent& event);
// Checks if a char is ok to be inserted into the textfield. The |ch| is a
// modified character, i.e., modifiers took effect when generating this char.
static bool ShouldInsertChar(char16 ch, int flags);
void CreateTouchSelectionControllerAndNotifyIt();
// Platform specific gesture event handling.
void PlatformGestureEventHandling(const ui::GestureEvent* event);
// Reveals the obscured char at |index| for the given |duration|. If |index|
// is -1, existing revealed index will be cleared.
void RevealObscuredChar(int index, const base::TimeDelta& duration);
// The parent textfield, the owner of this object.
Textfield* textfield_;
// The text model.
scoped_ptr<TextfieldViewsModel> model_;
// The focusable border. This is always non-NULL, but may not actually be
// drawn. If it is not drawn, then by default it's also zero-sized unless the
// Textfield has explicitly-set margins.
FocusableBorder* text_border_;
// The textfield's text and drop cursor visibility.
bool is_cursor_visible_;
// The drop cursor is a visual cue for where dragged text will be dropped.
bool is_drop_cursor_visible_;
// Position of the drop cursor, if it is visible.
gfx::SelectionModel drop_cursor_position_;
// True if InputMethod::CancelComposition() should not be called.
bool skip_input_method_cancel_composition_;
// Is the user potentially dragging and dropping from this view?
bool initiating_drag_;
// A runnable method factory for callback to update the cursor.
base::WeakPtrFactory<NativeTextfieldViews> cursor_timer_;
// State variables used to track double and triple clicks.
size_t aggregated_clicks_;
base::TimeDelta last_click_time_;
gfx::Point last_click_location_;
ui::Range double_click_word_;
// Context menu and its content list for the textfield.
scoped_ptr<ui::SimpleMenuModel> context_menu_contents_;
scoped_ptr<views::MenuModelAdapter> context_menu_delegate_;
scoped_ptr<views::MenuRunner> context_menu_runner_;
scoped_ptr<ui::TouchSelectionController> touch_selection_controller_;
// A timer to control the duration of showing the last typed char in
// obscured text. When the timer is running, the last typed char is shown
// and when the time expires, the last typed char is obscured.
base::OneShotTimer<NativeTextfieldViews> obscured_reveal_timer_;
DISALLOW_COPY_AND_ASSIGN(NativeTextfieldViews);
};
} // namespace views
#endif // UI_VIEWS_CONTROLS_TEXTFIELD_NATIVE_TEXTFIELD_VIEWS_H_