diff --git a/include/nana/config.hpp b/include/nana/config.hpp index ae11279d..88781d84 100644 --- a/include/nana/config.hpp +++ b/include/nana/config.hpp @@ -93,6 +93,9 @@ #endif #endif +//This marco is defined since 1.4 and until 1.5 for deprecating frame widget. +//This marco and class frame will be removed in version 1.5 +#define WIDGET_FRAME_DEPRECATED /////////////////// // Support for NANA_AUTOMATIC_GUI_TESTING diff --git a/include/nana/gui/basis.hpp b/include/nana/gui/basis.hpp index 744fa9ba..a80ff3da 100644 --- a/include/nana/gui/basis.hpp +++ b/include/nana/gui/basis.hpp @@ -56,14 +56,18 @@ namespace nana super, widget = 0x1, lite_widget = 0x3, - root = 0x5, - frame = 0x9 + root = 0x5 +#ifndef WIDGET_FRAME_DEPRECATED + ,frame = 0x9 +#endif }; //wait for constexpr struct widget_tag{ static const flags value = flags::widget; }; struct lite_widget_tag : public widget_tag{ static const flags value = flags::lite_widget; }; struct root_tag : public widget_tag{ static const flags value = flags::root; }; +#ifndef WIDGET_FRAME_DEPRECATED struct frame_tag : public widget_tag{ static const flags value = flags::frame; }; +#endif }// end namespace category using native_window_type = detail::native_window_handle_impl*; @@ -260,6 +264,26 @@ that return a corresponding nana::appearance with predefined values. } }; };//end namespace apper + + /// Interface for caret operations + class caret_interface + { + public: + virtual ~caret_interface() = default; + + virtual void disable_throw() noexcept = 0; + + virtual void effective_range(const rectangle& range) = 0; + + virtual void position(const point& pos) = 0; + virtual point position() const = 0; + + virtual void dimension(const size& size) = 0; + virtual size dimension() const = 0; + + virtual void visible(bool visibility) = 0; + virtual bool visible() const = 0; + };//end class caret_interface }//end namespace nana #include diff --git a/include/nana/gui/detail/basic_window.hpp b/include/nana/gui/detail/basic_window.hpp index 6d44a936..01ccb589 100644 --- a/include/nana/gui/detail/basic_window.hpp +++ b/include/nana/gui/detail/basic_window.hpp @@ -32,32 +32,37 @@ namespace detail invisible, visible, displayed }; - class caret_descriptor + class caret + : public caret_interface { public: - typedef basic_window core_window_t; + caret(basic_window* owner, const size& size); + ~caret(); - caret_descriptor(core_window_t*, unsigned width, unsigned height); - ~caret_descriptor(); - void set_active(bool); - core_window_t* window() const; - void position(int x, int y); - void effective_range(::nana::rectangle); - ::nana::point position() const; - void visible(bool isshow); - bool visible() const; - ::nana::size size() const; - void size(const ::nana::size&); + void activate(bool activity); + basic_window* owner() const noexcept; void update(); + public: + //Implement caret_interface functions + + //This function is useless for class caret, see caret_proxy. + void disable_throw() noexcept override; + void effective_range(const rectangle& r) override; + void position(const point& pos) override; + nana::point position() const override; + size dimension() const override; + void dimension(const size& s); + void visible(bool visibility) override; + bool visible() const override; private: - core_window_t* wd_; - ::nana::point point_; - ::nana::size size_; - ::nana::size paint_size_; - visible_state visible_state_; - bool out_of_range_; - ::nana::rectangle effective_range_; - };//end class caret_descriptor + basic_window * owner_; + point position_; + size size_; + size visual_size_; + visible_state visibility_{ visible_state::invisible }; + bool out_of_range_{ false }; + rectangle effect_range_; + };//end class caret /// Define some constant about tab category, these flags can be combine with operator | struct tab_type @@ -70,6 +75,8 @@ namespace detail }; }; + class caret; + /// a window data structure descriptor struct basic_window : public events_holder @@ -107,7 +114,9 @@ namespace detail /// bind a native window and baisc_window void bind_native_window(native_window_type, unsigned width, unsigned height, unsigned extra_width, unsigned extra_height, paint::graphics&); +#ifndef WIDGET_FRAME_DEPRECATED void frame_window(native_window_type); +#endif bool is_ancestor_of(const basic_window* wd) const; bool visible_parents() const; @@ -174,13 +183,15 @@ namespace detail mouse_action action_before; }flags; - struct + + struct annex_components { - caret_descriptor* caret; + caret* caret_ptr{ nullptr }; + + //The following pointers refer to the widget's object. std::shared_ptr events_ptr; - }together; - - widget_geometrics* scheme{ nullptr }; + widget_geometrics* scheme{ nullptr }; + }annex; struct { @@ -191,11 +202,13 @@ namespace detail struct other_tag { +#ifndef WIDGET_FRAME_DEPRECATED struct attr_frame_tag { native_window_type container{nullptr}; std::vector attach; }; +#endif struct attr_root_tag { @@ -223,7 +236,9 @@ namespace detail union { attr_root_tag * root; +#ifndef WIDGET_FRAME_DEPRECATED attr_frame_tag * frame; +#endif }attribute; other_tag(category::flags); diff --git a/include/nana/gui/detail/bedrock.hpp b/include/nana/gui/detail/bedrock.hpp index 32a812ad..cda91c98 100644 --- a/include/nana/gui/detail/bedrock.hpp +++ b/include/nana/gui/detail/bedrock.hpp @@ -82,9 +82,7 @@ namespace detail void define_state_cursor(core_window_t*, nana::cursor, thread_context*); void undefine_state_cursor(core_window_t*, thread_context*); - widget_geometrics& get_scheme_template(scheme_factory_interface&&); - widget_geometrics* make_scheme(scheme_factory_interface&&); - + color_schemes& scheme(); events_operation& evt_operation(); window_manager& wd_manager(); diff --git a/include/nana/gui/detail/drawer.hpp b/include/nana/gui/detail/drawer.hpp index 26061033..e313c172 100644 --- a/include/nana/gui/detail/drawer.hpp +++ b/include/nana/gui/detail/drawer.hpp @@ -14,7 +14,6 @@ #define NANA_GUI_DETAIL_DRAWER_HPP #include -#include #include "general_events.hpp" #include #include @@ -29,14 +28,23 @@ namespace nana } class drawer_trigger - : ::nana::noncopyable, ::nana::nonmovable { friend class detail::drawer; + + //Noncopyable + drawer_trigger(const drawer_trigger&) = delete; + drawer_trigger& operator=(const drawer_trigger&) = delete; + + //Nonmovable + drawer_trigger(drawer_trigger&&) = delete; + drawer_trigger& operator=(drawer_trigger&&) = delete; + public: using widget_reference = widget&; using graph_reference = paint::graphics&; - virtual ~drawer_trigger(); + drawer_trigger() = default; + virtual ~drawer_trigger() = default; virtual void attached(widget_reference, graph_reference); //none-const virtual void detached(); //none-const @@ -73,21 +81,11 @@ namespace nana { struct basic_window; - namespace dynamic_drawing - { - //declaration - class object; - } - //@brief: Every window has a drawer, the drawer holds a drawer_trigger for // a widget. class drawer : nana::noncopyable, nana::nonmovable { - enum{ - event_size = static_cast(event_code::end) - }; - enum class method_state { pending, @@ -95,6 +93,7 @@ namespace nana not_overrided }; public: + drawer(); ~drawer(); void bind(basic_window*); @@ -136,21 +135,21 @@ namespace nana void _m_emit(event_code evt_code, const Arg& arg, Mfptr mfptr) { const int pos = static_cast(evt_code); - if (realizer_ && (method_state::not_overrided != mth_state_[pos])) + if (data_impl_->realizer && (method_state::not_overrided != data_impl_->mth_state[pos])) { _m_bground_pre(); - if (method_state::pending == mth_state_[pos]) + if (method_state::pending == data_impl_->mth_state[pos]) { - (realizer_->*mfptr)(graphics, arg); + (data_impl_->realizer->*mfptr)(graphics, arg); //Check realizer, when the window is closed in that event handler, the drawer will be //detached and realizer will be a nullptr - if(realizer_) - mth_state_[pos] = (realizer_->_m_overrided(evt_code) ? method_state::overrided : method_state::not_overrided); + if (data_impl_->realizer) + data_impl_->mth_state[pos] = (data_impl_->realizer->_m_overrided(evt_code) ? method_state::overrided : method_state::not_overrided); } else - (realizer_->*mfptr)(graphics, arg); + (data_impl_->realizer->*mfptr)(graphics, arg); if (_m_lazy_decleared()) { @@ -162,11 +161,9 @@ namespace nana public: nana::paint::graphics graphics; private: - basic_window* core_window_{nullptr}; - drawer_trigger* realizer_{nullptr}; - std::vector dynamic_drawing_objects_; - bool refreshing_{false}; - method_state mth_state_[event_size]; + struct data_implement; + + data_implement * const data_impl_; }; }//end namespace detail }//end namespace nana diff --git a/include/nana/gui/detail/effects_renderer.hpp b/include/nana/gui/detail/effects_renderer.hpp index f7bd7d03..155fcb78 100644 --- a/include/nana/gui/detail/effects_renderer.hpp +++ b/include/nana/gui/detail/effects_renderer.hpp @@ -174,12 +174,12 @@ namespace nana{ good_r.x = good_r.y = 1; good_r.width = r.width - 2; good_r.height = r.height - 2; - pixbuf.rectangle(good_r, wd->scheme->activated.get_color(), 0.95, false); + pixbuf.rectangle(good_r, wd->annex.scheme->activated.get_color(), 0.95, false); good_r.x = good_r.y = 0; good_r.width = r.width; good_r.height = r.height; - pixbuf.rectangle(good_r, wd->scheme->activated.get_color(), 0.4, false); + pixbuf.rectangle(good_r, wd->annex.scheme->activated.get_color(), 0.4, false); pixbuf.pixel(0, 0, px0); pixbuf.pixel(r.width - 1, 0, px1); diff --git a/include/nana/gui/detail/window_manager.hpp b/include/nana/gui/detail/window_manager.hpp index cab6ecb1..d2a83d3e 100644 --- a/include/nana/gui/detail/window_manager.hpp +++ b/include/nana/gui/detail/window_manager.hpp @@ -94,10 +94,12 @@ namespace detail core_window_t* create_root(core_window_t*, bool nested, rectangle, const appearance&, widget*); core_window_t* create_widget(core_window_t*, const rectangle&, bool is_lite, widget*); +#ifndef WIDGET_FRAME_DEPRECATED core_window_t* create_frame(core_window_t*, const rectangle&, widget*); bool insert_frame(core_window_t* frame, native_window); bool insert_frame(core_window_t* frame, core_window_t*); +#endif void close(core_window_t*); //destroy diff --git a/include/nana/gui/programming_interface.hpp b/include/nana/gui/programming_interface.hpp index 23d5aee8..62125e65 100644 --- a/include/nana/gui/programming_interface.hpp +++ b/include/nana/gui/programming_interface.hpp @@ -80,8 +80,9 @@ namespace API window create_window(window, bool nested, const rectangle&, const appearance&, widget* attached); window create_widget(window, const rectangle&, widget* attached); window create_lite_widget(window, const rectangle&, widget* attached); +#ifndef WIDGET_FRAME_DEPRECATED window create_frame(window, const rectangle&, widget* attached); - +#endif paint::graphics* window_graphics(window); void delay_restore(bool); @@ -201,9 +202,12 @@ namespace API void fullscreen(window, bool); bool enabled_double_click(window, bool); + +#ifndef WIDGET_FRAME_DEPRECATED bool insert_frame(window frame, native_window_type); native_window_type frame_container(window frame); native_window_type frame_element(window frame, unsigned index); +#endif void close_window(window); void show_window(window, bool show); ///< Sets a window visible state. void restore_window(window); @@ -334,15 +338,18 @@ namespace API color activated_color(window); color activated_color(window, const color&); - void create_caret(window, unsigned width, unsigned height); + void create_caret(window, const size&); void destroy_caret(window); - void caret_effective_range(window, const rectangle&); - void caret_pos(window, const ::nana::point&); - nana::point caret_pos(window); - nana::size caret_size(window); - void caret_size(window, const size&); - void caret_visible(window, bool is_show); - bool caret_visible(window); + + /// Opens an existing caret of a window. + /** + * This function returns an object to operate caret. The object doesn't create or destroy the caret. + * When you are finished with the caret, be sure to reset the pointer. + * + * @param window_handle A handle to a window whose caret is to be retrieved + * @return a pointer to the caret proxy. nullptr if the window doesn't have a caret. + */ + ::std::unique_ptr open_caret(window window_handle, bool disable_throw = false); /// Enables that the user can give input focus to the specified window using TAB key. void tabstop(window); diff --git a/include/nana/gui/widgets/form.hpp b/include/nana/gui/widgets/form.hpp index 66047576..77972a8b 100644 --- a/include/nana/gui/widgets/form.hpp +++ b/include/nana/gui/widgets/form.hpp @@ -14,9 +14,12 @@ #define NANA_GUI_WIDGET_FORM_HPP #include "widget.hpp" +#include namespace nana { + class place; + namespace drawerbase { namespace form @@ -29,12 +32,29 @@ namespace nana private: widget* wd_{nullptr}; }; + + class form_base + : public widget_object + { + public: + form_base(window owner, bool nested, const rectangle&, const appearance&); + + //place methods + + place & get_place(); + void div(const char* div_text); + place::field_reference operator[](const char* field_name); + void collocate() noexcept; + private: + std::unique_ptr place_; + }; }//end namespace form }//end namespace drawerbase /// \brief Pop-up window. Is different from other window widgets: its default constructor create the window. /// \see nana::appearance - class form: public widget_object + class form + : public drawerbase::form::form_base { public: using appear = ::nana::appear; @@ -50,7 +70,8 @@ namespace nana void wait_for_this(); }; - class nested_form : public widget_object + class nested_form + : public drawerbase::form::form_base { public: using appear = ::nana::appear; diff --git a/include/nana/gui/widgets/frame.hpp b/include/nana/gui/widgets/frame.hpp index 6cc91dce..82a53d95 100644 --- a/include/nana/gui/widgets/frame.hpp +++ b/include/nana/gui/widgets/frame.hpp @@ -16,6 +16,8 @@ #define NANA_GUI_WIDGET_FRAME_HPP #include "widget.hpp" + +#ifndef WIDGET_FRAME_DEPRECATED namespace nana { /** @@ -51,3 +53,4 @@ namespace nana }; }//end namespace nana #endif +#endif diff --git a/include/nana/gui/widgets/skeletons/text_editor.hpp b/include/nana/gui/widgets/skeletons/text_editor.hpp index 92b6a5ac..c1fb06fa 100644 --- a/include/nana/gui/widgets/skeletons/text_editor.hpp +++ b/include/nana/gui/widgets/skeletons/text_editor.hpp @@ -308,7 +308,8 @@ namespace nana{ namespace widgets void _m_offset_y(int y); - unsigned _m_char_by_pixels(const wchar_t*, std::size_t len, unsigned* pxbuf, int str_px, int pixels, bool is_rtl); + unsigned _m_char_by_pixels(const unicode_bidi::entity&, unsigned pos); + unsigned _m_pixels_by_char(const ::std::wstring&, std::size_t pos) const; void _handle_move_key(const arg_keyboard& arg); @@ -316,6 +317,7 @@ namespace nana{ namespace widgets std::unique_ptr behavior_; undoable undo_; nana::window window_; + std::unique_ptr caret_; graph_reference graph_; const text_editor_scheme* scheme_; event_interface * event_handler_{ nullptr }; diff --git a/include/nana/gui/widgets/widget.hpp b/include/nana/gui/widgets/widget.hpp index 952cd2a4..5e1ad652 100644 --- a/include/nana/gui/widgets/widget.hpp +++ b/include/nana/gui/widgets/widget.hpp @@ -14,7 +14,6 @@ #define NANA_GUI_WIDGET_HPP #include -#include #include "../programming_interface.hpp" #include #include @@ -391,33 +390,6 @@ namespace nana { return API::window_outline_size(handle()); } - - place & get_place() - { - if (this->empty()) - throw std::runtime_error("form::get_plac: the form has destroyed."); - - if (!place_) - place_.reset(new place{ *this }); - - return *place_; - } - - void div(const char* div_text) - { - get_place().div(div_text); - } - - place::field_reference operator[](const char* field_name) - { - return get_place()[field_name]; - } - - void collocate() noexcept - { - if (place_) - place_->collocate(); - } protected: DrawerTrigger& get_drawer_trigger() { @@ -447,9 +419,9 @@ namespace nana DrawerTrigger trigger_; std::shared_ptr events_; std::unique_ptr scheme_; - std::unique_ptr place_; };//end class widget_object +#ifndef WIDGET_FRAME_DEPRECATED /// Base class of all the classes defined as a frame window. \see nana::frame template class widget_object: public widget{}; @@ -509,6 +481,7 @@ namespace nana std::shared_ptr events_; std::unique_ptr scheme_; };//end class widget_object +#endif }//end namespace nana #include diff --git a/source/gui/detail/basic_window.cpp b/source/gui/detail/basic_window.cpp index 5c149ec3..a7cbd2e6 100644 --- a/source/gui/detail/basic_window.cpp +++ b/source/gui/detail/basic_window.cpp @@ -17,188 +17,194 @@ namespace nana { namespace detail { - //class caret_descriptor - caret_descriptor::caret_descriptor(core_window_t* wd, unsigned width, unsigned height) - :wd_(wd), size_(width, height), visible_state_(visible_state::invisible), out_of_range_(false) + //class caret + caret::caret(basic_window* owner, const size& size): + owner_(owner), + size_(size) {} - caret_descriptor::~caret_descriptor() + caret::~caret() { - if(wd_) native_interface::caret_destroy(wd_->root); + if (owner_) + native_interface::caret_destroy(owner_->root); } - void caret_descriptor::set_active(bool active) + void caret::activate(bool activity) { - if(wd_) + if (owner_) { - if(active) + if (activity) { - native_interface::caret_create(wd_->root, size_); + native_interface::caret_create(owner_->root, size_); - visible_state_ = visible_state::invisible; - this->position(point_.x, point_.y); + visibility_ = visible_state::invisible; + this->position(position_); } else - native_interface::caret_destroy(wd_->root); + native_interface::caret_destroy(owner_->root); - wd_->root_widget->other.attribute.root->ime_enabled = active; + owner_->root_widget->other.attribute.root->ime_enabled = activity; } } - auto caret_descriptor::window() const ->core_window_t* + basic_window* caret::owner() const noexcept { - return wd_; + return owner_; } - void caret_descriptor::position(int x, int y) + void caret::update() { - point_.x = x; - point_.y = y; + auto pos = position_; + auto size = size_; - update(); - } - - void caret_descriptor::effective_range(nana::rectangle rect) - { - //Chech rect - if (rect.width && rect.height && rect.right() > 0 && rect.bottom() > 0) - { - if(rect.x < 0) - { - rect.width += rect.x; - rect.x = 0; - } - - if(rect.y < 0) - { - rect.height += rect.y; - rect.y = 0; - } - - if(effective_range_ != rect) - { - effective_range_ = rect; - update(); - } - } - } - - nana::point caret_descriptor::position() const - { - return point_; - } - - void caret_descriptor::visible(bool is_show) - { - auto pre_displayed = (visible_state::displayed == visible_state_); - - if (is_show) - { - visible_state_ = visible_state::visible; - if (wd_->displayed() && (! out_of_range_)) - visible_state_ = visible_state::displayed; - } - else - visible_state_ = visible_state::invisible; - - if (pre_displayed != (visible_state::displayed == visible_state_)) - native_interface::caret_visible(wd_->root, !pre_displayed); - } - - bool caret_descriptor::visible() const - { - return (visible_state::invisible != visible_state_); - } - - nana::size caret_descriptor::size() const - { - return size_; - } - - void caret_descriptor::size(const nana::size& s) - { - size_ = s; - update(); - - if (visible_state::invisible != visible_state_) - visible(true); - } - - void caret_descriptor::update() - { - nana::point pos = point_; - nana::size size = size_; - - nana::rectangle rect = effective_range_; - if(0 == effective_range_.width || 0 == effective_range_.height) + auto rect = effect_range_; + if (0 == effect_range_.width || 0 == effect_range_.height) { rect.x = rect.y = 0; - rect = wd_->dimension; + rect = owner_->dimension; } else { - pos.x += effective_range_.x; - pos.y += effective_range_.y; + pos += effect_range_.position(); } - if( (pos.x + static_cast(size.width) <= rect.x) || (pos.x >= rect.right()) || + if ((pos.x + static_cast(size.width) <= rect.x) || (pos.x >= rect.right()) || (pos.y + static_cast(size.height) <= rect.y) || (pos.y >= rect.bottom()) ) {//Out of Range without overlap - if(false == out_of_range_) + if (false == out_of_range_) { out_of_range_ = true; - if (visible_state::invisible != visible_state_) + if (visible_state::invisible != visibility_) visible(false); } } else { - if(pos.x < rect.x) + if (pos.x < rect.x) { size.width -= (rect.x - pos.x); pos.x = rect.x; } - else if(pos.x + static_cast(size.width) > rect.right()) + else if (pos.x + static_cast(size.width) > rect.right()) { size.width -= pos.x + size.width - rect.right(); } - if(pos.y < rect.y) + if (pos.y < rect.y) { size.width -= (rect.y - pos.y); pos.y = rect.y; } - else if(pos.y + static_cast(size.height) > rect.bottom()) + else if (pos.y + static_cast(size.height) > rect.bottom()) size.height -= pos.y + size.height - rect.bottom(); - if(out_of_range_) + if (out_of_range_) { - if (paint_size_ == size) + if (visual_size_ == size) visible(true); out_of_range_ = false; } - if(paint_size_ != size) + if (visual_size_ != size) { - bool vs = (visible_state::invisible != visible_state_); - native_interface::caret_destroy(wd_->root); - native_interface::caret_create(wd_->root, size); + bool vs = (visible_state::invisible != visibility_); + native_interface::caret_destroy(owner_->root); + native_interface::caret_create(owner_->root, size); - visible_state_ = visible_state::invisible; + visibility_ = visible_state::invisible; if (vs) visible(true); - paint_size_ = size; + visual_size_ = size; } - - native_interface::caret_pos(wd_->root, wd_->pos_root + pos); + + native_interface::caret_pos(owner_->root, owner_->pos_root + pos); } } - //end class caret_descriptor + + //Implement caret_interface functions + void caret::disable_throw() noexcept + { + //This function is useless for class caret, see caret_proxy. + } + + void caret::effective_range(const rectangle& r) + { + auto range = r; + //Chech rect + if (range.width && range.height && range.right() > 0 && range.bottom() > 0) + { + if (range.x < 0) + { + range.width += range.x; + range.x = 0; + } + + if (range.y < 0) + { + range.height += range.y; + range.y = 0; + } + + if (effect_range_ != range) + { + effect_range_ = range; + update(); + } + } + } + + void caret::position(const point& pos) + { + position_ = pos; + update(); + } + + point caret::position() const + { + return position_; + } + + size caret::dimension() const + { + return size_; + } + + void caret::dimension(const size& s) + { + size_ = s; + update(); + + if (visible_state::invisible != visibility_) + visible(true); + } + + void caret::visible(bool visibility) + { + auto pre_displayed = (visible_state::displayed == visibility_); + + if (visibility) + { + visibility_ = visible_state::visible; + if (owner_->displayed() && (!out_of_range_)) + visibility_ = visible_state::displayed; + } + else + visibility_ = visible_state::invisible; + + if (pre_displayed != (visible_state::displayed == visibility_)) + native_interface::caret_visible(owner_->root, !pre_displayed); + } + + bool caret::visible() const + { + return (visible_state::invisible != visibility_); + } + //end class caret //struct basic_window //struct basic_window::other_tag @@ -210,9 +216,11 @@ namespace nana case category::flags::root: attribute.root = new attr_root_tag; break; +#ifndef WIDGET_FRAME_DEPRECATED case category::flags::frame: attribute.frame = new attr_frame_tag; break; +#endif default: attribute.root = nullptr; } @@ -220,6 +228,7 @@ namespace nana basic_window::other_tag::~other_tag() { +#ifndef WIDGET_FRAME_DEPRECATED switch(category) { case category::flags::root: @@ -230,6 +239,9 @@ namespace nana break; default: break; } +#endif + if (category::flags::root == category) + delete attribute.root; } //end struct basic_window::other_tag @@ -245,8 +257,8 @@ namespace nana basic_window::~basic_window() { - delete together.caret; - together.caret = nullptr; + delete annex.caret_ptr; + annex.caret_ptr = nullptr; delete effect.bground; effect.bground = nullptr; @@ -268,11 +280,13 @@ namespace nana } } +#ifndef WIDGET_FRAME_DEPRECATED void basic_window::frame_window(native_window_type wd) { if(category::flags::frame == this->other.category) other.attribute.frame->container = wd; } +#endif bool basic_window::is_ancestor_of(const basic_window* wd) const { @@ -312,7 +326,7 @@ namespace nana const basic_window* get_child_caret(const basic_window* wd, bool this_is_a_child) { - if (this_is_a_child && wd->together.caret) + if (this_is_a_child && wd->annex.caret_ptr) return wd; for (auto child : wd->children) @@ -412,8 +426,6 @@ namespace nana effect.bground = nullptr; effect.bground_fade_rate = 0; - together.caret = nullptr; - extra_width = extra_height = 0; //The window must keep its thread_id same as its parent if it is a child. @@ -425,15 +437,15 @@ namespace nana bool basic_window::set_events(const std::shared_ptr& p) { - if (together.events_ptr) + if (annex.events_ptr) return false; - together.events_ptr = p; + annex.events_ptr = p; return true; } general_events * basic_window::get_events() const { - return together.events_ptr.get(); + return annex.events_ptr.get(); } //end struct basic_window }//end namespace detail diff --git a/source/gui/detail/bedrock_pi.cpp b/source/gui/detail/bedrock_pi.cpp index 087fed6d..c0e37ae4 100644 --- a/source/gui/detail/bedrock_pi.cpp +++ b/source/gui/detail/bedrock_pi.cpp @@ -129,16 +129,16 @@ namespace nana arg.window_handle = reinterpret_cast(wd); if (emit(event_code::expose, wd, arg, false, get_thread_context())) { - const core_window_t * caret_wd = (wd->together.caret ? wd : wd->child_caret()); + const core_window_t * caret_wd = (wd->annex.caret_ptr ? wd : wd->child_caret()); if (caret_wd) { if (exposed) { if (wd->root_widget->other.attribute.root->focus == caret_wd) - caret_wd->together.caret->visible(true); + caret_wd->annex.caret_ptr->visible(true); } else - caret_wd->together.caret->visible(false); + caret_wd->annex.caret_ptr->visible(false); } if (!exposed) @@ -148,8 +148,10 @@ namespace nana //find an ancestor until it is not a lite_widget wd = wd->seek_non_lite_widget_ancestor(); } +#ifndef WIDGET_FRAME_DEPRECATED else if (category::flags::frame == wd->other.category) wd = wd_manager().find_window(wd->root, wd->pos_root.x, wd->pos_root.y); +#endif } wd_manager().refresh_tree(wd); @@ -201,24 +203,21 @@ namespace nana { if (root_wd->flags.enabled && root_wd->flags.take_active) { - if (focused && focused->together.caret) - focused->together.caret->set_active(true); + if (focused && focused->annex.caret_ptr) + focused->annex.caret_ptr->activate(true); if (!emit(event_code::focus, focused, arg, true, get_thread_context())) this->wd_manager().set_focus(root_wd, true, arg_focus::reason::general); } } - else + else if (root_wd->other.attribute.root->focus) { - if (root_wd->other.attribute.root->focus) + if (emit(event_code::focus, focused, arg, true, get_thread_context())) { - if (emit(event_code::focus, focused, arg, true, get_thread_context())) - { - if (focused->together.caret) - focused->together.caret->set_active(false); - } - close_menu_if_focus_other_window(receiver); + if (focused->annex.caret_ptr) + focused->annex.caret_ptr->activate(false); } + close_menu_if_focus_other_window(receiver); } } @@ -353,19 +352,14 @@ namespace nana return pi_data_->shortkey_occurred; } - widget_geometrics& bedrock::get_scheme_template(scheme_factory_interface&& factory) + color_schemes& bedrock::scheme() { - return pi_data_->scheme.scheme_template(std::move(factory)); - } - - widget_geometrics* bedrock::make_scheme(scheme_factory_interface&& factory) - { - return pi_data_->scheme.create(std::move(factory)); + return pi_data_->scheme; } void bedrock::_m_emit_core(event_code evt_code, core_window_t* wd, bool draw_only, const ::nana::event_arg& event_arg) { - auto retain = wd->together.events_ptr; + auto retain = wd->annex.events_ptr; auto evts_ptr = retain.get(); switch (evt_code) diff --git a/source/gui/detail/bedrock_posix.cpp b/source/gui/detail/bedrock_posix.cpp index 1ac30c25..c959b01c 100644 --- a/source/gui/detail/bedrock_posix.cpp +++ b/source/gui/detail/bedrock_posix.cpp @@ -385,7 +385,7 @@ namespace detail delete msg.u.mouse_drop.files; arg.pos.x = msg.u.mouse_drop.x - msgwd->pos_root.x; arg.pos.y = msg.u.mouse_drop.y - msgwd->pos_root.y; - msgwd->together.events_ptr->mouse_dropfiles.emit(arg, reinterpret_cast(msgwd)); + msgwd->annex.events_ptr->mouse_dropfiles.emit(arg, reinterpret_cast(msgwd)); brock.wd_manager().do_lazy_refresh(msgwd, false); } break; @@ -594,7 +594,7 @@ namespace detail } } - auto retain = msgwnd->together.events_ptr; + auto retain = msgwnd->annex.events_ptr; context.event_window = msgwnd; pressed_wd = nullptr; @@ -632,7 +632,7 @@ namespace detail nana::point mspos{xevent.xbutton.x, xevent.xbutton.y}; while(msgwnd) { - if(msgwnd->together.events_ptr->mouse_wheel.length() != 0) + if(msgwnd->annex.events_ptr->mouse_wheel.length() != 0) { mspos -= msgwnd->pos_root; arg_wheel arg; @@ -653,7 +653,7 @@ namespace detail msgwnd->set_action(mouse_action::normal); if(msgwnd->flags.enabled) { - auto retain = msgwnd->together.events_ptr; + auto retain = msgwnd->annex.events_ptr; ::nana::arg_mouse arg; assign_arg(arg, msgwnd, message, xevent); @@ -682,7 +682,7 @@ namespace detail if(hit) msgwnd->set_action(mouse_action::hovered); - auto retain = msgwnd->together.events_ptr; + auto retain = msgwnd->annex.events_ptr; auto evt_ptr = retain.get(); arg.evt_code = event_code::mouse_up; @@ -698,7 +698,7 @@ namespace detail } } else if(click_arg.window_handle) - msgwnd->together.events_ptr->click.emit(click_arg, reinterpret_cast(msgwnd)); + msgwnd->annex.events_ptr->click.emit(click_arg, reinterpret_cast(msgwnd)); wd_manager.do_lazy_refresh(msgwnd, false); } @@ -895,7 +895,7 @@ namespace detail msgwnd->set_action(mouse_action::pressed); pressed_wd_space = msgwnd; - auto retain = msgwnd->together.events_ptr; + auto retain = msgwnd->annex.events_ptr; draw_invoker(&drawer::mouse_down, msgwnd, arg, &context); wd_manager.do_lazy_refresh(msgwnd, false); @@ -987,7 +987,7 @@ namespace detail arg.evt_code = event_code::key_char; arg.window_handle = reinterpret_cast(msgwnd); brock.get_key_state(arg); - msgwnd->together.events_ptr->key_char.emit(arg, reinterpret_cast(msgwnd)); + msgwnd->annex.events_ptr->key_char.emit(arg, reinterpret_cast(msgwnd)); if(arg.ignore == false && wd_manager.available(msgwnd)) draw_invoker(&drawer::key_char, msgwnd, arg, &context); } @@ -1031,7 +1031,7 @@ namespace detail click_arg.mouse_args = nullptr; click_arg.window_handle = reinterpret_cast(msgwnd); - auto retain = msgwnd->together.events_ptr; + auto retain = msgwnd->annex.events_ptr; if (brock.emit(event_code::click, msgwnd, click_arg, true, &context)) { arg_mouse arg; diff --git a/source/gui/detail/bedrock_windows.cpp b/source/gui/detail/bedrock_windows.cpp index 798d662c..d6019428 100644 --- a/source/gui/detail/bedrock_windows.cpp +++ b/source/gui/detail/bedrock_windows.cpp @@ -947,7 +947,7 @@ namespace detail assign_arg(arg, msgwnd, message, pmdec); msgwnd->set_action(mouse_action::pressed); - auto retain = msgwnd->together.events_ptr; + auto retain = msgwnd->annex.events_ptr; if (brock.emit(event_code::mouse_down, msgwnd, arg, true, &context)) { //If a root_window is created during the mouse_down event, Nana.GUI will ignore the mouse_up event. @@ -986,7 +986,7 @@ namespace detail msgwnd->set_action(mouse_action::normal); if(msgwnd->flags.enabled) { - auto retain = msgwnd->together.events_ptr; + auto retain = msgwnd->annex.events_ptr; ::nana::arg_mouse arg; assign_arg(arg, msgwnd, message, pmdec); @@ -1121,7 +1121,7 @@ namespace detail auto evt_wd = scrolled_wd; while (evt_wd) { - if (evt_wd->together.events_ptr->mouse_wheel.length() != 0) + if (evt_wd->annex.events_ptr->mouse_wheel.length() != 0) { def_window_proc = false; nana::point mspos{ scr_pos.x, scr_pos.y }; @@ -1198,7 +1198,7 @@ namespace detail wd_manager.calc_window_point(msgwnd, dropfiles.pos); dropfiles.window_handle = reinterpret_cast(msgwnd); - msgwnd->together.events_ptr->mouse_dropfiles.emit(dropfiles, reinterpret_cast(msgwnd)); + msgwnd->annex.events_ptr->mouse_dropfiles.emit(dropfiles, reinterpret_cast(msgwnd)); wd_manager.do_lazy_refresh(msgwnd, false); } } @@ -1422,7 +1422,7 @@ namespace detail msgwnd->set_action(mouse_action::pressed); pressed_wd_space = msgwnd; - auto retain = msgwnd->together.events_ptr; + auto retain = msgwnd->annex.events_ptr; draw_invoker(&drawer::mouse_down, msgwnd, arg, &context); wd_manager.do_lazy_refresh(msgwnd, false); @@ -1468,7 +1468,7 @@ namespace detail brock.get_key_state(arg); arg.ignore = false; - msgwnd->together.events_ptr->key_char.emit(arg, reinterpret_cast(msgwnd)); + msgwnd->annex.events_ptr->key_char.emit(arg, reinterpret_cast(msgwnd)); if ((false == arg.ignore) && wd_manager.available(msgwnd)) draw_invoker(&drawer::key_char, msgwnd, arg, &context); @@ -1496,7 +1496,7 @@ namespace detail click_arg.mouse_args = nullptr; click_arg.window_handle = reinterpret_cast(msgwnd); - auto retain = msgwnd->together.events_ptr; + auto retain = msgwnd->annex.events_ptr; if (brock.emit(event_code::click, msgwnd, click_arg, true, &context)) { arg_mouse arg; diff --git a/source/gui/detail/drawer.cpp b/source/gui/detail/drawer.cpp index c7605538..e741692b 100644 --- a/source/gui/detail/drawer.cpp +++ b/source/gui/detail/drawer.cpp @@ -26,7 +26,6 @@ namespace nana typedef detail::edge_nimbus_renderer edge_nimbus_renderer_t; //class drawer_trigger - drawer_trigger::~drawer_trigger(){} void drawer_trigger::attached(widget_reference, graph_reference){} void drawer_trigger::detached(){} //none-const void drawer_trigger::typeface_changed(graph_reference){} @@ -136,23 +135,43 @@ namespace nana typedef bedrock bedrock_type; //class drawer + + enum{ + event_size = static_cast(event_code::end) + }; + + struct drawer::data_implement + { + bool refreshing{ false }; + basic_window* window_handle{ nullptr }; + drawer_trigger* realizer{ nullptr }; + method_state mth_state[event_size]; + std::vector draws; + }; + + drawer::drawer() + : data_impl_{ new data_implement } + {} + drawer::~drawer() { - for(auto p : dynamic_drawing_objects_) + for(auto p : data_impl_->draws) { delete p; } + + delete data_impl_; } void drawer::bind(basic_window* cw) { - core_window_ = cw; + data_impl_->window_handle = cw; } void drawer::typeface_changed() { - if(realizer_) - realizer_->typeface_changed(graphics); + if(data_impl_->realizer) + data_impl_->realizer->typeface_changed(graphics); } void drawer::click(const arg_click& arg) @@ -245,7 +264,7 @@ namespace nana if(wd) { auto iwd = reinterpret_cast(wd); - bool owns_caret = (iwd->together.caret) && (iwd->together.caret->visible()); + bool owns_caret = (iwd->annex.caret_ptr) && (iwd->annex.caret_ptr->visible()); //The caret in X11 is implemented by Nana, it is different from Windows' //the caret in X11 is asynchronous, it is hard to hide and show the caret @@ -254,7 +273,7 @@ namespace nana if(owns_caret) { #ifndef NANA_X11 - iwd->together.caret->visible(false); + iwd->annex.caret_ptr->visible(false); #else owns_caret = nana::detail::platform_spec::instance().caret_update(iwd->root, *iwd->root_graph, false); #endif @@ -265,7 +284,7 @@ namespace nana if(owns_caret) { #ifndef NANA_X11 - iwd->together.caret->visible(true); + iwd->annex.caret_ptr->visible(true); #else nana::detail::platform_spec::instance().caret_update(iwd->root, *iwd->root_graph, true); #endif @@ -275,39 +294,39 @@ namespace nana void drawer::refresh() { - if(realizer_ && (refreshing_ == false)) + if (data_impl_->realizer && !data_impl_->refreshing) { - refreshing_ = true; + data_impl_->refreshing = true; _m_bground_pre(); - realizer_->refresh(graphics); + data_impl_->realizer->refresh(graphics); _m_draw_dynamic_drawing_object(); _m_bground_end(); graphics.flush(); - refreshing_ = false; + data_impl_->refreshing = false; } } drawer_trigger* drawer::realizer() const { - return realizer_; + return data_impl_->realizer; } void drawer::attached(widget& wd, drawer_trigger& realizer) { - for (auto i = std::begin(mth_state_), end = std::end(mth_state_); i != end; ++i) + for (auto i = std::begin(data_impl_->mth_state), end = std::end(data_impl_->mth_state); i != end; ++i) *i = method_state::pending; - realizer_ = &realizer; + data_impl_->realizer = &realizer; realizer._m_reset_overrided(); realizer.attached(wd, graphics); } drawer_trigger* drawer::detached() { - if(realizer_) + if (data_impl_->realizer) { - auto rmp = realizer_; - realizer_ = nullptr; + auto rmp = data_impl_->realizer; + data_impl_->realizer = nullptr; rmp->detached(); return rmp; } @@ -317,7 +336,7 @@ namespace nana void drawer::clear() { std::vector then; - for(auto p : dynamic_drawing_objects_) + for (auto p : data_impl_->draws) { if(p->diehard()) then.push_back(p); @@ -325,7 +344,7 @@ namespace nana delete p; } - then.swap(dynamic_drawing_objects_); + then.swap(data_impl_->draws); } void* drawer::draw(std::function && f, bool diehard) @@ -333,7 +352,7 @@ namespace nana if(f) { auto p = new dynamic_drawing::user_draw_function(std::move(f), diehard); - dynamic_drawing_objects_.push_back(p); + data_impl_->draws.push_back(p); return (diehard ? p : nullptr); } return nullptr; @@ -343,11 +362,11 @@ namespace nana { if(p) { - for (auto i = dynamic_drawing_objects_.begin(); i != dynamic_drawing_objects_.end(); ++i) + for (auto i = data_impl_->draws.begin(); i != data_impl_->draws.end(); ++i) if (*i == p) { delete (*i); - dynamic_drawing_objects_.erase(i); + data_impl_->draws.erase(i); break; } } @@ -355,25 +374,25 @@ namespace nana void drawer::_m_bground_pre() { - if(core_window_->effect.bground && core_window_->effect.bground_fade_rate < 0.01) - core_window_->other.glass_buffer.paste(graphics, 0, 0); + if (data_impl_->window_handle->effect.bground && data_impl_->window_handle->effect.bground_fade_rate < 0.01) + data_impl_->window_handle->other.glass_buffer.paste(graphics, 0, 0); } void drawer::_m_bground_end() { - if(core_window_->effect.bground && core_window_->effect.bground_fade_rate >= 0.01) - core_window_->other.glass_buffer.blend(::nana::rectangle{ core_window_->other.glass_buffer.size() }, graphics, nana::point(), core_window_->effect.bground_fade_rate); + if (data_impl_->window_handle->effect.bground && data_impl_->window_handle->effect.bground_fade_rate >= 0.01) + data_impl_->window_handle->other.glass_buffer.blend(::nana::rectangle{ data_impl_->window_handle->other.glass_buffer.size() }, graphics, nana::point(), data_impl_->window_handle->effect.bground_fade_rate); } void drawer::_m_draw_dynamic_drawing_object() { - for(auto * dw : dynamic_drawing_objects_) + for (auto * dw : data_impl_->draws) dw->draw(graphics); } bool drawer::_m_lazy_decleared() const { - return (basic_window::update_state::refresh == core_window_->other.upd_state); + return (basic_window::update_state::refresh == data_impl_->window_handle->other.upd_state); } }//end namespace detail }//end namespace nana diff --git a/source/gui/detail/window_layout.cpp b/source/gui/detail/window_layout.cpp index 509e3142..ea574baa 100644 --- a/source/gui/detail/window_layout.cpp +++ b/source/gui/detail/window_layout.cpp @@ -66,6 +66,7 @@ namespace nana nana::point p_src; for (auto & el : blocks) { +#ifndef WIDGET_FRAME_DEPRECATED if (category::flags::frame == el.window->other.category) { native_window_type container = el.window->other.attribute.frame->container; @@ -73,6 +74,7 @@ namespace nana graph.bitblt(el.r, container); } else +#endif { p_src.x = el.r.x - el.window->pos_root.x; p_src.y = el.r.y - el.window->pos_root.y; diff --git a/source/gui/detail/window_manager.cpp b/source/gui/detail/window_manager.cpp index 0d173e0c..0af79eb8 100644 --- a/source/gui/detail/window_manager.cpp +++ b/source/gui/detail/window_manager.cpp @@ -237,7 +237,7 @@ namespace detail switch(evtid) { case event_code::mouse_drop: - wd->flags.dropable = (is_make || (0 != wd->together.events_ptr->mouse_dropfiles.length())); + wd->flags.dropable = (is_make || (0 != wd->annex.events_ptr->mouse_dropfiles.length())); break; default: break; @@ -277,8 +277,12 @@ namespace detail if (owner->flags.destroying) throw std::runtime_error("the specified owner is destory"); +#ifndef WIDGET_FRAME_DEPRECATED native = (category::flags::frame == owner->other.category ? owner->other.attribute.frame->container : owner->root_widget->root); +#else + native = owner->root_widget->root; +#endif r.x += owner->pos_root.x; r.y += owner->pos_root.y; } @@ -311,8 +315,10 @@ namespace detail wd->bind_native_window(result.native_handle, result.width, result.height, result.extra_width, result.extra_height, value->root_graph); impl_->wd_register.insert(wd, wd->thread_id); +#ifndef WIDGET_FRAME_DEPRECATED if (owner && (category::flags::frame == owner->other.category)) insert_frame(owner, wd); +#endif bedrock::inc_window(wd->thread_id); this->icon(wd, impl_->default_icon_small, impl_->default_icon_big); @@ -321,6 +327,7 @@ namespace detail return nullptr; } +#ifndef WIDGET_FRAME_DEPRECATED window_manager::core_window_t* window_manager::create_frame(core_window_t* parent, const rectangle& r, widget* wdg) { //Thread-Safe Required! @@ -337,6 +344,7 @@ namespace detail return (wd); } + bool window_manager::insert_frame(core_window_t* frame, native_window wd) { if(frame) @@ -367,6 +375,7 @@ namespace detail } return false; } +#endif window_manager::core_window_t* window_manager::create_widget(core_window_t* parent, const rectangle& r, bool is_lite, widget* wdg) { @@ -461,7 +470,11 @@ namespace detail std::lock_guard lock(mutex_); if (impl_->wd_register.available(wd) == false) return; +#ifndef WIDGET_FRAME_DEPRECATED if((category::flags::root == wd->other.category) || (category::flags::frame != wd->other.category)) +#else + if (category::flags::root == wd->other.category) +#endif { impl_->misc_register.erase(wd->root); impl_->wd_register.remove(wd); @@ -498,6 +511,7 @@ namespace detail if(visible != wd->visible) { +#ifndef WIDGET_FRAME_DEPRECATED native_window_type nv = nullptr; switch(wd->other.category) { @@ -508,6 +522,9 @@ namespace detail default: //category::widget_tag, category::lite_widget_tag break; } +#else + auto nv = (category::flags::root == wd->other.category ? wd->root : nullptr); +#endif if(visible && wd->effect.bground) window_layer::make_bground(wd); @@ -717,12 +734,14 @@ namespace detail if(false == passive) native_interface::window_size(wd->root, sz + nana::size(wd->extra_width, wd->extra_height)); } +#ifndef WIDGET_FRAME_DEPRECATED else if(category::flags::frame == wd->other.category) { native_interface::window_size(wd->other.attribute.frame->container, sz); for(auto natwd : wd->other.attribute.frame->attach) native_interface::window_size(natwd, sz); } +#endif else { //update the bground buffer of glass window. @@ -943,8 +962,8 @@ namespace detail if (impl_->wd_register.available(prev_focus)) { - if(prev_focus->together.caret) - prev_focus->together.caret->set_active(false); + if(prev_focus->annex.caret_ptr) + prev_focus->annex.caret_ptr->activate(false); arg.getting = false; arg.window_handle = reinterpret_cast(prev_focus); @@ -961,8 +980,8 @@ namespace detail return prev_focus; //no new focus_window - if(wd->together.caret) - wd->together.caret->set_active(true); + if(wd->annex.caret_ptr) + wd->annex.caret_ptr->activate(true); arg.window_handle = reinterpret_cast(wd); arg.getting = true; @@ -1446,6 +1465,7 @@ namespace detail } } +#ifndef WIDGET_FRAME_DEPRECATED if (category::flags::frame == wd->other.category) { //remove the frame handle from the WM frames manager. @@ -1454,6 +1474,7 @@ namespace detail if (established) pa_root_attr->frames.push_back(wd); } +#endif if (established) { @@ -1507,11 +1528,11 @@ namespace detail wd->flags.destroying = true; - if(wd->together.caret) + if(wd->annex.caret_ptr) { //The deletion of caret wants to know whether the window is destroyed under SOME platform. Such as X11 - delete wd->together.caret; - wd->together.caret = nullptr; + delete wd->annex.caret_ptr; + wd->annex.caret_ptr = nullptr; } arg_destroy arg; @@ -1552,6 +1573,7 @@ namespace detail wd->drawer.detached(); wd->widget_notifier->destroy(); +#ifndef WIDGET_FRAME_DEPRECATED if(category::flags::frame == wd->other.category) { //The frame widget does not have an owner, and close their element windows without activating owner. @@ -1561,6 +1583,7 @@ namespace detail native_interface::close_window(wd->other.attribute.frame->container); } +#endif if(wd->other.category != category::flags::root) //Not a root window impl_->wd_register.remove(wd); @@ -1571,13 +1594,18 @@ namespace detail if(category::flags::root != wd->other.category) //A root widget always starts at (0, 0) and its childs are not to be changed { wd->pos_root += delta; +#ifndef WIDGET_FRAME_DEPRECATED if (category::flags::frame != wd->other.category) { - if (wd->together.caret && wd->together.caret->visible()) - wd->together.caret->update(); + if (wd->annex.caret_ptr && wd->annex.caret_ptr->visible()) + wd->annex.caret_ptr->update(); } else native_interface::move_window(wd->other.attribute.frame->container, wd->pos_root.x, wd->pos_root.y); +#else + if (wd->annex.caret_ptr && wd->annex.caret_ptr->visible()) + wd->annex.caret_ptr->update(); +#endif if (wd->displayed() && wd->effect.bground) window_layer::make_bground(wd); diff --git a/source/gui/programming_interface.cpp b/source/gui/programming_interface.cpp index ffcec9a0..4485b260 100644 --- a/source/gui/programming_interface.cpp +++ b/source/gui/programming_interface.cpp @@ -57,7 +57,7 @@ namespace API { ::nana::widget_geometrics* make_scheme(::nana::detail::scheme_factory_interface&& factory) { - return restrict::bedrock.make_scheme(static_cast<::nana::detail::scheme_factory_interface&&>(factory)); + return restrict::bedrock.scheme().create(static_cast<::nana::detail::scheme_factory_interface&&>(factory)); } bool emit_event(event_code evt_code, window wd, const ::nana::event_arg& arg) @@ -89,7 +89,7 @@ namespace API if (!restrict::wd_manager().available(reinterpret_cast(wd))) return nullptr; - return reinterpret_cast(wd)->together.events_ptr.get(); + return reinterpret_cast(wd)->annex.events_ptr.get(); } }//end namespace detail @@ -200,14 +200,14 @@ namespace API auto iwd = reinterpret_cast(wd); internal_scope_guard lock; if (restrict::wd_manager().available(iwd)) - iwd->scheme = wdg_geom; + iwd->annex.scheme = wdg_geom; } widget_geometrics* get_scheme(window wd) { auto iwd = reinterpret_cast(wd); internal_scope_guard lock; - return (restrict::wd_manager().available(iwd) ? iwd->scheme : nullptr); + return (restrict::wd_manager().available(iwd) ? iwd->annex.scheme : nullptr); } void attach_drawer(widget& wd, drawer_trigger& dr) @@ -217,7 +217,7 @@ namespace API if(restrict::wd_manager().available(iwd)) { iwd->drawer.graphics.make(iwd->dimension); - iwd->drawer.graphics.rectangle(true, iwd->scheme->background.get_color()); + iwd->drawer.graphics.rectangle(true, iwd->annex.scheme->background.get_color()); iwd->drawer.attached(wd, dr); iwd->drawer.refresh(); //Always redrawe no matter it is visible or invisible. This can make the graphics data correctly. } @@ -266,10 +266,12 @@ namespace API return reinterpret_cast(restrict::wd_manager().create_widget(reinterpret_cast(parent), r, true, wdg)); } +#ifndef WIDGET_FRAME_DEPRECATED window create_frame(window parent, const rectangle& r, widget* wdg) { return reinterpret_cast(restrict::wd_manager().create_frame(reinterpret_cast(parent), r, wdg)); } +#endif paint::graphics* window_graphics(window wd) { @@ -546,6 +548,7 @@ namespace API reinterpret_cast(wd)->flags.fullscreen = v; } +#ifndef WIDGET_FRAME_DEPRECATED bool insert_frame(window frame, native_window_type native_window) { return restrict::wd_manager().insert_frame(reinterpret_cast(frame), native_window); @@ -571,6 +574,7 @@ namespace API } return nullptr; } +#endif void close_window(window wd) { @@ -1022,7 +1026,7 @@ namespace API { internal_scope_guard lock; if (restrict::wd_manager().available(reinterpret_cast(wd))) - return reinterpret_cast(wd)->scheme->foreground.get_color(); + return reinterpret_cast(wd)->annex.scheme->foreground.get_color(); return{}; } @@ -1032,10 +1036,10 @@ namespace API internal_scope_guard lock; if (restrict::wd_manager().available(iwd)) { - auto prev = iwd->scheme->foreground.get_color(); + auto prev = iwd->annex.scheme->foreground.get_color(); if (prev != clr) { - iwd->scheme->foreground = clr; + iwd->annex.scheme->foreground = clr; restrict::wd_manager().update(iwd, true, false); } return prev; @@ -1047,7 +1051,7 @@ namespace API { internal_scope_guard lock; if (restrict::wd_manager().available(reinterpret_cast(wd))) - return reinterpret_cast(wd)->scheme->background.get_color(); + return reinterpret_cast(wd)->annex.scheme->background.get_color(); return{}; } @@ -1057,10 +1061,10 @@ namespace API internal_scope_guard lock; if (restrict::wd_manager().available(iwd)) { - auto prev = iwd->scheme->background.get_color(); + auto prev = iwd->annex.scheme->background.get_color(); if (prev != clr) { - iwd->scheme->background = clr; + iwd->annex.scheme->background = clr; //If the bground mode of this window is basic, it should remake the background if (iwd->effect.bground && iwd->effect.bground_fade_rate < 0.01) // fade rate < 0.01 means it is basic mode @@ -1077,7 +1081,7 @@ namespace API { internal_scope_guard lock; if (restrict::wd_manager().available(reinterpret_cast(wd))) - return reinterpret_cast(wd)->scheme->activated.get_color(); + return reinterpret_cast(wd)->annex.scheme->activated.get_color(); return{}; } @@ -1087,10 +1091,10 @@ namespace API internal_scope_guard lock; if (restrict::wd_manager().available(iwd)) { - auto prev = iwd->scheme->activated.get_color(); + auto prev = iwd->annex.scheme->activated.get_color(); if (prev != clr) { - iwd->scheme->activated = clr; + iwd->annex.scheme->activated = clr; restrict::wd_manager().update(iwd, true, false); } return prev; @@ -1099,12 +1103,99 @@ namespace API return{}; } - void create_caret(window wd, unsigned width, unsigned height) + class caret_proxy + : public caret_interface + { + public: + caret_proxy(basic_window* wd) + : window_{ wd } + {} + + void disable_throw() noexcept override + { + throw_ = false; + } + + void effective_range(const rectangle& range) override + { + internal_scope_guard lock; + auto caret = _m_caret(); + if (caret) + caret->effective_range(range); + } + + void position(const point& pos) override + { + internal_scope_guard lock; + auto caret = _m_caret(); + if (caret) + caret->position(pos); + } + + point position() const override + { + internal_scope_guard lock; + auto caret = _m_caret(); + if (caret) + return caret->position(); + + return{}; + } + + void dimension(const size& size) override + { + internal_scope_guard lock; + auto caret = _m_caret(); + if (caret) + caret->dimension(size); + } + + size dimension() const override + { + internal_scope_guard lock; + auto caret = _m_caret(); + if (caret) + return caret->dimension(); + + return{}; + } + + void visible(bool visibility) override + { + internal_scope_guard lock; + auto caret = _m_caret(); + if (caret) + caret->visible(visibility); + } + + bool visible() const override + { + internal_scope_guard lock; + auto caret = _m_caret(); + return (caret && caret->visible()); + } + private: + caret_interface* _m_caret() const + { + if (restrict::wd_manager().available(window_) && window_->annex.caret_ptr) + return window_->annex.caret_ptr; + + if (throw_) + throw std::runtime_error("nana.api: access invalid caret"); + + return nullptr; + } + private: + basic_window* const window_; + bool throw_{ true }; + }; + + void create_caret(window wd, const size& caret_size) { auto iwd = reinterpret_cast(wd); internal_scope_guard lock; - if(restrict::wd_manager().available(iwd) && (nullptr == iwd->together.caret)) - iwd->together.caret = new ::nana::detail::caret_descriptor(iwd, width, height); + if (restrict::wd_manager().available(iwd) && !(iwd->annex.caret_ptr)) + iwd->annex.caret_ptr = new ::nana::detail::caret(iwd, caret_size); } void destroy_caret(window wd) @@ -1113,72 +1204,19 @@ namespace API internal_scope_guard lock; if(restrict::wd_manager().available(iwd)) { - auto p = iwd->together.caret; - iwd->together.caret = nullptr; + auto p = iwd->annex.caret_ptr; + iwd->annex.caret_ptr = nullptr; delete p; } } - void caret_pos(window wd, const point& pos) - { - auto iwd = reinterpret_cast(wd); - internal_scope_guard lock; - if(restrict::wd_manager().available(iwd) && iwd->together.caret) - iwd->together.caret->position(pos.x, pos.y); - } + std::unique_ptr open_caret(window window_handle, bool disable_throw) + { + auto p = new caret_proxy{ reinterpret_cast(window_handle) }; + if (disable_throw) + p->disable_throw(); - nana::point caret_pos(window wd) - { - auto iwd = reinterpret_cast(wd); - internal_scope_guard lock; - if(restrict::wd_manager().available(iwd) && iwd->together.caret) - return iwd->together.caret->position(); - - return{}; - } - - void caret_effective_range(window wd, const nana::rectangle& rect) - { - auto iwd = reinterpret_cast(wd); - internal_scope_guard lock; - if(restrict::wd_manager().available(iwd) && iwd->together.caret) - iwd->together.caret->effective_range(rect); - } - - void caret_size(window wd, const nana::size& sz) - { - auto iwd = reinterpret_cast(wd); - internal_scope_guard isg; - if(restrict::wd_manager().available(iwd) && iwd->together.caret) - iwd->together.caret->size(sz); - } - - nana::size caret_size(window wd) - { - auto iwd = reinterpret_cast(wd); - internal_scope_guard lock; - if(restrict::wd_manager().available(iwd) && iwd->together.caret) - return iwd->together.caret->size(); - - return{}; - } - - void caret_visible(window wd, bool is_show) - { - auto iwd = reinterpret_cast(wd); - internal_scope_guard lock; - if(restrict::wd_manager().available(iwd) && iwd->together.caret) - iwd->together.caret->visible(is_show); - } - - bool caret_visible(window wd) - { - auto iwd = reinterpret_cast(wd); - internal_scope_guard lock; - if(restrict::wd_manager().available(iwd) && iwd->together.caret) - return iwd->together.caret->visible(); - - return false; + return std::unique_ptr{ p }; } void tabstop(window wd) diff --git a/source/gui/widgets/form.cpp b/source/gui/widgets/form.cpp index af43ea37..7f8247ff 100644 --- a/source/gui/widgets/form.cpp +++ b/source/gui/widgets/form.cpp @@ -28,27 +28,61 @@ namespace nana { graph.rectangle(true, API::bgcolor(*wd_)); } + //end class trigger + + //class form_base + form_base::form_base(window owner, bool nested, const rectangle& r, const appearance& app) + : widget_object(owner, nested, r, app) + {} + + place & form_base::get_place() + { + if (this->empty()) + throw std::runtime_error("form::get_plac: the form has destroyed."); + + if (!place_) + place_.reset(new place{ *this }); + + return *place_; + } + + void form_base::div(const char* div_text) + { + get_place().div(div_text); + } + + place::field_reference form_base::operator[](const char* field_name) + { + return get_place()[field_name]; + } + + void form_base::collocate() noexcept + { + if (place_) + place_->collocate(); + } + //end class form_base }//end namespace form }//end namespace drawerbase //class form - typedef widget_object form_base_t; + using form_base = drawerbase::form::form_base; form::form(const form& fm, const ::nana::size& sz, const appearance& apr) - : form_base_t(fm.handle(), false, API::make_center(fm.handle(), sz.width, sz.height), apr) + : form_base(fm.handle(), false, API::make_center(fm.handle(), sz.width, sz.height), apr) { } form::form(const rectangle& r, const appearance& apr) - : form_base_t(nullptr, false, r, apr) + : form_base(nullptr, false, r, apr) {} form::form(window owner, const ::nana::size& sz, const appearance& apr) - : form_base_t(owner, false, API::make_center(owner, sz.width, sz.height), apr) + : form_base(owner, false, API::make_center(owner, sz.width, sz.height), apr) {} form::form(window owner, const rectangle& r, const appearance& apr) - : form_base_t(owner, false, r, apr) + : form_base(owner, false, r, apr) {} void form::modality() const @@ -64,21 +98,21 @@ namespace nana //class nested_form nested_form::nested_form(const form& fm, const rectangle& r, const appearance& apr) - : form_base_t(fm.handle(), true, r, apr) + : form_base(fm.handle(), true, r, apr) { } nested_form::nested_form(const nested_form& fm, const rectangle& r, const appearance& apr) - : form_base_t(fm.handle(), true, r, apr) + : form_base(fm.handle(), true, r, apr) { } nested_form::nested_form(window owner, const appearance& apr) - : form_base_t(owner, true, rectangle(), apr) + : form_base(owner, true, rectangle(), apr) {} nested_form::nested_form(window owner, const rectangle& r, const appearance& apr) - : form_base_t(owner, true, r, apr) + : form_base(owner, true, r, apr) {} //end nested_form }//end namespace nana diff --git a/source/gui/widgets/frame.cpp b/source/gui/widgets/frame.cpp index 27121345..7b9e7af2 100644 --- a/source/gui/widgets/frame.cpp +++ b/source/gui/widgets/frame.cpp @@ -13,6 +13,8 @@ #include +#ifndef WIDGET_FRAME_DEPRECATED + namespace nana { //class frame:: public widget_object @@ -45,3 +47,5 @@ namespace nana //end class frame }//end namespace nana +#endif + diff --git a/source/gui/widgets/skeletons/text_editor.cpp b/source/gui/widgets/skeletons/text_editor.cpp index 32bd6e6a..341fa22d 100644 --- a/source/gui/widgets/skeletons/text_editor.cpp +++ b/source/gui/widgets/skeletons/text_editor.cpp @@ -376,9 +376,7 @@ namespace nana{ namespace widgets auto str_px = static_cast(editor_._m_text_extent_size(ent.begin, len).width); if (scrpos.x < str_px) { - std::unique_ptr pxbuf(new unsigned[len]); - - res.x = editor_._m_char_by_pixels(ent.begin, len, pxbuf.get(), str_px, scrpos.x, is_right_text(ent)); + res.x = editor_._m_char_by_pixels(ent, static_cast(scrpos.x)); res.x += static_cast(ent.begin - lnstr.data()); return res; } @@ -837,9 +835,7 @@ namespace nana{ namespace widgets auto str_px = static_cast(editor_._m_text_extent_size(ent.begin, len).width); if (scrpos.x < str_px) { - std::unique_ptr pxbuf(new unsigned[len]); - - res.x += editor_._m_char_by_pixels(ent.begin, len, pxbuf.get(), str_px, scrpos.x, is_right_text(ent)); + res.x += editor_._m_char_by_pixels(ent, scrpos.x); res.x += static_cast(ent.begin - str); return res; } @@ -1281,7 +1277,9 @@ namespace nana{ namespace widgets //class text_editor text_editor::text_editor(window wd, graph_reference graph, const text_editor_scheme* schm) : behavior_(new behavior_normal(*this)), - window_(wd), graph_(graph), + window_(wd), + caret_(API::open_caret(wd, true)), + graph_(graph), scheme_(schm), keywords_(new keywords) { text_area_.area = graph.size(); @@ -1295,7 +1293,7 @@ namespace nana{ namespace widgets select_.mode_selection = selection::mode::no_selected; select_.ignore_press = false; - API::create_caret(wd, 1, line_height()); + API::create_caret(wd, { 1, line_height() }); API::bgcolor(wd, colors::white); API::fgcolor(wd, colors::black); @@ -1864,18 +1862,17 @@ namespace nana{ namespace widgets { visible = true; if (line_bottom > _m_end_pos(false)) - API::caret_size(window_, nana::size(1, line_pixels - (line_bottom - _m_end_pos(false)))); - else if (API::caret_size(window_).height != line_pixels) + caret_->dimension(nana::size(1, line_pixels - (line_bottom - _m_end_pos(false)))); + else if (caret_->dimension().height != line_pixels) reset_caret_pixels(); } if(!attributes_.editable) visible = false; - API::caret_visible(window_, visible); - + caret_->visible(visible); if(visible) - API::caret_pos(window_, pos); + caret_->position(pos); } void text_editor::move_caret_end() @@ -1887,7 +1884,7 @@ namespace nana{ namespace widgets void text_editor::reset_caret_pixels() const { - API::caret_size(window_, nana::size(1, line_height())); + caret_->dimension({ 1, line_height() }); } void text_editor::reset_caret() @@ -1898,7 +1895,7 @@ namespace nana{ namespace widgets void text_editor::show_caret(bool isshow) { if(isshow == false || API::is_focus_ready(window_)) - API::caret_visible(window_, isshow); + caret_->visible(isshow); } bool text_editor::selected() const @@ -2004,7 +2001,7 @@ namespace nana{ namespace widgets if (attributes_.line_wrapped) exclude_px = text_area_.vscroll; else - exclude_px = API::caret_size(window_).width; + exclude_px = caret_->dimension().width; return (text_area_.area.width > exclude_px ? text_area_.area.width - exclude_px : 0); } @@ -3452,42 +3449,48 @@ namespace nana{ namespace widgets points_.offset.y = y; } - unsigned text_editor::_m_char_by_pixels(const wchar_t* str, std::size_t len, unsigned * pxbuf, int str_px, int pixels, bool is_rtl) + unsigned text_editor::_m_char_by_pixels(const unicode_bidi::entity& ent, unsigned pos) { - if (graph_.glyph_pixels(str, len, pxbuf)) - { - if (is_rtl) - { //RTL - for (std::size_t u = 0; u < len; ++u) - { - auto px = static_cast(pxbuf[u]); - auto chbeg = str_px - px; - if (chbeg <= pixels && pixels < str_px) - { - if ((px < 2) || (pixels <= chbeg + (px >> 1))) - return static_cast(u + 1); + unsigned len = ent.end - ent.begin; - return static_cast(u); + std::unique_ptr pxbuf(new unsigned[len]); + if (graph_.glyph_pixels(ent.begin, len, pxbuf.get())) + { + const auto px_end = pxbuf.get() + len; + + if (is_right_text(ent)) + { + auto total_px = std::accumulate(pxbuf.get(), px_end, static_cast(0)); + + for (auto p = pxbuf.get(); p != px_end; ++p) + { + auto chpos = total_px - *p; + if ((chpos <= pos) && (pos < total_px)) + { + if ((*p < 2) || (pos <= chpos + (*p >> 1))) + return static_cast(p - pxbuf.get()) + 1; + + return static_cast(p - pxbuf.get()); } - str_px = chbeg; + total_px = chpos; } } else { - //LTR - for (std::size_t u = 0; u < len; ++u) + for (auto p = pxbuf.get(); p != px_end; ++p) { - auto px = static_cast(pxbuf[u]); - if (pixels < px) + if (pos < *p) { - if ((px > 1) && (pixels > (px >> 1))) - return static_cast(u + 1); - return static_cast(u); + if ((*p > 1) && (pos >(*p >> 1))) + return static_cast(p - pxbuf.get()) + 1; + return static_cast(p - pxbuf.get()); } - pixels -= px; + + pos -= *p; } } } + return 0; } diff --git a/source/paint/pixel_buffer.cpp b/source/paint/pixel_buffer.cpp index 23a8b4e5..f29c4068 100644 --- a/source/paint/pixel_buffer.cpp +++ b/source/paint/pixel_buffer.cpp @@ -48,6 +48,7 @@ namespace nana{ namespace paint struct pixel_buffer::pixel_buffer_storage : private nana::noncopyable { + pixel_buffer_storage(const pixel_buffer_storage& other) = delete; pixel_buffer_storage& operator=(const pixel_buffer_storage&) = delete; bool _m_alloc() @@ -112,18 +113,6 @@ namespace nana{ namespace paint } }img_pro; - pixel_buffer_storage(const pixel_buffer_storage& other) : - drawable{ other.drawable }, - valid_r{ other.valid_r }, - pixel_size{ other.pixel_size }, - bytes_per_line{ other.bytes_per_line }, - alpha_channel{ other.alpha_channel }, - img_pro{ other.img_pro } - { - if (_m_alloc()) - std::memcpy(raw_pixel_buffer, other.raw_pixel_buffer, pixel_size.width * pixel_size.height); - } - pixel_buffer_storage(std::size_t width, std::size_t height) : drawable(nullptr), valid_r(0, 0, static_cast(width), static_cast(height)),