diff --git a/include/nana/gui/detail/basic_window.hpp b/include/nana/gui/detail/basic_window.hpp index 759f8096..49ba4369 100644 --- a/include/nana/gui/detail/basic_window.hpp +++ b/include/nana/gui/detail/basic_window.hpp @@ -1,7 +1,7 @@ /* * A Basic Window Widget Definition * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at diff --git a/include/nana/gui/widgets/combox.hpp b/include/nana/gui/widgets/combox.hpp index fb58c5b6..242bfdd6 100644 --- a/include/nana/gui/widgets/combox.hpp +++ b/include/nana/gui/widgets/combox.hpp @@ -1,7 +1,7 @@ /* * A Combox Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -52,8 +52,6 @@ namespace nana trigger(); ~trigger(); - void set_accept(std::function&&); - drawer_impl& get_drawer_impl(); const drawer_impl& get_drawer_impl() const; private: @@ -70,7 +68,6 @@ namespace nana void key_press(graph_reference, const arg_keyboard&) override; void key_char(graph_reference, const arg_keyboard&) override; private: - std::function pred_acceptive_; drawer_impl * drawer_; }; diff --git a/include/nana/gui/widgets/skeletons/text_editor.hpp b/include/nana/gui/widgets/skeletons/text_editor.hpp index e1edf261..4da6c6c6 100644 --- a/include/nana/gui/widgets/skeletons/text_editor.hpp +++ b/include/nana/gui/widgets/skeletons/text_editor.hpp @@ -1,7 +1,7 @@ /* * A text editor implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -131,17 +131,22 @@ namespace nana{ namespace widgets struct keywords; class keyword_parser; public: - typedef ::nana::char_t char_type; - typedef textbase::size_type size_type; - typedef textbase::string_type string_type; + using char_type = ::nana::char_t; + using size_type = textbase::size_type; + using string_type = textbase::string_type; - typedef ::nana::paint::graphics & graph_reference; + using graph_reference = ::nana::paint::graphics&; struct ext_renderer_tag { std::function background; }; + enum class accepts + { + no_restrict, integer, real + }; + text_editor(window, graph_reference, const text_editor_scheme*); ~text_editor(); @@ -150,7 +155,9 @@ namespace nana{ namespace widgets void set_keyword(const ::nana::string& kw, const std::string& name, bool case_sensitive, bool whole_word_matched); void erase_keyword(const ::nana::string& kw); - bool respone_keyboard(nana::char_t, bool enterable); + void set_accept(std::function); + void set_accept(accepts); + bool respone_keyboard(char_type); void typeface_changed(); @@ -163,8 +170,8 @@ namespace nana{ namespace widgets bool load(const nana::char_t*); - //text_area - //@return: Returns true if the area of text is changed. + /// Sets the text area. + /// @return true if the area is changed with the new value. bool text_area(const nana::rectangle&); bool tip_string(nana::string&&); @@ -188,8 +195,7 @@ namespace nana{ namespace widgets void text(nana::string); nana::string text() const; - //move_caret - //@brief: Set caret position through text coordinate + /// Sets caret position through text coordinate. void move_caret(const upoint&); void move_caret_end(); void reset_caret_height() const; @@ -198,7 +204,7 @@ namespace nana{ namespace widgets bool selected() const; bool select(bool); - //Set the end position of a selected string + /// Sets the end position of a selected string. void set_end_caret(); bool hit_text_area(const point&) const; bool hit_select_area(nana::upoint pos) const; @@ -236,6 +242,7 @@ namespace nana{ namespace widgets skeletons::textbase& textbase(); const skeletons::textbase& textbase() const; private: + bool _m_accepts(char_type) const; ::nana::color _m_bgcolor() const; bool _m_scroll_text(bool vertical); void _m_on_scroll(const arg_mouse&); @@ -253,17 +260,15 @@ namespace nana{ namespace widgets unsigned _m_tabs_pixels(size_type tabs) const; nana::size _m_text_extent_size(const char_type*, size_type n) const; - //_m_move_offset_x_while_over_border - //@brief: Moves the view window + /// Moves the view of window. bool _m_move_offset_x_while_over_border(int many); bool _m_move_select(bool record_undo); int _m_text_top_base() const; - //_m_endx - //@brief: Gets the right point of text area + + /// Returns the right point of text area. int _m_endx() const; - //_m_endy - //@brief: Get the bottom point of text area + /// Returns the bottom point of text area. int _m_endy() const; void _m_draw_tip_string() const; @@ -298,6 +303,9 @@ namespace nana{ namespace widgets struct attributes { + accepts acceptive{ accepts::no_restrict }; + std::function pred_acceptive; + nana::string tip_string; bool line_wrapped{false}; diff --git a/include/nana/gui/widgets/spinbox.hpp b/include/nana/gui/widgets/spinbox.hpp index dcf0b982..58934dae 100644 --- a/include/nana/gui/widgets/spinbox.hpp +++ b/include/nana/gui/widgets/spinbox.hpp @@ -47,6 +47,8 @@ namespace nana void mouse_move(graph_reference, const arg_mouse&) override; void mouse_up(graph_reference, const arg_mouse& arg) override; void mouse_leave(graph_reference, const arg_mouse&) override; + void key_press(graph_reference, const arg_keyboard&) override; + void key_char(graph_reference, const arg_keyboard&) override; private: implementation * const impl_; }; @@ -58,15 +60,40 @@ namespace nana : public widget_object { public: + /// Constructs a spinbox. spinbox(); spinbox(window, bool visible); spinbox(window, const nana::rectangle& = {}, bool visible = true); + /// Sets the widget whether it accepts user keyboard input. + /// @param accept Set to indicate whether it accepts uesr keyboard input. + void editable(bool accept); + + /// Determines whether the widget accepts user keyboard input. + bool editable() const; + + /// Sets the numeric spin values and step. void range(int begin, int last, int step); void range(double begin, double last, double step); + + /// Sets the string spin values. void range(std::initializer_list steps_utf8); void range(std::initializer_list steps); + /// Sets a predicator that determines whether accepts the current user input. + /// @param pred Predicator to determines the input. + void set_accept(std::function pred); + + /// Sets the spinbox that only accepts integer input. + void set_accept_integer(); + + /// Sets the spinbox that only accepts real number input. + void set_accept_real(); + + /// Removes the accept excluding predicate accept. + void remove_accept(); + + /// Sets the qualifications void qualify(std::wstring prefix, std::wstring suffix); void qualify(const std::string & prefix_utf8, const std::string& suffix_utf8); private: diff --git a/include/nana/gui/widgets/textbox.hpp b/include/nana/gui/widgets/textbox.hpp index 16c95aac..83a7eab4 100644 --- a/include/nana/gui/widgets/textbox.hpp +++ b/include/nana/gui/widgets/textbox.hpp @@ -1,7 +1,7 @@ /* * A Textbox Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -62,7 +62,6 @@ namespace nana drawer(); text_editor * editor(); const text_editor * editor() const; - void set_accept(std::function &&); private: void attached(widget_reference, graph_reference) override; void detached() override; @@ -82,7 +81,6 @@ namespace nana void _m_text_area(unsigned width, unsigned height); private: widget* widget_; - std::function pred_acceptive_; widgets::skeletons::text_editor * editor_; std::unique_ptr evt_agent_; }; diff --git a/source/gui/widgets/combox.cpp b/source/gui/widgets/combox.cpp index 5ab4e8d6..9656f1df 100644 --- a/source/gui/widgets/combox.cpp +++ b/source/gui/widgets/combox.cpp @@ -1,7 +1,7 @@ /* * A Combox Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -61,13 +61,13 @@ namespace nana using graph_reference = paint::graphics&; using widget_reference = widget&; - enum class where_t{unknown, text, push_button}; + enum class parts{none, text, push_button}; drawer_impl() { state_.focused = false; state_.button_state = element_state::normal; - state_.pointer_where = where_t::unknown; + state_.pointer_where = parts::none; state_.lister = nullptr; } @@ -105,7 +105,7 @@ namespace nana API::refresh_window(widget_->handle()); } - where_t get_where() const + parts get_where() const { return state_.pointer_where; } @@ -174,14 +174,13 @@ namespace nana bool calc_where(graph_reference graph, int x, int y) { - auto new_where = where_t::unknown; - + auto new_where = parts::none; if(1 < x && x < static_cast(graph.width()) - 2 && 1 < y && y < static_cast(graph.height()) - 2) { if((editor_->attr().editable == false) || (static_cast(graph.width()) - 22 <= x)) - new_where = where_t::push_button; + new_where = parts::push_button; else - new_where = where_t::text; + new_where = parts::text; } if(new_where != state_.pointer_where) @@ -195,7 +194,7 @@ namespace nana void set_mouse_over(bool mo) { state_.button_state = (mo ? element_state::hovered : element_state::normal); - state_.pointer_where = where_t::unknown; + state_.pointer_where = parts::none; } void set_mouse_press(bool mp) @@ -459,7 +458,7 @@ namespace nana auto estate = state_.button_state; if (enabled && !items_.empty()) { - if (has_lister() || (element_state::pressed == estate && state_.pointer_where == where_t::push_button)) + if (has_lister() || (element_state::pressed == estate && state_.pointer_where == parts::push_button)) estate = element_state::pressed; } else @@ -521,21 +520,21 @@ namespace nana img.stretch(img.size(), *graph_, nana::rectangle(pos, imgsz)); } private: - std::vector > items_; + std::vector> items_; nana::float_listbox::module_type module_; - ::nana::combox * widget_ = nullptr; - nana::paint::graphics * graph_ = nullptr; - drawerbase::float_listbox::item_renderer* item_renderer_ = nullptr; + ::nana::combox * widget_{ nullptr }; + nana::paint::graphics * graph_{ nullptr }; + drawerbase::float_listbox::item_renderer* item_renderer_{ nullptr }; - bool image_enabled_ = false; - unsigned image_pixels_ = 16; - widgets::skeletons::text_editor * editor_ = nullptr; + bool image_enabled_{ false }; + unsigned image_pixels_{ 16 }; + widgets::skeletons::text_editor * editor_{ nullptr }; struct state_type { bool focused; element_state button_state; - where_t pointer_where; + parts pointer_where; nana::float_listbox * lister; std::size_t item_index_before_selection; @@ -553,11 +552,6 @@ namespace nana delete drawer_; } - void trigger::set_accept(std::function&& pred) - { - pred_acceptive_ = std::move(pred); - } - drawer_impl& trigger::get_drawer_impl() { return *drawer_; @@ -626,7 +620,7 @@ namespace nana { auto * editor = drawer_->editor(); if(false == editor->mouse_down(arg.left_button, arg.pos)) - if(drawer_impl::where_t::push_button == drawer_->get_where()) + if(drawer_impl::parts::push_button == drawer_->get_where()) drawer_->open_lister(); drawer_->draw(); @@ -716,8 +710,7 @@ namespace nana void trigger::key_char(graph_reference graph, const arg_keyboard& arg) { - bool enterable = drawer_->widget_ptr()->enabled() && (!pred_acceptive_ || pred_acceptive_(arg.key)); - if (drawer_->editor()->respone_keyboard(arg.key, enterable)) + if (drawer_->editor()->respone_keyboard(arg.key)) API::lazy_refresh(); } //end class trigger @@ -913,7 +906,9 @@ namespace nana void combox::set_accept(std::function pred) { internal_scope_guard lock; - get_drawer_trigger().set_accept(std::move(pred)); + auto editor = get_drawer_trigger().get_drawer_impl().editor(); + if(editor) + editor->set_accept(std::move(pred)); } combox& combox::push_back(nana::string text) diff --git a/source/gui/widgets/skeletons/text_editor.cpp b/source/gui/widgets/skeletons/text_editor.cpp index fde51b77..bf96794e 100644 --- a/source/gui/widgets/skeletons/text_editor.cpp +++ b/source/gui/widgets/skeletons/text_editor.cpp @@ -1,7 +1,7 @@ /* * A text editor implementation * Nana C++ Library(http://www.nanapro.org) -* Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com) +* Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -1355,7 +1355,17 @@ namespace nana{ namespace widgets keywords_->kwbase.erase(i); } - bool text_editor::respone_keyboard(nana::char_t key, bool enterable) //key is a character of ASCII code + void text_editor::set_accept(std::function pred) + { + attributes_.pred_acceptive = std::move(pred); + } + + void text_editor::set_accept(accepts acceptive) + { + attributes_.acceptive = acceptive; + } + + bool text_editor::respone_keyboard(char_type key) //key is a character of ASCII code { switch (key) { @@ -1367,7 +1377,7 @@ namespace nana{ namespace widgets return true; } - if (attributes_.editable && enterable) + if (attributes_.editable && API::window_enabled(window_) && (!attributes_.pred_acceptive || attributes_.pred_acceptive(key))) { switch (key) { @@ -1389,6 +1399,9 @@ namespace nana{ namespace widgets undo(false); break; default: + if (!_m_accepts(key)) + return false; + if (key > 0x7F || (32 <= key && key <= 126)) put(key); else if (sizeof(nana::char_t) == sizeof(char)) @@ -1958,6 +1971,19 @@ namespace nana{ namespace widgets nana::string text; nana::system::dataexch().get(text); + //If it is required check the acceptable + if (accepts::no_restrict != attributes_.acceptive) + { + for (auto i = text.begin(); i != text.end(); ++i) + { + if (!_m_accepts(*i)) + { + text.erase(i, text.end()); + break; + } + } + } + if (!text.empty()) put(std::move(text)); } @@ -2239,6 +2265,23 @@ namespace nana{ namespace widgets return false; } + bool text_editor::_m_accepts(char_type ch) const + { + if (accepts::no_restrict == attributes_.acceptive) + return true; + + //Checks the input whether it meets the requirement for a numeric. + auto str = text(); + + if ('+' == ch || '-' == ch) + return str.empty(); + + if ((accepts::real == attributes_.acceptive) && ('.' == ch)) + return (str.find(L'.') == str.npos); + + return ('0' <= ch && ch <= '9'); + } + ::nana::color text_editor::_m_bgcolor() const { return (!API::window_enabled(window_) ? color{ 0xE0, 0xE0, 0xE0 } : API::bgcolor(window_)); diff --git a/source/gui/widgets/spinbox.cpp b/source/gui/widgets/spinbox.cpp index c34e88d6..d1b39b21 100644 --- a/source/gui/widgets/spinbox.cpp +++ b/source/gui/widgets/spinbox.cpp @@ -137,7 +137,7 @@ namespace nana timer_.interval(intv / 2); }); - timer_.interval(1000); + timer_.interval(600); } void attach(::nana::widget& wdg, ::nana::paint::graphics& graph) @@ -185,6 +185,11 @@ namespace nana } } + void draw_spins() + { + _m_draw_spins(buttons::none); + } + void render() { editor_->render(API::is_focus_window(editor_->window_handle())); @@ -208,7 +213,7 @@ namespace nana { API::capture_window(editor_->window_handle(), false); timer_.stop(); - timer_.interval(1000); + timer_.interval(600); } if (buttons::none != spin_stated_) @@ -409,6 +414,24 @@ namespace nana API::lazy_refresh(); } + void drawer::key_press(graph_reference, const arg_keyboard& arg) + { + if (impl_->editor()->move(arg.key)) + { + impl_->editor()->reset_caret(); + impl_->draw_spins(); + API::lazy_refresh(); + } + } + + void drawer::key_char(graph_reference, const arg_keyboard& arg) + { + if (impl_->editor()->respone_keyboard(arg.key)) + { + impl_->draw_spins(); + API::lazy_refresh(); + } + } } }//end namespace drawerbase @@ -425,6 +448,20 @@ namespace nana this->create(wd, r, visible); } + void spinbox::editable(bool accept) + { + internal_scope_guard lock; + auto editor = get_drawer_trigger().impl()->editor(); + if (editor) + editor->editable(accept); + } + + bool spinbox::editable() const + { + auto editor = get_drawer_trigger().impl()->editor(); + return (editor ? editor->attr().editable : false); + } + void spinbox::range(int begin, int last, int step) { using namespace drawerbase::spinbox; @@ -453,6 +490,39 @@ namespace nana API::refresh_window(handle()); } + + void spinbox::set_accept(std::function pred) + { + internal_scope_guard lock; + auto editor = get_drawer_trigger().impl()->editor(); + if (editor) + editor->set_accept(std::move(pred)); + } + + void spinbox::set_accept_integer() + { + using accepts = ::nana::widgets::skeletons::text_editor::accepts; + auto editor = get_drawer_trigger().impl()->editor(); + if (editor) + editor->set_accept(accepts::integer); + } + + void spinbox::set_accept_real() + { + using accepts = ::nana::widgets::skeletons::text_editor::accepts; + auto editor = get_drawer_trigger().impl()->editor(); + if (editor) + editor->set_accept(accepts::real); + } + + void spinbox::remove_accept() + { + using accepts = ::nana::widgets::skeletons::text_editor::accepts; + auto editor = get_drawer_trigger().impl()->editor(); + if (editor) + editor->set_accept(accepts::no_restrict); + } + void spinbox::qualify(std::wstring prefix, std::wstring suffix) { get_drawer_trigger().impl()->qualify(std::move(prefix), std::move(suffix)); diff --git a/source/gui/widgets/textbox.cpp b/source/gui/widgets/textbox.cpp index ac084912..c43931ff 100644 --- a/source/gui/widgets/textbox.cpp +++ b/source/gui/widgets/textbox.cpp @@ -1,7 +1,7 @@ /* * A Textbox Implementation * Nana C++ Library(http://www.nanapro.org) - * Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com) + * Copyright(C) 2003-2015 Jinhao(cnjinhao@hotmail.com) * * Distributed under the Boost Software License, Version 1.0. * (See accompanying file LICENSE_1_0.txt or copy at @@ -45,11 +45,6 @@ namespace nana{ namespace drawerbase { return editor_; } - void drawer::set_accept(std::function && fn) - { - pred_acceptive_ = std::move(fn); - } - void drawer::attached(widget_reference wdg, graph_reference graph) { auto wd = wdg.handle(); @@ -139,8 +134,7 @@ namespace nana{ namespace drawerbase { void drawer::key_char(graph_reference, const arg_keyboard& arg) { - bool enterable = widget_->enabled() && (!pred_acceptive_ || pred_acceptive_(arg.key)); - if (editor_->respone_keyboard(arg.key, enterable)) + if (editor_->respone_keyboard(arg.key)) API::lazy_refresh(); } @@ -348,7 +342,9 @@ namespace nana{ namespace drawerbase { void textbox::set_accept(std::function fn) { internal_scope_guard lock; - get_drawer_trigger().set_accept(std::move(fn)); + auto editor = get_drawer_trigger().editor(); + if(editor) + editor->set_accept(std::move(fn)); } textbox& textbox::tip_string(nana::string str)