#include #include 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_(false), real_visible_state_(false), out_of_range_(false) {} caret_descriptor::~caret_descriptor() { if(wd_) native_interface::caret_destroy(wd_->root); } void caret_descriptor::set_active(bool active) { if(wd_) { if(active) { native_interface::caret_create(wd_->root, size_.width, size_.height); real_visible_state_ = false; visible_ = false; this->position(point_.x, point_.y); } else native_interface::caret_destroy(wd_->root); wd_->root_widget->other.attribute.root->ime_enabled = active; } } auto caret_descriptor::window() const ->core_window_t* { return wd_; } void caret_descriptor::position(int x, int y) { point_.x = x; point_.y = y; update(); } void caret_descriptor::effective_range(nana::rectangle rect) { //Chech rect if( (rect.width && rect.height) && (rect.x + rect.width > 0) && (rect.y + rect.height > 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 isshow) { if(visible_ != isshow) { visible_ = isshow; if(visible_ == false || false == out_of_range_) _m_visible(isshow); } } bool caret_descriptor::visible() const { return visible_; } nana::size caret_descriptor::size() const { return size_; } void caret_descriptor::size(const nana::size& s) { size_ = s; update(); if(visible_) this->visible(true); } void caret_descriptor::_m_visible(bool isshow) { if(real_visible_state_ != isshow) { real_visible_state_ = isshow; native_interface::caret_visible(wd_->root, isshow); } } 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) { rect.x = rect.y = 0; rect = wd_->dimension; } else { pos.x += effective_range_.x; pos.y += effective_range_.y; } if( (pos.x + static_cast(size.width) <= rect.x) || (pos.x >= rect.x + static_cast(rect.width)) || (pos.y + static_cast(size.height) <= rect.y) || (pos.y >= rect.y + static_cast(rect.height)) ) {//Out of Range without overlap if(false == out_of_range_) { out_of_range_ = true; if(visible_) _m_visible(false); } } else { if(pos.x < rect.x) { size.width -= (rect.x - pos.x); pos.x = rect.x; } else if(pos.x + size.width > rect.x + rect.width) { size.width -= pos.x + size.width - (rect.x + rect.width); } if(pos.y < rect.y) { size.width -= (rect.y - pos.y); pos.y = rect.y; } else if(pos.y + size.height > rect.y + rect.height) size.height -= pos.y + size.height - (rect.y + rect.height); if(out_of_range_) { if(paint_size_ == size) _m_visible(true); out_of_range_ = false; } if(paint_size_ != size) { native_interface::caret_destroy(wd_->root); native_interface::caret_create(wd_->root, size.width, size.height); real_visible_state_ = false; if(visible_) _m_visible(true); paint_size_ = size; } native_interface::caret_pos(wd_->root, wd_->pos_root.x + pos.x, wd_->pos_root.y + pos.y); } } //end class caret_descriptor //struct basic_window //struct basic_window::other_tag basic_window::other_tag::other_tag(category::flags categ) : category(categ), active_window(nullptr), upd_state(update_state::none) { switch(categ) { case category::root_tag::value: attribute.root = new attr_root_tag; attribute.root->context.focus_changed = false; break; case category::frame_tag::value: attribute.frame = new attr_frame_tag; break; default: attribute.root = nullptr; } } basic_window::other_tag::~other_tag() { switch(category) { case category::root_tag::value: delete attribute.root; break; case category::frame_tag::value: delete attribute.frame; break; default: break; } } //end struct basic_window::other_tag //basic_window //@brief: constructor for the root window basic_window::basic_window(basic_window* owner, widget* wdg, category::root_tag**) : widget_ptr(wdg), other(category::root_tag::value) { drawer.bind(this); _m_init_pos_and_size(0, rectangle()); this->_m_initialize(owner); } basic_window::~basic_window() { delete together.caret; together.caret = nullptr; delete effect.bground; effect.bground = nullptr; } //bind_native_window //@brief: bind a native window and baisc_window void basic_window::bind_native_window(native_window_type wd, unsigned width, unsigned height, unsigned extra_width, unsigned extra_height, nana::paint::graphics& graphics) { if(category::root_tag::value == this->other.category) { this->root = wd; dimension.width = width; dimension.height = height; this->extra_width = extra_width; this->extra_height = extra_height; this->root_widget = this; this->root_graph = &graphics; } } void basic_window::frame_window(native_window_type wd) { if(category::frame_tag::value == this->other.category) other.attribute.frame->container = wd; } bool basic_window::is_ancestor_of(const basic_window* wd) const { while (wd) { if (this == wd->parent) return true; wd = wd->parent; } return false; } bool basic_window::visible_parents() const { for (auto pnt = parent; pnt; pnt = pnt->parent) { if (!pnt->visible) return false; } return true; } bool basic_window::belong_to_lazy() const { for (auto wd = this; wd; wd = wd->parent) { if (basic_window::update_state::refresh == wd->other.upd_state) return true; } return false; } void basic_window::_m_init_pos_and_size(basic_window* parent, const rectangle& r) { pos_owner = pos_root = r; dimension = r; if(parent) { pos_root.x += parent->pos_root.x; pos_root.y += parent->pos_root.y; } } void basic_window::_m_initialize(basic_window* agrparent) { if(other.category == category::root_tag::value) { if(agrparent && (nana::system::this_thread_id() != agrparent->thread_id)) agrparent = nullptr; while(agrparent && (agrparent->other.category != category::root_tag::value)) agrparent = agrparent->parent; owner = agrparent; parent = nullptr; index = 0; } else { parent = agrparent; owner = nullptr; root_widget = agrparent->root_widget; root = agrparent->root; root_graph = agrparent->root_graph; index = static_cast(agrparent->children.size()); agrparent->children.push_back(this); } predef_cursor = cursor::arrow; flags.capture = false; flags.dbl_click = true; flags.enabled = true; flags.modal = false; flags.take_active = true; flags.dropable = false; flags.fullscreen = false; flags.tab = nana::detail::tab_type::none; flags.action = mouse_action::normal; flags.refreshing = false; flags.destroying = false; flags.borderless = false; visible = false; //colors.foreground = 0x0; //deprecated //colors.background = nana::color::button_face; //colors.active = 0x60C8FD; colors.fgcolor = ::nana::colors::black; colors.bgcolor = ::nana::colors::button_face; colors.activated.from_rgb(0x60, 0xc8, 0xfd); effect.edge_nimbus = effects::edge_nimbus::none; effect.bground = nullptr; effect.bground_fade_rate = 0; together.caret = nullptr; together.attached_events = nullptr; extra_width = extra_height = 0; //The window must keep its thread_id same as its parent if it is a child. //Otherwise, its root buffer would be mapped repeatly if it is in its parent thread. thread_id = nana::system::this_thread_id(); if(agrparent && (thread_id != agrparent->thread_id)) thread_id = agrparent->thread_id; } bool basic_window::set_events(const std::shared_ptr& p) { if (together.attached_events) return false; together.events_ptr = p; together.attached_events = p.get(); return true; } general_events * basic_window::get_events() const { return together.attached_events; } //end struct basic_window }//end namespace detail }//end namespace nana