siyao
4 年前
当前提交
bea46202
共有 14 个文件被更改,包括 684 次插入 和 118 次删除
-
4com.unity.uiwidgets/Runtime/cupertino/text_field.cs
-
4com.unity.uiwidgets/Runtime/external/simplejson/SimpleJSON.cs
-
7com.unity.uiwidgets/Runtime/services/message_codecs.cs
-
121com.unity.uiwidgets/Runtime/services/platform_channel.cs
-
44com.unity.uiwidgets/Runtime/services/raw_keyboard.cs
-
8com.unity.uiwidgets/Runtime/services/system_channels.cs
-
214com.unity.uiwidgets/Runtime/services/text_input.cs
-
4com.unity.uiwidgets/Runtime/ui2/channel_buffers.cs
-
2engine/Build.bee.cs
-
24engine/src/shell/platform/unity/windows/text_input_plugin.cc
-
5engine/src/shell/platform/unity/windows/text_input_plugin.h
-
72Samples/UIWidgetsSamples_2019_4/Assets/Script/TextField.cs
-
191engine/src/shell/platform/common/cpp/text_input_model.cc
-
102engine/src/shell/platform/common/cpp/text_input_model.h
|
|||
using Unity.UIWidgets.engine2; |
|||
using Unity.UIWidgets.widgets; |
|||
using ui_ = Unity.UIWidgets.widgets.ui_; |
|||
using Unity.UIWidgets.cupertino; |
|||
|
|||
namespace UIWidgetsSample |
|||
{ |
|||
public class TextField : UIWidgetsPanel |
|||
{ |
|||
protected void OnEnable() |
|||
{ |
|||
base.OnEnable(); |
|||
} |
|||
|
|||
protected override void main() |
|||
{ |
|||
ui_.runApp(new MyApp()); |
|||
} |
|||
|
|||
class MyApp : StatelessWidget |
|||
{ |
|||
public override Widget build(BuildContext context) |
|||
{ |
|||
return new CupertinoApp( |
|||
home: new HomeScreen() |
|||
); |
|||
} |
|||
} |
|||
|
|||
class HomeScreen : StatelessWidget |
|||
{ |
|||
public override Widget build(BuildContext context) |
|||
{ |
|||
return new HomeScreen3(); |
|||
} |
|||
} |
|||
|
|||
public class HomeScreen3 : StatelessWidget |
|||
{ |
|||
public override Widget build(BuildContext context) |
|||
{ |
|||
return new CupertinoPageScaffold( |
|||
child: new Center( |
|||
child: new MyPrefilledText() |
|||
|
|||
) |
|||
); |
|||
} |
|||
} |
|||
|
|||
public class MyPrefilledText : StatefulWidget |
|||
{ |
|||
public override State createState() => new _MyPrefilledTextState(); |
|||
} |
|||
|
|||
class _MyPrefilledTextState : State<MyPrefilledText> |
|||
{ |
|||
TextEditingController _textController; |
|||
|
|||
public override void initState() |
|||
{ |
|||
base.initState(); |
|||
_textController = new TextEditingController(text: "initial text"); |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) |
|||
{ |
|||
return new CupertinoTextField(controller: _textController); |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
// Copyright 2013 The UIWidgets 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 "shell/platform/common/cpp/text_input_model.h"
|
|||
|
|||
#include <codecvt>
|
|||
#include <iostream>
|
|||
#include <locale>
|
|||
|
|||
// TODO(awdavies): Need to fix this regarding issue #47.
|
|||
static constexpr char kComposingBaseKey[] = "composingBase"; |
|||
|
|||
static constexpr char kComposingExtentKey[] = "composingExtent"; |
|||
|
|||
static constexpr char kSelectionAffinityKey[] = "selectionAffinity"; |
|||
static constexpr char kAffinityDownstream[] = "TextAffinity.downstream"; |
|||
|
|||
static constexpr char kSelectionBaseKey[] = "selectionBase"; |
|||
static constexpr char kSelectionExtentKey[] = "selectionExtent"; |
|||
|
|||
static constexpr char kSelectionIsDirectionalKey[] = "selectionIsDirectional"; |
|||
|
|||
static constexpr char kTextKey[] = "text"; |
|||
|
|||
// Input client configuration keys.
|
|||
static constexpr char kTextInputAction[] = "inputAction"; |
|||
static constexpr char kTextInputType[] = "inputType"; |
|||
static constexpr char kTextInputTypeName[] = "name"; |
|||
|
|||
#if defined(_MSC_VER)
|
|||
// TODO(naifu): This temporary code is to solve link error.(VS2015/2017)
|
|||
// https://social.msdn.microsoft.com/Forums/vstudio/en-US/8f40dcd8-c67f-4eba-9134-a19b9178e481/vs-2015-rc-linker-stdcodecvt-error
|
|||
std::locale::id std::codecvt<char32_t, char, _Mbstatet>::id; |
|||
#endif // defined(_MSC_VER)
|
|||
|
|||
namespace uiwidgets { |
|||
|
|||
TextInputModel::TextInputModel(int client_id, const rapidjson::Value& config) |
|||
: client_id_(client_id), |
|||
selection_base_(text_.begin()), |
|||
selection_extent_(text_.begin()) { |
|||
// TODO: Improve error handling during refactoring; this is just minimal
|
|||
// checking to avoid asserts since RapidJSON is stricter than jsoncpp.
|
|||
if (config.IsObject()) { |
|||
auto input_action = config.FindMember(kTextInputAction); |
|||
if (input_action != config.MemberEnd() && input_action->value.IsString()) { |
|||
input_action_ = input_action->value.GetString(); |
|||
} |
|||
auto input_type_info = config.FindMember(kTextInputType); |
|||
if (input_type_info != config.MemberEnd() && |
|||
input_type_info->value.IsObject()) { |
|||
auto input_type = input_type_info->value.FindMember(kTextInputTypeName); |
|||
if (input_type != input_type_info->value.MemberEnd() && |
|||
input_type->value.IsString()) { |
|||
input_type_ = input_type->value.GetString(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
TextInputModel::~TextInputModel() = default; |
|||
|
|||
bool TextInputModel::SetEditingState(size_t selection_base, |
|||
size_t selection_extent, |
|||
const std::string& text) { |
|||
if (selection_base > selection_extent) { |
|||
return false; |
|||
} |
|||
// Only checks extent since it is implicitly greater-than-or-equal-to base.
|
|||
if (selection_extent > text.size()) { |
|||
return false; |
|||
} |
|||
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> utf32conv; |
|||
text_ = utf32conv.from_bytes(text); |
|||
selection_base_ = text_.begin() + selection_base; |
|||
selection_extent_ = text_.begin() + selection_extent; |
|||
return true; |
|||
} |
|||
|
|||
void TextInputModel::DeleteSelected() { |
|||
selection_base_ = text_.erase(selection_base_, selection_extent_); |
|||
// Moves extent back to base, so that it is a single cursor placement again.
|
|||
selection_extent_ = selection_base_; |
|||
} |
|||
|
|||
void TextInputModel::AddCharacter(char32_t c) { |
|||
if (selection_base_ != selection_extent_) { |
|||
DeleteSelected(); |
|||
} |
|||
selection_extent_ = text_.insert(selection_extent_, c); |
|||
selection_extent_++; |
|||
selection_base_ = selection_extent_; |
|||
} |
|||
|
|||
bool TextInputModel::Backspace() { |
|||
if (selection_base_ != selection_extent_) { |
|||
DeleteSelected(); |
|||
return true; |
|||
} |
|||
if (selection_base_ != text_.begin()) { |
|||
selection_base_ = text_.erase(selection_base_ - 1, selection_base_); |
|||
selection_extent_ = selection_base_; |
|||
return true; |
|||
} |
|||
return false; // No edits happened.
|
|||
} |
|||
|
|||
bool TextInputModel::Delete() { |
|||
if (selection_base_ != selection_extent_) { |
|||
DeleteSelected(); |
|||
return true; |
|||
} |
|||
if (selection_base_ != text_.end()) { |
|||
selection_base_ = text_.erase(selection_base_, selection_base_ + 1); |
|||
selection_extent_ = selection_base_; |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
void TextInputModel::MoveCursorToBeginning() { |
|||
selection_base_ = text_.begin(); |
|||
selection_extent_ = text_.begin(); |
|||
} |
|||
|
|||
void TextInputModel::MoveCursorToEnd() { |
|||
selection_base_ = text_.end(); |
|||
selection_extent_ = text_.end(); |
|||
} |
|||
|
|||
bool TextInputModel::MoveCursorForward() { |
|||
// If about to move set to the end of the highlight (when not selecting).
|
|||
if (selection_base_ != selection_extent_) { |
|||
selection_base_ = selection_extent_; |
|||
return true; |
|||
} |
|||
// If not at the end, move the extent forward.
|
|||
if (selection_extent_ != text_.end()) { |
|||
selection_extent_++; |
|||
selection_base_++; |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
bool TextInputModel::MoveCursorBack() { |
|||
// If about to move set to the beginning of the highlight
|
|||
// (when not selecting).
|
|||
if (selection_base_ != selection_extent_) { |
|||
selection_extent_ = selection_base_; |
|||
return true; |
|||
} |
|||
// If not at the start, move the beginning backward.
|
|||
if (selection_base_ != text_.begin()) { |
|||
selection_base_--; |
|||
selection_extent_--; |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
std::unique_ptr<rapidjson::Document> TextInputModel::GetState() const { |
|||
// TODO(stuartmorgan): Move client_id out up to the plugin so that this
|
|||
// function just returns the editing state.
|
|||
auto args = std::make_unique<rapidjson::Document>(rapidjson::kArrayType); |
|||
auto& allocator = args->GetAllocator(); |
|||
args->PushBack(client_id_, allocator); |
|||
|
|||
rapidjson::Value editing_state(rapidjson::kObjectType); |
|||
// TODO(awdavies): Most of these are hard-coded for now.
|
|||
editing_state.AddMember(kComposingBaseKey, -1, allocator); |
|||
editing_state.AddMember(kComposingExtentKey, -1, allocator); |
|||
editing_state.AddMember(kSelectionAffinityKey, kAffinityDownstream, |
|||
allocator); |
|||
editing_state.AddMember(kSelectionBaseKey, |
|||
static_cast<int>(selection_base_ - text_.begin()), |
|||
allocator); |
|||
editing_state.AddMember(kSelectionExtentKey, |
|||
static_cast<int>(selection_extent_ - text_.begin()), |
|||
allocator); |
|||
editing_state.AddMember(kSelectionIsDirectionalKey, false, allocator); |
|||
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> utf8conv; |
|||
editing_state.AddMember( |
|||
kTextKey, rapidjson::Value(utf8conv.to_bytes(text_), allocator).Move(), |
|||
allocator); |
|||
args->PushBack(editing_state, allocator); |
|||
return args; |
|||
} |
|||
|
|||
} // namespace uiwidgets
|
|
|||
// Copyright 2013 The UIWidgets 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 UIWIDGETS_SHELL_PLATFORM_CPP_TEXT_INPUT_MODEL_H_ |
|||
#define UIWIDGETS_SHELL_PLATFORM_CPP_TEXT_INPUT_MODEL_H_ |
|||
|
|||
#include <memory> |
|||
#include <string> |
|||
|
|||
#include "rapidjson/document.h" |
|||
|
|||
namespace uiwidgets { |
|||
// Handles underlying text input state, using a simple ASCII model. |
|||
// |
|||
// Ignores special states like "insert mode" for now. |
|||
class TextInputModel { |
|||
public: |
|||
TextInputModel(int client_id, const rapidjson::Value& config); |
|||
virtual ~TextInputModel(); |
|||
|
|||
// Attempts to set the text state. |
|||
// |
|||
// Returns false if the state is not valid (base or extent are out of |
|||
// bounds, or base is less than extent). |
|||
bool SetEditingState(size_t selection_base, |
|||
size_t selection_extent, |
|||
const std::string& text); |
|||
|
|||
// Adds a character. |
|||
// |
|||
// Either appends after the cursor (when selection base and extent are the |
|||
// same), or deletes the selected characters, replacing the text with the |
|||
// character specified. |
|||
void AddCharacter(char32_t c); |
|||
|
|||
// Deletes either the selection, or one character ahead of the cursor. |
|||
// |
|||
// Deleting one character ahead of the cursor occurs when the selection base |
|||
// and extent are the same. |
|||
// |
|||
// Returns true if any deletion actually occurred. |
|||
bool Delete(); |
|||
|
|||
// Deletes either the selection, or one character behind the cursor. |
|||
// |
|||
// Deleting one character behind the cursor occurs when the selection base |
|||
// and extent are the same. |
|||
// |
|||
// Returns true if any deletion actually occurred. |
|||
bool Backspace(); |
|||
|
|||
// Attempts to move the cursor backward. |
|||
// |
|||
// Returns true if the cursor could be moved. Changes base and extent to be |
|||
// equal to either the extent (if extent is at the end of the string), or |
|||
// for extent to be equal to |
|||
bool MoveCursorBack(); |
|||
|
|||
// Attempts to move the cursor forward. |
|||
// |
|||
// Returns true if the cursor could be moved. |
|||
bool MoveCursorForward(); |
|||
|
|||
// Attempts to move the cursor to the beginning. |
|||
// |
|||
// Returns true if the cursor could be moved. |
|||
void MoveCursorToBeginning(); |
|||
|
|||
// Attempts to move the cursor to the back. |
|||
// |
|||
// Returns true if the cursor could be moved. |
|||
void MoveCursorToEnd(); |
|||
|
|||
// Returns the state in the form of a platform message. |
|||
std::unique_ptr<rapidjson::Document> GetState() const; |
|||
|
|||
// Id of the text input client. |
|||
int client_id() const { return client_id_; } |
|||
|
|||
// Keyboard type of the client. See available options: |
|||
// https://docs.uiwidgets.io/uiwidgets/services/TextInputType-class.html |
|||
std::string input_type() const { return input_type_; } |
|||
|
|||
// An action requested by the user on the input client. See available options: |
|||
// https://docs.uiwidgets.io/uiwidgets/services/TextInputAction-class.html |
|||
std::string input_action() const { return input_action_; } |
|||
|
|||
private: |
|||
void DeleteSelected(); |
|||
|
|||
std::u32string text_; |
|||
int client_id_; |
|||
std::string input_type_; |
|||
std::string input_action_; |
|||
std::u32string::iterator selection_base_; |
|||
std::u32string::iterator selection_extent_; |
|||
}; |
|||
|
|||
} // namespace uiwidgets |
|||
|
|||
#endif // UIWIDGETS_SHELL_PLATFORM_CPP_TEXT_INPUT_MODEL_H_ |
撰写
预览
正在加载...
取消
保存
Reference in new issue