first init of 0.9

This commit is contained in:
cnjinhao
2014-12-11 03:32:35 +08:00
commit d0a317bd45
206 changed files with 69773 additions and 0 deletions

View File

@@ -0,0 +1,385 @@
#include <nana/gui/detail/basic_window.hpp>
#include <nana/gui/detail/native_window_interface.hpp>
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<int>(size.width) <= rect.x) || (pos.x >= rect.x + static_cast<int>(rect.width)) ||
(pos.y + static_cast<int>(size.height) <= rect.y) || (pos.y >= rect.y + static_cast<int>(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<unsigned>(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;
color.foreground = 0x0;
color.background = nana::color::button_face;
color.active = 0x60C8FD;
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<general_events>& 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

View File

@@ -0,0 +1,331 @@
/*
* A Bedrock Platform-Independent Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com)
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* @file: nana/gui/detail/bedrock_pi.cpp
*/
#include <nana/config.hpp>
#include PLATFORM_SPEC_HPP
#include GUI_BEDROCK_HPP
#include <nana/gui/detail/event_code.hpp>
#include <nana/system/platform.hpp>
#include <sstream>
#include <nana/system/timepiece.hpp>
#include <nana/gui/wvl.hpp>
#include <nana/gui/detail/inner_fwd_implement.hpp>
#include <nana/gui/detail/native_window_interface.hpp>
#include <nana/gui/layout_utility.hpp>
#include <nana/gui/detail/element_store.hpp>
namespace nana
{
namespace detail
{
void events_operation_register(event_handle evt)
{
bedrock::instance().evt_operation.register_evt(evt);
}
void events_operation_cancel(event_handle evt)
{
bedrock::instance().evt_operation.cancel(evt);
}
void bedrock::event_expose(core_window_t * wd, bool exposed)
{
if (nullptr == wd) return;
wd->visible = exposed;
arg_expose arg;
arg.exposed = exposed;
arg.window_handle = reinterpret_cast<window>(wd);
if (emit(event_code::expose, wd, arg, false, get_thread_context()))
{
if (!exposed)
{
if (category::flags::root != wd->other.category)
{
//If the wd->parent is a lite_widget then find a parent until it is not a lite_widget
wd = wd->parent;
while (category::flags::lite_widget == wd->other.category)
wd = wd->parent;
}
else if (category::flags::frame == wd->other.category)
wd = wd_manager.find_window(wd->root, wd->pos_root.x, wd->pos_root.y);
}
wd_manager.refresh_tree(wd);
wd_manager.map(wd);
}
}
void bedrock::event_move(core_window_t* wd, int x, int y)
{
if (wd)
{
arg_move arg;
arg.window_handle = reinterpret_cast<window>(wd);
arg.x = x;
arg.y = y;
if (emit(event_code::move, wd, arg, false, get_thread_context()))
wd_manager.update(wd, true, true);
}
}
bool bedrock::event_msleave(core_window_t* hovered)
{
if (wd_manager.available(hovered) && hovered->flags.enabled)
{
hovered->flags.action = mouse_action::normal;
arg_mouse arg;
arg.evt_code = event_code::mouse_leave;
arg.window_handle = reinterpret_cast<window>(hovered);
arg.pos.x = arg.pos.y = 0;
arg.left_button = arg.right_button = arg.mid_button = false;
arg.ctrl = arg.shift = false;
emit(event_code::mouse_leave, hovered, arg, true, get_thread_context());
return true;
}
return false;
}
void bedrock::update_cursor(core_window_t * wd)
{
internal_scope_guard isg;
if (wd_manager.available(wd))
{
auto * thrd = get_thread_context(wd->thread_id);
if (nullptr == thrd)
return;
auto pos = native_interface::cursor_position();
auto native_handle = native_interface::find_window(pos.x, pos.y);
if (!native_handle)
return;
native_interface::calc_window_point(native_handle, pos);
if (wd != wd_manager.find_window(native_handle, pos.x, pos.y))
return;
set_cursor(wd, wd->predef_cursor, thrd);
}
}
void bedrock::_m_emit_core(event_code evt_code, core_window_t* wd, bool draw_only, const ::nana::detail::event_arg_interface& event_arg)
{
switch (evt_code)
{
case event_code::click:
case event_code::dbl_click:
case event_code::mouse_enter:
case event_code::mouse_move:
case event_code::mouse_leave:
case event_code::mouse_down:
case event_code::mouse_up:
{
auto arg = dynamic_cast<const arg_mouse*>(&event_arg);
if (nullptr == arg)
return;
void(::nana::detail::drawer::*drawer_event_fn)(const arg_mouse&);
::nana::basic_event<arg_mouse>* evt_addr;
switch (evt_code)
{
case event_code::click:
drawer_event_fn = &drawer::click;
evt_addr = &wd->together.attached_events->click;
break;
case event_code::dbl_click:
drawer_event_fn = &drawer::dbl_click;
evt_addr = &wd->together.attached_events->dbl_click;
break;
case event_code::mouse_enter:
drawer_event_fn = &drawer::mouse_enter;
evt_addr = &wd->together.attached_events->mouse_enter;
break;
case event_code::mouse_move:
drawer_event_fn = &drawer::mouse_move;
evt_addr = &wd->together.attached_events->mouse_move;
break;
case event_code::mouse_leave:
drawer_event_fn = &drawer::mouse_leave;
evt_addr = &wd->together.attached_events->mouse_leave;
break;
case event_code::mouse_down:
drawer_event_fn = &drawer::mouse_down;
evt_addr = &wd->together.attached_events->mouse_down;
break;
case event_code::mouse_up:
drawer_event_fn = &drawer::mouse_up;
evt_addr = &wd->together.attached_events->mouse_up;
break;
default:
throw std::runtime_error("Invalid mouse event code");
}
(wd->drawer.*drawer_event_fn)(*arg);
if (!draw_only)
evt_addr->emit(*arg);
break;
}
case event_code::mouse_wheel:
{
auto arg = dynamic_cast<const arg_wheel*>(&event_arg);
if (arg)
{
wd->drawer.mouse_wheel(*arg);
if (!draw_only)
wd->together.attached_events->mouse_wheel.emit(*arg);
}
break;
}
case event_code::key_press:
case event_code::key_char:
case event_code::key_release:
case event_code::shortkey:
{
auto arg = dynamic_cast<const arg_keyboard*>(&event_arg);
if (nullptr == arg)
return;
void(::nana::detail::drawer::*drawer_event_fn)(const arg_keyboard&);
::nana::basic_event<arg_keyboard>* evt_addr;
switch (evt_code)
{
case event_code::key_press:
drawer_event_fn = &drawer::key_press;
evt_addr = &wd->together.attached_events->key_press;
break;
case event_code::key_char:
drawer_event_fn = &drawer::key_char;
evt_addr = &wd->together.attached_events->key_char;
break;
case event_code::key_release:
drawer_event_fn = &drawer::key_release;
evt_addr = &wd->together.attached_events->key_release;
break;
case event_code::shortkey:
drawer_event_fn = &drawer::shortkey;
evt_addr = &wd->together.attached_events->shortkey;
break;
default:
throw std::runtime_error("Invalid keyboard event code");
}
(wd->drawer.*drawer_event_fn)(*arg);
if (!draw_only)
evt_addr->emit(*arg);
break;
}
case event_code::expose:
if (!draw_only)
{
auto arg = dynamic_cast<const arg_expose*>(&event_arg);
if (arg)
wd->together.attached_events->expose.emit(*arg);
}
break;
case event_code::focus:
{
auto arg = dynamic_cast<const arg_focus*>(&event_arg);
if (arg)
{
wd->drawer.focus(*arg);
if (!draw_only)
wd->together.attached_events->focus.emit(*arg);
}
break;
}
case event_code::move:
{
auto arg = dynamic_cast<const arg_move*>(&event_arg);
if (arg)
{
wd->drawer.move(*arg);
if (!draw_only)
wd->together.attached_events->move.emit(*arg);
}
break;
}
case event_code::resizing:
{
auto arg = dynamic_cast<const arg_resizing*>(&event_arg);
if (arg)
{
wd->drawer.resizing(*arg);
if (!draw_only)
wd->together.attached_events->resizing.emit(*arg);
}
break;
}
case event_code::resized:
{
auto arg = dynamic_cast<const arg_resized*>(&event_arg);
if (arg)
{
wd->drawer.resized(*arg);
if (!draw_only)
wd->together.attached_events->resized.emit(*arg);
}
break;
}
case event_code::unload:
if (!draw_only)
{
auto arg = dynamic_cast<const arg_unload*>(&event_arg);
if (arg && (wd->other.category == category::flags::root))
{
auto evt_ptr = dynamic_cast<events_root_extension*>(wd->together.attached_events);
if (evt_ptr)
evt_ptr->unload.emit(*arg);
}
}
break;
case event_code::destroy:
if (!draw_only)
{
auto arg = dynamic_cast<const arg_destroy*>(&event_arg);
if (arg)
wd->together.attached_events->destroy.emit(*arg);
}
break;
default:
throw std::runtime_error("Invalid event code");
}
}
void bedrock::_m_except_handler()
{
std::vector<core_window_t*> v;
wd_manager.all_handles(v);
if (v.size())
{
std::vector<native_window_type> roots;
native_window_type root = nullptr;
unsigned tid = nana::system::this_thread_id();
for (auto wd : v)
{
if ((wd->thread_id == tid) && (wd->root != root))
{
root = wd->root;
if (roots.cend() == std::find(roots.cbegin(), roots.cend(), root))
roots.push_back(root);
}
}
for (auto i : roots)
interface_type::close_window(i);
}
}
}//end namespace detail
}//end namespace nana

View File

@@ -0,0 +1,23 @@
/*
* Bedrock Selector
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com)
*
* Distributed under the Nana Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://nanapro.sourceforge.net/LICENSE_1_0.txt)
*
* @file: nana/gui/detail/bedrock_selector.cpp
*
* This file is used to support the Nana project of some cross-platform IDE,
*
*/
#include <nana/config.hpp>
#if defined(NANA_WINDOWS)
#include "win32/bedrock.cpp"
#elif defined(NANA_LINUX)
#include "linux_X11/bedrock.cpp"
#endif

View File

@@ -0,0 +1,388 @@
/*
* A Drawer Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com)
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* @file: nana/gui/detail/drawer.cpp
*/
#include <nana/config.hpp>
#include GUI_BEDROCK_HPP
#include <nana/gui/detail/drawer.hpp>
#include <nana/gui/detail/dynamic_drawing_object.hpp>
#include <nana/gui/detail/effects_renderer.hpp>
#include <nana/gui/detail/basic_window.hpp>
#if defined(NANA_X11)
#include <nana/detail/linux_X11/platform_spec.hpp>
#endif
#include <algorithm>
namespace nana
{
typedef detail::edge_nimbus_renderer<detail::bedrock::core_window_t> 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){}
void drawer_trigger::refresh(graph_reference){}
void drawer_trigger::resizing(graph_reference, const arg_resizing&)
{
overrided_ = false;
}
void drawer_trigger::resized(graph_reference graph, const arg_resized&)
{
overrided_ = true;
this->refresh(graph);
detail::bedrock::instance().thread_context_lazy_refresh();
}
void drawer_trigger::move(graph_reference, const arg_move&)
{
overrided_ = false;
}
void drawer_trigger::click(graph_reference, const arg_mouse&)
{
overrided_ = false;
}
void drawer_trigger::dbl_click(graph_reference, const arg_mouse&)
{
overrided_ = false;
}
void drawer_trigger::mouse_enter(graph_reference, const arg_mouse&)
{
overrided_ = false;
}
void drawer_trigger::mouse_move(graph_reference, const arg_mouse&)
{
overrided_ = false;
}
void drawer_trigger::mouse_leave(graph_reference, const arg_mouse&)
{
overrided_ = false;
}
void drawer_trigger::mouse_down(graph_reference, const arg_mouse&)
{
overrided_ = false;
}
void drawer_trigger::mouse_up(graph_reference, const arg_mouse&)
{
overrided_ = false;
}
void drawer_trigger::mouse_wheel(graph_reference, const arg_wheel&)
{
overrided_ = false;
}
void drawer_trigger::mouse_dropfiles(graph_reference, const arg_dropfiles&)
{
overrided_ = false;
}
void drawer_trigger::focus(graph_reference, const arg_focus&)
{
overrided_ = false;
}
void drawer_trigger::key_press(graph_reference, const arg_keyboard&)
{
overrided_ = false;
}
void drawer_trigger::key_char(graph_reference, const arg_keyboard&)
{
overrided_ = false;
}
void drawer_trigger::key_release(graph_reference, const arg_keyboard&)
{
overrided_ = false;
}
void drawer_trigger::shortkey(graph_reference, const arg_keyboard&)
{
overrided_ = false;
}
void drawer_trigger::_m_reset_overrided()
{
overrided_ = true;
}
bool drawer_trigger::_m_overrided() const
{
return overrided_;
}
//end class drawer_trigger
namespace detail
{
typedef bedrock bedrock_type;
//class drawer
drawer::~drawer()
{
for(auto p : dynamic_drawing_objects_)
{
delete p;
}
}
void drawer::bind(basic_window* cw)
{
core_window_ = cw;
}
void drawer::typeface_changed()
{
if(realizer_)
realizer_->typeface_changed(graphics);
}
void drawer::click(const arg_mouse& arg)
{
_m_emit(event_code::click, arg, &drawer_trigger::click);
}
void drawer::dbl_click(const arg_mouse& arg)
{
_m_emit(event_code::dbl_click, arg, &drawer_trigger::dbl_click);
}
void drawer::mouse_enter(const arg_mouse& arg)
{
_m_emit(event_code::mouse_enter, arg, &drawer_trigger::mouse_enter);
}
void drawer::mouse_move(const arg_mouse& arg)
{
_m_emit(event_code::mouse_move, arg, &drawer_trigger::mouse_move);
}
void drawer::mouse_leave(const arg_mouse& arg)
{
_m_emit(event_code::mouse_leave, arg, &drawer_trigger::mouse_leave);
}
void drawer::mouse_down(const arg_mouse& arg)
{
_m_emit(event_code::mouse_down, arg, &drawer_trigger::mouse_down);
}
void drawer::mouse_up(const arg_mouse& arg)
{
_m_emit(event_code::mouse_up, arg, &drawer_trigger::mouse_up);
}
void drawer::mouse_wheel(const arg_wheel& arg)
{
_m_emit(event_code::mouse_wheel, arg, &drawer_trigger::mouse_wheel);
}
void drawer::mouse_dropfiles(const arg_dropfiles& arg)
{
_m_emit(event_code::mouse_drop, arg, &drawer_trigger::mouse_dropfiles);
}
void drawer::resizing(const arg_resizing& arg)
{
_m_emit(event_code::resizing, arg, &drawer_trigger::resizing);
}
void drawer::resized(const arg_resized& arg)
{
_m_emit(event_code::resized, arg, &drawer_trigger::resized);
}
void drawer::move(const arg_move& arg)
{
_m_emit(event_code::move, arg, &drawer_trigger::move);
}
void drawer::focus(const arg_focus& arg)
{
_m_emit(event_code::focus, arg, &drawer_trigger::focus);
}
void drawer::key_press(const arg_keyboard& arg)
{
_m_emit(event_code::key_press, arg, &drawer_trigger::key_press);
}
void drawer::key_char(const arg_keyboard& arg)
{
_m_emit(event_code::key_char, arg, &drawer_trigger::key_char);
}
void drawer::key_release(const arg_keyboard& arg)
{
_m_emit(event_code::key_release, arg, &drawer_trigger::key_release);
}
void drawer::shortkey(const arg_keyboard& arg)
{
_m_emit(event_code::shortkey, arg, &drawer_trigger::shortkey);
}
void drawer::map(window wd) //Copy the root buffer to screen
{
if(wd)
{
bedrock_type::core_window_t* iwd = reinterpret_cast<bedrock_type::core_window_t*>(wd);
bedrock_type::core_window_t * caret_wd = iwd->root_widget->other.attribute.root->focus;
bool owns_caret = (caret_wd && (caret_wd->together.caret) && (caret_wd->together.caret->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
//immediately, and therefore the caret always be flickering when the graphics
//buffer is mapping to the window.
if(owns_caret)
{
#ifndef NANA_X11
caret_wd->together.caret->visible(false);
#else
owns_caret = nana::detail::platform_spec::instance().caret_update(iwd->root, *iwd->root_graph, false);
#endif
}
if(false == edge_nimbus_renderer_t::instance().render(iwd))
{
nana::rectangle vr;
if(bedrock_type::window_manager_t::wndlayout_type::read_visual_rectangle(iwd, vr))
iwd->root_graph->paste(iwd->root, vr, vr.x, vr.y);
}
if(owns_caret)
{
#ifndef NANA_X11
caret_wd->together.caret->visible(true);
#else
nana::detail::platform_spec::instance().caret_update(iwd->root, *iwd->root_graph, true);
#endif
}
}
}
void drawer::refresh()
{
if(realizer_ && (refreshing_ == false))
{
refreshing_ = true;
_m_bground_pre();
realizer_->refresh(graphics);
_m_draw_dynamic_drawing_object();
_m_bground_end();
graphics.flush();
refreshing_ = false;
}
}
drawer_trigger* drawer::realizer() const
{
return realizer_;
}
void drawer::attached(widget& wd, drawer_trigger& realizer)
{
for (auto i = std::begin(mth_state_), end = std::end(mth_state_); i != end; ++i)
*i = method_state::unknown;
realizer_ = &realizer;
realizer.attached(wd, graphics);
}
drawer_trigger* drawer::detached()
{
if(realizer_)
{
auto rmp = realizer_;
realizer_ = nullptr;
rmp->detached();
return rmp;
}
return nullptr;
}
void drawer::clear()
{
std::vector<dynamic_drawing::object*> then;
for(auto p : dynamic_drawing_objects_)
{
if(p->diehard())
then.push_back(p);
else
delete p;
}
then.swap(dynamic_drawing_objects_);
}
void* drawer::draw(std::function<void(paint::graphics&)> && f, bool diehard)
{
if(f)
{
auto p = new dynamic_drawing::user_draw_function(std::move(f), diehard);
dynamic_drawing_objects_.push_back(p);
return (diehard ? p : nullptr);
}
return nullptr;
}
void drawer::erase(void * p)
{
if(p)
{
auto i = std::find(dynamic_drawing_objects_.begin(), dynamic_drawing_objects_.end(), p);
if (i != dynamic_drawing_objects_.end())
{
delete (*i);
dynamic_drawing_objects_.erase(i);
}
}
}
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);
}
void drawer::_m_bground_end()
{
if(core_window_->effect.bground && core_window_->effect.bground_fade_rate >= 0.01)
core_window_->other.glass_buffer.blend(core_window_->other.glass_buffer.size(), graphics, nana::point(), core_window_->effect.bground_fade_rate);
}
void drawer::_m_draw_dynamic_drawing_object()
{
for(auto * dw : dynamic_drawing_objects_)
dw->draw(graphics);
}
//If the drawer_trigger didn't declear a lazy refresh, then use the refresh().
void drawer::_m_use_refresh()
{
if (basic_window::update_state::refresh != core_window_->other.upd_state)
refresh();
}
}//end namespace detail
}//end namespace nana

View File

@@ -0,0 +1,45 @@
/*
* The Store for the Storage Of Elements
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com)
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* @file: nana/gui/detail/element_store.cpp
*/
#include <nana/gui/detail/element_store.hpp>
namespace nana
{
namespace detail
{
//class element_store
element_store::data::data()
: fast_ptr(nullptr)
{}
nana::element::element_interface * const * element_store::bground(const std::string& name)
{
element_interface * const * addr = &(bground_.table[name].fast_ptr);
return addr;
}
void element_store::bground(const std::string& name, const pat::cloneable<element_interface>& rhs)
{
auto & store = bground_.table[name];
store.object = rhs;
store.fast_ptr = store.object.get();
}
void element_store::bground(const std::string& name, pat::cloneable<element_interface>&& rv)
{
auto & store = bground_.table[name];
store.object = std::move(rv);
store.fast_ptr = store.object.get();
}
}//end namespace detail
}

View File

@@ -0,0 +1,52 @@
#include <nana/gui/detail/events_operation.hpp>
namespace nana
{
namespace detail
{
//class events_operation
typedef std::lock_guard<std::recursive_mutex> lock_guard;
void events_operation::make(window wd, const std::shared_ptr<general_events>& sp)
{
lock_guard lock(mutex_);
evt_table_[wd] = sp;
}
void events_operation::umake(window wd)
{
lock_guard lock(mutex_);
evt_table_.erase(wd);
}
void events_operation::register_evt(event_handle evt)
{
lock_guard lock(mutex_);
register_.insert(evt);
}
void events_operation::cancel(event_handle evt)
{
lock_guard lock(mutex_);
register_.erase(evt);
}
void events_operation::erase(event_handle evt)
{
lock_guard lock(mutex_);
auto i = register_.find(evt);
if (i != register_.end())
{
reinterpret_cast<detail::docker_interface*>(evt)->get_event()->remove(evt);
}
}
std::size_t events_operation::size() const
{
lock_guard lock(mutex_);
return register_.size();
}
//end namespace events_operation
}//end namespace detail
}//end namespace nana

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,391 @@
/*
* Window Layout Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2014 Jinhao(cnjinhao@hotmail.com)
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*
* @file: nana/gui/detail/window_layout.hpp
*
*/
#include <nana/gui/detail/window_layout.hpp>
#include <nana/gui/detail/basic_window.hpp>
#include <nana/gui/detail/native_window_interface.hpp>
#include <nana/gui/layout_utility.hpp>
#include <algorithm>
namespace nana
{
namespace detail
{
//class window_layout
void window_layout::paint(core_window_t* wd, bool is_redraw, bool is_child_refreshed)
{
if (nullptr == wd->effect.bground)
{
if (is_redraw)
{
if (wd->flags.refreshing) return;
wd->flags.refreshing = true;
wd->drawer.refresh();
wd->flags.refreshing = false;
}
maproot(wd, is_redraw, is_child_refreshed);
}
else
_m_paint_glass_window(wd, is_redraw, is_child_refreshed, false, true);
}
bool window_layout::maproot(core_window_t* wd, bool have_refreshed, bool is_child_refreshed)
{
nana::rectangle vr;
if (read_visual_rectangle(wd, vr))
{
//get the root graphics
auto& graph = *(wd->root_graph);
if (wd->other.category != category::lite_widget_tag::value)
graph.bitblt(vr, wd->drawer.graphics, nana::point(vr.x - wd->pos_root.x, vr.y - wd->pos_root.y));
_m_paste_children(wd, is_child_refreshed, have_refreshed, vr, graph, nana::point());
if (wd->parent)
{
std::vector<wd_rectangle> blocks;
blocks.reserve(10);
if (read_overlaps(wd, vr, blocks))
{
nana::point p_src;
for (auto & el : blocks)
{
if (el.window->other.category == category::frame_tag::value)
{
native_window_type container = el.window->other.attribute.frame->container;
native_interface::refresh_window(container);
graph.bitblt(el.r, container);
}
else
{
p_src.x = el.r.x - el.window->pos_root.x;
p_src.y = el.r.y - el.window->pos_root.y;
graph.bitblt(el.r, (el.window->drawer.graphics), p_src);
}
_m_paste_children(el.window, is_child_refreshed, false, el.r, graph, nana::point{});
}
}
}
_m_notify_glasses(wd, vr);
return true;
}
return false;
}
void window_layout::paste_children_to_graphics(core_window_t* wd, nana::paint::graphics& graph)
{
_m_paste_children(wd, false, false, rectangle{ wd->pos_root, wd->dimension }, graph, wd->pos_root);
}
//read_visual_rectangle
//@brief: Reads the visual rectangle of a window, the visual rectangle's reference frame is to root widget,
// the visual rectangle is a rectangular block that a window should be displayed on screen.
// The result is a rectangle that is a visible area for its ancesters.
bool window_layout::read_visual_rectangle(core_window_t* wd, nana::rectangle& visual)
{
if (false == wd->visible) return false;
visual = rectangle{ wd->pos_root, wd->dimension };
if (wd->root_widget != wd)
{
//Test if the root widget is overlapped the specified widget
//the pos of root widget is (0, 0)
if (overlap(visual, rectangle{ wd->root_widget->pos_owner, wd->root_widget->dimension }) == false)
return false;
}
for (auto* parent = wd->parent; parent; parent = parent->parent)
{
overlap(rectangle{ parent->pos_root, parent->dimension }, visual, visual);
}
return true;
}
//read_overlaps
// reads the overlaps that are overlapped a rectangular block
bool window_layout::read_overlaps(core_window_t* wd, const nana::rectangle& vis_rect, std::vector<wd_rectangle>& blocks)
{
wd_rectangle block;
while (wd->parent)
{
auto & siblings = wd->parent->children;
//It should be checked that whether the window is still a chlid of its parent.
if (siblings.size())
{
auto i = &(siblings[0]);
auto *end = i + siblings.size();
i = std::find(i, end, wd);
if (i != end)
{
//find the widget that next to wd.
for (++i; i < end; ++i)
{
core_window_t* cover = *i;
if (cover->visible && (nullptr == cover->effect.bground))
{
if (overlap(vis_rect, rectangle{ cover->pos_root, cover->dimension }, block.r))
{
block.window = cover;
blocks.push_back(block);
}
}
}
}
}
wd = wd->parent;
}
return (!blocks.empty());
}
bool window_layout::enable_effects_bground(core_window_t * wd, bool enabled)
{
if (wd->other.category != category::widget_tag::value)
return false;
if (false == enabled)
{
delete wd->effect.bground;
wd->effect.bground = nullptr;
wd->effect.bground_fade_rate = 0;
}
//Find the window whether it is registered for the bground effects
auto i = std::find(data_sect.effects_bground_windows.begin(), data_sect.effects_bground_windows.end(), wd);
if (i != data_sect.effects_bground_windows.end())
{
//If it has already registered, do nothing.
if (enabled)
return false;
//Disable the effect.
data_sect.effects_bground_windows.erase(i);
wd->other.glass_buffer.release();
return true;
}
//No such effect has registered.
if (false == enabled)
return false;
//Enable the effect.
data_sect.effects_bground_windows.push_back(wd);
wd->other.glass_buffer.make(wd->dimension.width, wd->dimension.height);
make_bground(wd);
return true;
}
//make_bground
// update the glass buffer of a glass window.
void window_layout::make_bground(core_window_t* const wd)
{
nana::point rpos{ wd->pos_root };
auto & glass_buffer = wd->other.glass_buffer;
if (wd->parent->other.category == category::lite_widget_tag::value)
{
std::vector<core_window_t*> layers;
core_window_t * beg = wd->parent;
while (beg && (beg->other.category == category::lite_widget_tag::value))
{
layers.push_back(beg);
beg = beg->parent;
}
glass_buffer.bitblt(wd->dimension, beg->drawer.graphics, wd->pos_root - beg->pos_root);
nana::rectangle r(wd->pos_owner, wd->dimension);
for (auto i = layers.rbegin(), layers_rend = layers.rend(); i != layers_rend; ++i)
{
core_window_t * pre = *i;
if (false == pre->visible)
continue;
core_window_t * term = ((i + 1 != layers_rend) ? *(i + 1) : wd);
r.x = wd->pos_root.x - pre->pos_root.x;
r.y = wd->pos_root.y - pre->pos_root.y;
for (auto child : pre->children)
{
if (child->index >= term->index)
break;
nana::rectangle ovlp;
if (child->visible && overlap(r, rectangle(child->pos_owner, child->dimension), ovlp))
{
if (child->other.category != category::lite_widget_tag::value)
glass_buffer.bitblt(nana::rectangle(ovlp.x - pre->pos_owner.x, ovlp.y - pre->pos_owner.y, ovlp.width, ovlp.height), child->drawer.graphics, nana::point(ovlp.x - child->pos_owner.x, ovlp.y - child->pos_owner.y));
ovlp.x += pre->pos_root.x;
ovlp.y += pre->pos_root.y;
_m_paste_children(child, false, false, ovlp, glass_buffer, rpos);
}
}
}
}
else
glass_buffer.bitblt(wd->dimension, wd->parent->drawer.graphics, wd->pos_owner);
const rectangle r_of_wd{ wd->pos_owner, wd->dimension };
for (auto child : wd->parent->children)
{
if (child->index >= wd->index)
break;
nana::rectangle ovlp;
if (child->visible && overlap(r_of_wd, rectangle{ child->pos_owner, child->dimension }, ovlp))
{
if (child->other.category != category::lite_widget_tag::value)
glass_buffer.bitblt(nana::rectangle{ ovlp.x - wd->pos_owner.x, ovlp.y - wd->pos_owner.y, ovlp.width, ovlp.height }, child->drawer.graphics, nana::point(ovlp.x - child->pos_owner.x, ovlp.y - child->pos_owner.y));
ovlp.x += wd->pos_root.x;
ovlp.y += wd->pos_root.y;
_m_paste_children(child, false, false, ovlp, glass_buffer, rpos);
}
}
if (wd->effect.bground)
wd->effect.bground->take_effect(reinterpret_cast<window>(wd), glass_buffer);
}
//_m_paste_children
//@brief:paste children window to the root graphics directly. just paste the visual rectangle
void window_layout::_m_paste_children(core_window_t* wd, bool is_child_refreshed, bool have_refreshed, const nana::rectangle& parent_rect, nana::paint::graphics& graph, const nana::point& graph_rpos)
{
nana::rectangle rect;
for (auto child : wd->children)
{
//it will not past children if no drawer and visible is false.
if ((false == child->visible) || ((child->other.category != category::lite_widget_tag::value) && child->drawer.graphics.empty()))
continue;
if (nullptr == child->effect.bground)
{
if (overlap(nana::rectangle{ child->pos_root, child->dimension }, parent_rect, rect))
{
bool have_child_refreshed = false;
if (child->other.category != category::lite_widget_tag::value)
{
if (is_child_refreshed && (false == child->flags.refreshing))
{
have_child_refreshed = true;
child->flags.refreshing = true;
child->drawer.refresh();
child->flags.refreshing = false;
}
graph.bitblt(nana::rectangle(rect.x - graph_rpos.x, rect.y - graph_rpos.y, rect.width, rect.height),
child->drawer.graphics, nana::point(rect.x - child->pos_root.x, rect.y - child->pos_root.y));
}
_m_paste_children(child, is_child_refreshed, have_child_refreshed, rect, graph, graph_rpos);
}
}
else
{
//If have_refreshed, the glass should be notified.
_m_paint_glass_window(child, false, is_child_refreshed, have_refreshed, false);
}
}
}
void window_layout::_m_paint_glass_window(core_window_t* wd, bool is_redraw, bool is_child_refreshed, bool called_by_notify, bool notify_other)
{
if (wd->flags.refreshing && is_redraw) return;
nana::rectangle vr;
if (read_visual_rectangle(wd, vr))
{
if (is_redraw || called_by_notify)
{
if (called_by_notify)
make_bground(wd);
wd->flags.refreshing = true;
wd->drawer.refresh();
wd->flags.refreshing = false;
}
auto & root_graph = *(wd->root_graph);
//Map root
root_graph.bitblt(vr, wd->drawer.graphics, nana::point(vr.x - wd->pos_root.x, vr.y - wd->pos_root.y));
_m_paste_children(wd, is_child_refreshed, (is_redraw || called_by_notify), vr, root_graph, nana::point());
if (wd->parent)
{
std::vector<wd_rectangle> blocks;
read_overlaps(wd, vr, blocks);
for (auto & n : blocks)
{
root_graph.bitblt(n.r, (n.window->drawer.graphics), nana::point(n.r.x - n.window->pos_root.x, n.r.y - n.window->pos_root.y));
}
}
if (notify_other)
_m_notify_glasses(wd, vr);
}
}
//_m_notify_glasses
//@brief: Notify the glass windows that are overlapped with the specified vis_rect
void window_layout::_m_notify_glasses(core_window_t* const sigwd, const nana::rectangle& r_visual)
{
typedef category::flags cat_flags;
nana::rectangle r_of_sigwd(sigwd->pos_root, sigwd->dimension);
for (auto wd : data_sect.effects_bground_windows)
{
if (wd == sigwd || !wd->visible || !wd->visible_parents() ||
(false == overlap(nana::rectangle{ wd->pos_root, wd->dimension }, r_of_sigwd)))
continue;
if (sigwd->parent == wd->parent)
{
if (sigwd->index >= wd->index)
continue;
}
else if (sigwd != wd->parent)
{
if (wd->parent && (cat_flags::lite_widget == wd->parent->other.category))
{
//Test if sigwd is an ancestor of the glass window, and there are lite widgets
//between sigwd and glass window.
auto ancestor = wd->parent->parent;
while (ancestor && (ancestor != sigwd) && (cat_flags::lite_widget == ancestor->other.category))
ancestor = ancestor->parent;
if ((ancestor != sigwd) || (cat_flags::lite_widget == ancestor->other.category))
continue;
}
else
{
//test if sigwnd is a parent of glass window x, or a slibing of the glass window, or a child of the slibing of the glass window.
core_window_t *p = wd->parent, *signode = sigwd;
while (signode->parent && (signode->parent != p))
signode = signode->parent;
if ((!signode->parent) || (signode->index >= wd->index))
continue;
}
}
else
continue;
_m_paint_glass_window(wd, true, false, true, true);
}
}
//end class window_layout
window_layout::data_section window_layout::data_sect;
}//end namespace detail
}//end namespace nana

File diff suppressed because it is too large Load Diff