fix and improve the internal handle of focus change

enhanced textbox behavior of focus change
This commit is contained in:
Jinhao 2016-02-27 02:02:29 +08:00
parent a839cf8deb
commit 569eb49a5c
14 changed files with 290 additions and 130 deletions

View File

@ -95,6 +95,7 @@ namespace nana
undo = substitute,
//System Code for OS
os_tab = 0x09,
os_shift = 0x10,
os_ctrl = 0x11,
os_pageup = 0x21, os_pagedown,

View File

@ -424,9 +424,18 @@ namespace nana
struct arg_focus : public event_arg
{
::nana::window window_handle; ///< A handle to the event window
::nana::native_window_type receiver; ///< it is a native window handle, and specified which window receives focus
bool getting; ///< the window received focus?
/// A constant to indicate how keyboard focus emitted.
enum class reason
{
general, ///< the focus is received by OS native window manager.
tabstop, ///< the focus is received by pressing tab.
mouse_press ///< the focus is received by pressing a mouse button.
};
::nana::window window_handle; ///< A handle to the event window
::nana::native_window_type receiver; ///< it is a native window handle, and specified which window receives focus
bool getting; ///< the window received focus?
reason focus_reason; ///< determines how the widget receives keyboard focus, it is ignored when 'getting' is equal to false
};
struct arg_keyboard : public event_arg

View File

@ -117,8 +117,9 @@ namespace nana{
nana::paint::graphics root_graph;
shortkey_container shortkeys;
struct condition_tag
struct condition_rep
{
bool ignore_tab{ false }; //ignore tab when the focus is changed by pressing tab.
core_window_t* pressed{nullptr}; //The handle to a window which has been pressed by pressing left button of mouse.
core_window_t* pressed_by_space{ nullptr }; //The handle to a window which has been pressed by pressing spacebar.
core_window_t* hovered{nullptr}; //the latest window that mouse moved

View File

@ -136,7 +136,7 @@ namespace detail
std::vector<core_window_t*> get_children(core_window_t*) const;
bool set_parent(core_window_t* wd, core_window_t* new_parent);
core_window_t* set_focus(core_window_t*, bool root_has_been_focused);
core_window_t* set_focus(core_window_t*, bool root_has_been_focused, arg_focus::reason);
core_window_t* capture_redirect(core_window_t*);
void capture_ignore_children(bool ignore);

View File

@ -283,8 +283,14 @@ namespace API
cursor window_cursor(window);
void activate_window(window);
/// Determines whether the specified window will get the keyboard focus when its root window gets native system focus.
bool is_focus_ready(window);
/// Returns the current keyboard focus window.
window focus_window();
/// Sets the keyboard focus for a specified window.
void focus_window(window);
window capture_window();

View File

@ -229,6 +229,9 @@ namespace nana{ namespace widgets
/// Returns text position of each line that currently displays on screen
const std::vector<upoint>& text_position() const;
void focus_behavior(text_focus_behavior);
void select_behavior(bool move_to_end);
public:
void draw_corner();
void render(bool focused);
@ -249,6 +252,8 @@ namespace nana{ namespace widgets
const upoint& caret() const;
point caret_screen_pos() const;
bool scroll(bool upwards, bool vertical);
bool focus_changed(const arg_focus&);
bool mouse_enter(bool);
bool mouse_move(bool left_button, const point& screen_pos);
bool mouse_pressed(const arg_mouse& arg);
@ -353,10 +358,13 @@ namespace nana{ namespace widgets
struct selection
{
enum mode_selection_t{mode_no_selected, mode_mouse_selected, mode_method_selected};
enum class mode{ no_selected, mouse_selected, method_selected };
mode_selection_t mode_selection;
text_focus_behavior behavior;
bool move_to_end;
mode mode_selection;
bool dragged;
bool ignore_press;
nana::upoint a, b;
}select_;

View File

@ -11,6 +11,15 @@ namespace nana
{
namespace skeletons
{
enum class text_focus_behavior
{
none,
select,
select_if_tabstop,
select_if_click,
select_if_tabstop_or_click
};
//forward declaration
class text_editor;

View File

@ -98,6 +98,8 @@ namespace nana
:public widget_object<category::widget_tag, drawerbase::textbox::drawer, drawerbase::textbox::textbox_events, ::nana::widgets::skeletons::text_editor_scheme>
{
public:
using text_focus_behavior = widgets::skeletons::text_focus_behavior;
using text_positions = std::vector<upoint>;
/// The default constructor without creating the widget.
textbox();
@ -207,6 +209,14 @@ namespace nana
/// Returns the height of line in pixels
unsigned line_pixels() const;
/// Sets the behavior when textbox gets focus.
void focus_behavior(text_focus_behavior);
/// Sets the caret move behavior when the content of textbox is selected.
/// E.g. Whether caret moves to left of selected content or moves to left of last position when left arrow key is pressed.
/// @param move_to_end determines whether to move caret to left of selected_content or to left of last position.
void select_behavior(bool move_to_end);
protected:
//Overrides widget's virtual functions
native_string_type _m_caption() const throw() override;

View File

@ -255,7 +255,7 @@ namespace detail
if ((!wd) && pre)
{
internal_scope_guard lock;
wd_manager().set_focus(pre, false);
wd_manager().set_focus(pre, false, arg_focus::reason::general);
wd_manager().update(pre, true, false);
}
}
@ -479,6 +479,7 @@ namespace detail
arg.window_handle = reinterpret_cast<window>(wd);
arg.receiver = recv;
arg.getting = getting;
arg.focus_reason = arg_focus::reason::general;
}
void assign_arg(arg_wheel& arg, basic_window* wd, const XEvent& evt)
@ -701,7 +702,7 @@ namespace detail
arg.receiver = native_window;
arg.getting = true;
if(!brock.emit(event_code::focus, focus, arg, true, &context))
brock.wd_manager().set_focus(msgwnd, true);
brock.wd_manager().set_focus(msgwnd, true, arg_focus::reason::general);
}
break;
case FocusOut:
@ -765,7 +766,7 @@ namespace detail
if (new_focus && !new_focus->flags.ignore_mouse_focus)
{
context.event_window = new_focus;
auto kill_focus = brock.wd_manager().set_focus(new_focus, false);
auto kill_focus = brock.wd_manager().set_focus(new_focus, false, arg_focus::reason::mouse_press);
if (kill_focus != new_focus)
brock.wd_manager().do_lazy_refresh(kill_focus, false);
}
@ -1048,7 +1049,8 @@ namespace detail
auto tstop_wd = wd_manager.tabstop(msgwnd, !argkey.shift);
if (tstop_wd)
{
wd_manager.set_focus(tstop_wd, false);
root_runtime->condition.ignore_tab = true;
wd_manager.set_focus(tstop_wd, false, arg_focus::reason::tabstop);
wd_manager.do_lazy_refresh(msgwnd, false);
wd_manager.do_lazy_refresh(tstop_wd, true);
}
@ -1144,8 +1146,8 @@ namespace detail
arg.ignore = false;
arg.key = charbuf[i];
// When tab is pressed, only tab-eating mode is allowed
if ((keyboard::tab == arg.key) && !(msgwnd->flags.tab & tab_type::eating))
//Only accept tab when it is not ignored.
if ((keyboard::tab == arg.key) && root_runtime->condition.ignore_tab)
continue;
if(context.is_alt_pressed)
@ -1185,52 +1187,61 @@ namespace detail
nana::detail::platform_spec::instance().write_keystate(xevent.xkey);
{
auto os_code = os_code_from_keysym(::XLookupKeysym(&xevent.xkey, 0));
if(keyboard::alt != os_code)
if(keyboard::alt != os_code) //MUST NOT BE AN ALT
{
if(0x11 == os_code)
context.is_ctrl_pressed = false;
msgwnd = brock.focus();
if(msgwnd)
{
if(msgwnd == pressed_wd_space)
{
msgwnd->flags.action = mouse_action::normal;
if (('\t' == os_code) && root_runtime->condition.ignore_tab)
{
root_runtime->condition.ignore_tab = false;
}
else
{
msgwnd = brock.focus();
if(msgwnd)
{
if(msgwnd == pressed_wd_space)
{
msgwnd->flags.action = mouse_action::normal;
arg_click click_arg;
click_arg.mouse_args = nullptr;
click_arg.window_handle = reinterpret_cast<window>(msgwnd);
arg_click click_arg;
click_arg.mouse_args = nullptr;
click_arg.window_handle = reinterpret_cast<window>(msgwnd);
auto retain = msgwnd->together.events_ptr;
if (brock.emit(event_code::click, msgwnd, click_arg, true, &context))
{
arg_mouse arg;
arg.alt = false;
arg.button = ::nana::mouse::left_button;
arg.ctrl = false;
arg.evt_code = event_code::mouse_up;
arg.left_button = true;
arg.mid_button = false;
arg.pos.x = 0;
arg.pos.y = 0;
arg.window_handle = reinterpret_cast<window>(msgwnd);
auto retain = msgwnd->together.events_ptr;
if (brock.emit(event_code::click, msgwnd, click_arg, true, &context))
{
arg_mouse arg;
arg.alt = false;
arg.button = ::nana::mouse::left_button;
arg.ctrl = false;
arg.evt_code = event_code::mouse_up;
arg.left_button = true;
arg.mid_button = false;
arg.pos.x = 0;
arg.pos.y = 0;
arg.window_handle = reinterpret_cast<window>(msgwnd);
emit_drawer(&drawer::mouse_up, msgwnd, arg, &context);
brock.wd_manager().do_lazy_refresh(msgwnd, false);
}
pressed_wd_space = nullptr;
}
else
{
arg_keyboard arg;
arg.evt_code = event_code::key_release;
arg.window_handle = reinterpret_cast<window>(msgwnd);
arg.ignore = false;
arg.key = os_code;
brock.get_key_state(arg);
brock.emit(event_code::key_release, msgwnd, arg, true, &context);
}
}
emit_drawer(&drawer::mouse_up, msgwnd, arg, &context);
brock.wd_manager().do_lazy_refresh(msgwnd, false);
}
pressed_wd_space = nullptr;
}
else
{
arg_keyboard arg;
arg.evt_code = event_code::key_release;
arg.window_handle = reinterpret_cast<window>(msgwnd);
arg.ignore = false;
arg.key = os_code;
brock.get_key_state(arg);
brock.emit(event_code::key_release, msgwnd, arg, true, &context);
}
}
}
if(os_code < keyboard::os_arrow_left || keyboard::os_arrow_down < os_code)
brock.delay_restore(2); //Restores while key release
@ -1245,7 +1256,7 @@ namespace detail
{
bool set_focus = (brock.focus() != msgwnd) && (!msgwnd->root_widget->flags.ignore_menubar_focus);
if (set_focus)
brock.wd_manager().set_focus(msgwnd, false);
brock.wd_manager().set_focus(msgwnd, false, arg_focus::reason::general);
arg_keyboard arg;
arg.evt_code = event_code::key_release;

View File

@ -549,6 +549,7 @@ namespace detail
arg.window_handle = reinterpret_cast<window>(wd);
arg.receiver = recv;
arg.getting = getting;
arg.focus_reason = arg_focus::reason::general;
}
void assign_arg(arg_wheel& arg, basic_window* wd, const parameter_decoder& pmdec)
@ -882,7 +883,7 @@ namespace detail
arg_focus arg;
assign_arg(arg, focus, native_window, true);
if (!brock.emit(event_code::focus, focus, arg, true, &context))
brock.wd_manager().set_focus(msgwnd, true);
brock.wd_manager().set_focus(msgwnd, true, arg_focus::reason::general);
}
def_window_proc = true;
break;
@ -922,7 +923,7 @@ namespace detail
{
if (msgwnd->flags.take_active && !msgwnd->flags.ignore_mouse_focus)
{
auto killed = brock.wd_manager().set_focus(msgwnd, false);
auto killed = brock.wd_manager().set_focus(msgwnd, false, arg_focus::reason::mouse_press);
if (killed != msgwnd)
brock.wd_manager().do_lazy_refresh(killed, false);
}
@ -964,7 +965,7 @@ namespace detail
auto new_focus = (msgwnd->flags.take_active ? msgwnd : msgwnd->other.active_window);
if (new_focus && (!new_focus->flags.ignore_mouse_focus))
{
auto kill_focus = brock.wd_manager().set_focus(new_focus, false);
auto kill_focus = brock.wd_manager().set_focus(new_focus, false, arg_focus::reason::mouse_press);
if (kill_focus != new_focus)
brock.wd_manager().do_lazy_refresh(kill_focus, false);
}
@ -1383,7 +1384,7 @@ namespace detail
bool set_focus = (brock.focus() != msgwnd) && (!msgwnd->root_widget->flags.ignore_menubar_focus);
if (set_focus)
brock.wd_manager().set_focus(msgwnd, false);
brock.wd_manager().set_focus(msgwnd, false, arg_focus::reason::general);
arg_keyboard arg;
arg.evt_code = event_code::key_release;
@ -1414,14 +1415,16 @@ namespace detail
if(msgwnd)
{
auto & wd_manager = brock.wd_manager();
if((VK_TAB == wParam) && (!msgwnd->visible || (false == (msgwnd->flags.tab & tab_type::eating)))) //Tab
if ((VK_TAB == wParam) && (!msgwnd->visible || (false == (msgwnd->flags.tab & tab_type::eating)))) //Tab
{
bool is_forward = (::GetKeyState(VK_SHIFT) >= 0);
auto tstop_wd = wd_manager.tabstop(msgwnd, is_forward);
if (tstop_wd)
{
wd_manager.set_focus(tstop_wd, false);
root_runtime->condition.ignore_tab = true;
wd_manager.set_focus(tstop_wd, false, arg_focus::reason::tabstop);
wd_manager.do_lazy_refresh(msgwnd, false);
wd_manager.do_lazy_refresh(tstop_wd, true);
}
@ -1479,8 +1482,10 @@ namespace detail
msgwnd = brock.focus();
if (msgwnd && msgwnd->flags.enabled)
{
// When tab is pressed, only tab-eating mode is allowed
if ((9 != wParam) || (msgwnd->flags.tab & tab_type::eating))
auto & wd_manager = brock.wd_manager();
//Only accept tab when it is not ignored.
if (VK_TAB != wParam || !root_runtime->condition.ignore_tab)
{
arg_keyboard arg;
arg.evt_code = event_code::key_char;
@ -1490,55 +1495,62 @@ namespace detail
arg.ignore = false;
msgwnd->together.events_ptr->key_char.emit(arg);
if ((false == arg.ignore) && brock.wd_manager().available(msgwnd))
if ((false == arg.ignore) && wd_manager.available(msgwnd))
brock.emit_drawer(event_code::key_char, msgwnd, arg, &context);
brock.wd_manager().do_lazy_refresh(msgwnd, false);
wd_manager.do_lazy_refresh(msgwnd, false);
}
}
return 0;
case WM_KEYUP:
if(wParam != VK_MENU) //MUST NOT BE AN ALT
{
msgwnd = brock.focus();
if(msgwnd)
if (VK_TAB == wParam && root_runtime->condition.ignore_tab)
{
if (msgwnd == pressed_wd_space)
root_runtime->condition.ignore_tab = false;
}
else
{
msgwnd = brock.focus();
if (msgwnd)
{
msgwnd->flags.action = mouse_action::normal;
arg_click click_arg;
click_arg.mouse_args = nullptr;
click_arg.window_handle = reinterpret_cast<window>(msgwnd);
auto retain = msgwnd->together.events_ptr;
if (brock.emit(event_code::click, msgwnd, click_arg, true, &context))
if (msgwnd == pressed_wd_space)
{
arg_mouse arg;
arg.alt = false;
arg.button = ::nana::mouse::left_button;
arg.ctrl = false;
arg.evt_code = event_code::mouse_up;
arg.left_button = true;
arg.mid_button = false;
arg.pos.x = 0;
arg.pos.y = 0;
arg.window_handle = reinterpret_cast<window>(msgwnd);
msgwnd->flags.action = mouse_action::normal;
emit_drawer(&drawer::mouse_up, msgwnd, arg, &context);
brock.wd_manager().do_lazy_refresh(msgwnd, false);
arg_click click_arg;
click_arg.mouse_args = nullptr;
click_arg.window_handle = reinterpret_cast<window>(msgwnd);
auto retain = msgwnd->together.events_ptr;
if (brock.emit(event_code::click, msgwnd, click_arg, true, &context))
{
arg_mouse arg;
arg.alt = false;
arg.button = ::nana::mouse::left_button;
arg.ctrl = false;
arg.evt_code = event_code::mouse_up;
arg.left_button = true;
arg.mid_button = false;
arg.pos.x = 0;
arg.pos.y = 0;
arg.window_handle = reinterpret_cast<window>(msgwnd);
emit_drawer(&drawer::mouse_up, msgwnd, arg, &context);
brock.wd_manager().do_lazy_refresh(msgwnd, false);
}
pressed_wd_space = nullptr;
}
else
{
arg_keyboard arg;
arg.evt_code = event_code::key_release;
arg.window_handle = reinterpret_cast<window>(msgwnd);
arg.key = static_cast<wchar_t>(wParam);
brock.get_key_state(arg);
arg.ignore = false;
brock.emit(event_code::key_release, msgwnd, arg, true, &context);
}
pressed_wd_space = nullptr;
}
else
{
arg_keyboard arg;
arg.evt_code = event_code::key_release;
arg.window_handle = reinterpret_cast<window>(msgwnd);
arg.key = static_cast<wchar_t>(wParam);
brock.get_key_state(arg);
arg.ignore = false;
brock.emit(event_code::key_release, msgwnd, arg, true, &context);
}
}
}
@ -1625,7 +1637,7 @@ namespace detail
if ((!wd) && pre && (pre->root != get_menu()))
{
internal_scope_guard lock;
wd_manager().set_focus(pre, false);
wd_manager().set_focus(pre, false, arg_focus::reason::general);
wd_manager().update(pre, true, false);
}
}

View File

@ -925,7 +925,7 @@ namespace detail
//set_focus
//@brief: set a keyboard focus to a window. this may fire a focus event.
window_manager::core_window_t* window_manager::set_focus(core_window_t* wd, bool root_has_been_focused)
window_manager::core_window_t* window_manager::set_focus(core_window_t* wd, bool root_has_been_focused, arg_focus::reason reason)
{
//Thread-Safe Required!
std::lock_guard<decltype(mutex_)> lock(mutex_);
@ -951,6 +951,7 @@ namespace detail
arg.getting = false;
arg.window_handle = reinterpret_cast<window>(prev_focus);
arg.receiver = wd->root;
arg.focus_reason = arg_focus::reason::general;
brock.emit(event_code::focus, prev_focus, arg, true, brock.get_thread_context());
}
@ -968,6 +969,7 @@ namespace detail
arg.window_handle = reinterpret_cast<window>(wd);
arg.getting = true;
arg.receiver = wd->root;
arg.focus_reason = reason;
brock.emit(event_code::focus, wd, arg, true, brock.get_thread_context());
if (!root_has_been_focused)

View File

@ -929,7 +929,7 @@ namespace API
void focus_window(window wd)
{
restrict::wd_manager().set_focus(reinterpret_cast<basic_window*>(wd), false);
restrict::wd_manager().set_focus(reinterpret_cast<basic_window*>(wd), false, arg_focus::reason::general);
restrict::wd_manager().update(reinterpret_cast<basic_window*>(wd), false, false);
}
@ -1171,7 +1171,7 @@ namespace API
window move_tabstop(window wd, bool next)
{
basic_window* ts_wd = restrict::wd_manager().tabstop(reinterpret_cast<basic_window*>(wd), next);
restrict::wd_manager().set_focus(ts_wd, false);
restrict::wd_manager().set_focus(ts_wd, false, arg_focus::reason::general);
restrict::wd_manager().update(ts_wd, false, false);
return reinterpret_cast<window>(ts_wd);
}

View File

@ -1289,7 +1289,11 @@ namespace nana{ namespace widgets
text_area_.tab_space = 4;
text_area_.scroll_pixels = 16;
text_area_.hscroll = text_area_.vscroll = 0;
select_.mode_selection = selection::mode_no_selected;
select_.behavior = text_focus_behavior::select_if_tabstop_or_click;
select_.move_to_end = false;
select_.mode_selection = selection::mode::no_selected;
select_.ignore_press = false;
select_.dragged = false;
API::create_caret(wd, 1, line_height());
@ -1348,11 +1352,13 @@ namespace nana{ namespace widgets
void text_editor::erase_keyword(const ::std::wstring& kw)
{
for (auto i = keywords_->kwbase.begin(); i != keywords_->kwbase.end(); ++i)
{
if (i->text == kw)
{
keywords_->kwbase.erase(i);
return;
}
}
}
void text_editor::set_accept(std::function<bool(char_type)> pred)
@ -1624,6 +1630,47 @@ namespace nana{ namespace widgets
return 0;
}
bool text_editor::focus_changed(const arg_focus& arg)
{
bool renderred = false;
if (arg.getting && (select_.a == select_.b)) //Do not change the selected text
{
bool select_all = false;
switch (select_.behavior)
{
case text_focus_behavior::select:
select_all = true;
break;
case text_focus_behavior::select_if_click:
select_all = (arg_focus::reason::mouse_press == arg.focus_reason);
break;
case text_focus_behavior::select_if_tabstop:
select_all = (arg_focus::reason::tabstop == arg.focus_reason);
break;
case text_focus_behavior::select_if_tabstop_or_click:
select_all = (arg_focus::reason::tabstop == arg.focus_reason || arg_focus::reason::mouse_press == arg.focus_reason);
default:
break;
}
if (select_all)
{
select(true);
move_caret_end();
renderred = true;
//If the text widget is focused by clicking mouse button, the selected text will be cancelled
//by the subsequent mouse down event. In this situation, the subsequent mouse down event should
//be ignored.
select_.ignore_press = (arg_focus::reason::mouse_press == arg.focus_reason);
}
}
show_caret(arg.getting);
reset_caret();
return renderred;
}
bool text_editor::mouse_enter(bool enter)
{
if((false == enter) && (false == text_area_.captured))
@ -1649,7 +1696,7 @@ namespace nana{ namespace widgets
auto caret_pos_before = caret();
mouse_caret(scrpos);
if(select_.mode_selection != selection::mode_no_selected)
if(select_.mode_selection != selection::mode::no_selected)
set_end_caret();
else if ((!select_.dragged) && (caret_pos_before != caret()))
select_.dragged = true;
@ -1664,8 +1711,11 @@ namespace nana{ namespace widgets
{
if (event_code::mouse_down == arg.evt_code)
{
if (!hit_text_area(arg.pos))
if (select_.ignore_press || (!hit_text_area(arg.pos)))
{
select_.ignore_press = false;
return false;
}
if (::nana::mouse::left_button == arg.button)
{
@ -1691,7 +1741,7 @@ namespace nana{ namespace widgets
}
points_.shift_begin_caret = points_.caret;
}
select_.mode_selection = selection::mode_mouse_selected;
select_.mode_selection = selection::mode::mouse_selected;
}
text_area_.border_renderer(graph_, _m_bgcolor());
@ -1699,11 +1749,12 @@ namespace nana{ namespace widgets
}
else if (event_code::mouse_up == arg.evt_code)
{
auto is_prev_no_selected = (select_.mode_selection == selection::mode_no_selected);
select_.ignore_press = false;
auto is_prev_no_selected = (select_.mode_selection == selection::mode::no_selected);
if (select_.mode_selection == selection::mode_mouse_selected)
if (select_.mode_selection == selection::mode::mouse_selected)
{
select_.mode_selection = selection::mode_no_selected;
select_.mode_selection = selection::mode::no_selected;
set_end_caret();
}
else if (is_prev_no_selected)
@ -1842,12 +1893,12 @@ namespace nana{ namespace widgets
select_.b.y = static_cast<unsigned>(textbase_.lines());
if(select_.b.y) --select_.b.y;
select_.b.x = static_cast<unsigned>(textbase_.getline(select_.b.y).size());
select_.mode_selection = selection::mode_method_selected;
select_.mode_selection = selection::mode::method_selected;
render(true);
return true;
}
select_.mode_selection = selection::mode_no_selected;
select_.mode_selection = selection::mode::no_selected;
if (_m_cancel_select(0))
{
render(true);
@ -1924,6 +1975,16 @@ namespace nana{ namespace widgets
return text_position_;
}
void text_editor::focus_behavior(text_focus_behavior behavior)
{
select_.behavior = behavior;
}
void text_editor::select_behavior(bool move_to_end)
{
select_.move_to_end = move_to_end;
}
void text_editor::draw_corner()
{
if(text_area_.vscroll && text_area_.hscroll)
@ -2339,27 +2400,45 @@ namespace nana{ namespace widgets
size_t lnsz = textbase_.getline(caret.y).size();
switch (key) {
case keyboard::os_arrow_left:
if (caret.x != 0) {
--caret.x;
if (select_.move_to_end && (select_.a != select_.b) && (!arg.shift))
{
caret = select_.a;
changed = true;
}else {
if (caret.y != 0) {
--caret.y;
caret.x = static_cast<decltype(caret.x)>(textbase_.getline(caret.y).size());
}
else
{
if (caret.x != 0) {
--caret.x;
changed = true;
}
else {
if (caret.y != 0) {
--caret.y;
caret.x = static_cast<decltype(caret.x)>(textbase_.getline(caret.y).size());
changed = true;
}
}
}
break;
case keyboard::os_arrow_right:
if (caret.x < lnsz) {
++caret.x;
if (select_.move_to_end && (select_.a != select_.b) && (!arg.shift))
{
caret = select_.b;
changed = true;
}else {
if (caret.y != nlines - 1) {
++caret.y;
caret.x = 0;
}
else
{
if (caret.x < lnsz) {
++caret.x;
changed = true;
}
else {
if (caret.y != nlines - 1) {
++caret.y;
caret.x = 0;
changed = true;
}
}
}
break;
case keyboard::os_arrow_up:
@ -2411,6 +2490,7 @@ namespace nana{ namespace widgets
if (select_.a != caret || select_.b != caret) {
changed = true;
}
if (changed) {
if (arg.shift) {
switch (key) {

View File

@ -94,14 +94,9 @@ namespace drawerbase {
void drawer::focus(graph_reference graph, const arg_focus& arg)
{
refresh(graph);
if (!editor_->attr().multi_lines && arg.getting)
{
editor_->select(true);
editor_->move_caret_end();
}
editor_->show_caret(arg.getting);
editor_->reset_caret();
if (!editor_->focus_changed(arg))
refresh(graph);
API::lazy_refresh();
}
@ -590,6 +585,22 @@ namespace drawerbase {
return (editor ? editor->line_height() : 0);
}
void textbox::focus_behavior(text_focus_behavior behavior)
{
internal_scope_guard lock;
auto editor = get_drawer_trigger().editor();
if (editor)
editor->focus_behavior(behavior);
}
void textbox::select_behavior(bool move_to_end)
{
internal_scope_guard lock;
auto editor = get_drawer_trigger().editor();
if (editor)
editor->select_behavior(move_to_end);
}
//Override _m_caption for caption()
auto textbox::_m_caption() const throw() -> native_string_type
{