coe refine

This commit is contained in:
Jinhao 2017-04-19 04:58:20 +08:00
parent 606087f962
commit 970412a3db
12 changed files with 331 additions and 431 deletions

View File

@ -1,295 +0,0 @@
/*
* Handle Manager Implementation
* Copyright(C) 2003-2013 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/handle_manager.hpp
*
* @description:
* this manages all the window handles
*/
#ifndef NANA_GUI_DETAIL_HANDLE_MANAGER_HPP
#define NANA_GUI_DETAIL_HANDLE_MANAGER_HPP
#include <nana/traits.hpp>
#include <nana/config.hpp>
#if defined(STD_THREAD_NOT_SUPPORTED)
#include <nana/std_mutex.hpp>
#else
#include <mutex>
#endif
#include <map>
#include <iterator>
#include <nana/push_ignore_diagnostic>
namespace nana
{
namespace detail
{
template<typename Key, typename Value, std::size_t CacheSize>
class cache
: noncopyable
{
public:
typedef Key key_type;
typedef Value value_type;
typedef std::pair<key_type, value_type> pair_type;
typedef std::size_t size_type;
cache()
:addr_(reinterpret_cast<pair_type*>(::operator new(sizeof(pair_type) * CacheSize)))
{
for(std::size_t i = 0; i < CacheSize; ++i)
{
bitmap_[i] = 0;
seq_[i] = nana::npos;
}
}
~cache()
{
for(std::size_t i = 0; i < CacheSize; ++i)
{
if(bitmap_[i])
addr_[i].~pair_type();
}
::operator delete(addr_);
}
bool insert(key_type k, value_type v)
{
size_type pos = _m_find_key(k);
if(pos != nana::npos)
{
addr_[pos].second = v;
}
else
{
//No key exists
pos = _m_find_pos();
if(pos == nana::npos)
{ //No room, and remove the last pair
pos = seq_[CacheSize - 1];
(addr_ + pos)->~pair_type();
}
if(seq_[0] != nana::npos)
{//Need to move
for(int i = CacheSize - 1; i > 0; --i)
seq_[i] = seq_[i - 1];
}
seq_[0] = pos;
new (addr_ + pos) pair_type(k, v);
bitmap_[pos] = 1;
}
return v;
}
value_type * get(key_type k)
{
size_type pos = _m_find_key(k);
if(pos != nana::npos)
return &(addr_[pos].second);
return 0;
}
private:
size_type _m_find_key(key_type k) const
{
for(std::size_t i = 0; i < CacheSize; ++i)
{
if(bitmap_[i] && (addr_[i].first == k))
return i;
}
return nana::npos;
}
size_type _m_find_pos() const
{
for(std::size_t i = 0; i < CacheSize; ++i)
{
if(bitmap_[i] == 0)
return i;
}
return nana::npos;
}
private:
char bitmap_[CacheSize];
size_type seq_[CacheSize];
pair_type * addr_;
};
//handle_manager
//@brief
// handle_manager maintains handles of a type. removing a handle dose not destroy it,
// it will be inserted to a trash queue for deleting at a safe time.
// For efficiency, this class is not a thread-safe.
template<typename HandleType, typename Condition, typename Deleter>
class handle_manager
: nana::noncopyable
{
public:
typedef HandleType handle_type;
typedef Condition cond_type;
typedef Deleter deleter_type;
typedef std::map<handle_type, unsigned> handle_map_t;
typedef std::pair<handle_type, unsigned> holder_pair;
~handle_manager()
{
delete_trash(0);
}
void insert(handle_type handle, unsigned tid)
{
std::lock_guard<decltype(mutex_)> lock(mutex_);
holder_[handle] = tid;
is_queue<std::is_same<cond_type, nana::null_type>::value, std::vector<handle_type> >::insert(handle, queue_);
cacher_.insert(handle, true);
}
void operator()(const handle_type handle)
{
remove(handle);
}
void remove(const handle_type handle)
{
std::lock_guard<decltype(mutex_)> lock(mutex_);
auto i = static_cast<const handle_map_t&>(holder_).find(handle);
if(holder_.cend() != i)
{
is_queue<std::is_same<cond_type, nana::null_type>::value, std::vector<handle_type> >::erase(handle, queue_);
cacher_.insert(handle, false);
trash_.push_back(*i);
holder_.erase(i);
}
}
void delete_trash(unsigned tid)
{
std::lock_guard<decltype(mutex_)> lock(mutex_);
if(trash_.size())
{
deleter_type del_functor;
if(tid == 0)
{
for(auto & m : trash_)
del_functor(m.first);
trash_.clear();
}
else
{
for(auto i = trash_.begin(), end = trash_.end(); i != end;)
{
if(tid == i->second)
{
del_functor(i->first);
i = trash_.erase(i);
end = trash_.end();
}
else
++i;
}
}
}
}
handle_type last() const
{
std::lock_guard<decltype(mutex_)> lock(mutex_);
if(queue_.size())
return queue_.back();
return handle_type();
}
std::size_t size() const
{
return holder_.size();
}
handle_type get(unsigned index) const
{
std::lock_guard<decltype(mutex_)> lock(mutex_);
if(index < queue_.size())
return queue_[index];
return handle_type();
}
bool available(const handle_type handle) const
{
if (nullptr == handle)
return false;
std::lock_guard<decltype(mutex_)> lock(mutex_);
bool * v = cacher_.get(handle);
if(v) return *v;
return cacher_.insert(handle, (holder_.count(handle) != 0));
}
void all(std::vector<handle_type> & v) const
{
std::lock_guard<decltype(mutex_)> lock(mutex_);
std::copy(queue_.cbegin(), queue_.cend(), std::back_inserter(v));
}
private:
template<bool IsQueueOperation, typename Container>
struct is_queue
{
public:
static void insert(handle_type handle, Container& queue)
{
if(cond_type::is_queue(handle))
queue.push_back(handle);
}
static void erase(handle_type handle, Container& queue)
{
if(cond_type::is_queue(handle))
{
for (auto i = queue.begin(); i != queue.end(); ++i)
{
if (handle == *i)
{
queue.erase(i);
break;
}
}
}
}
};
template<typename Container>
struct is_queue<true, Container>
{
public:
static void insert(handle_type handle, Container& queue){}
static void erase(handle_type handle, Container& queue){}
};
private:
mutable std::recursive_mutex mutex_;
mutable cache<const handle_type, bool, 5> cacher_;
handle_map_t holder_;
std::vector<handle_type> queue_;
std::vector<holder_pair> trash_;
};//end class handle_manager
}//end namespace detail
}// end namespace nana
#include <nana/pop_ignore_diagnostic>
#endif

View File

@ -1,7 +1,7 @@
/**
* Window Manager Implementation
* Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com)
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com)
*
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
@ -20,7 +20,6 @@
#include <nana/push_ignore_diagnostic>
#include "window_layout.hpp"
#include "event_code.hpp"
#include "inner_fwd.hpp"
#include <functional>
@ -31,6 +30,7 @@ namespace nana
namespace paint
{
class image;
class graphics;
}
}
@ -68,12 +68,10 @@ namespace detail
using mutex_type = revertible_mutex;
using core_window_t = basic_window;
using window_layer = window_layout;
window_manager();
~window_manager();
static bool is_queue(core_window_t*);
std::size_t number_of_core_window() const;
mutex_type & internal_lock() const;
void all_handles(std::vector<core_window_t*>&) const;
@ -103,12 +101,11 @@ namespace detail
// Deletes a window whose category type is a root type or a frame type.
void destroy_handle(core_window_t*);
void default_icon(const paint::image& _small_icon, const paint::image& big_icon);
void icon(core_window_t*, const paint::image& small_icon, const paint::image& big_icon);
bool show(core_window_t* wd, bool visible);
core_window_t* find_window(native_window_type root, int x, int y);
core_window_t* find_window(native_window_type root, const point& pos);
//move the wnd and its all children window, x and y is a relatively coordinate for wnd's parent window
bool move(core_window_t*, int x, int y, bool passive);

View File

@ -25,7 +25,6 @@ namespace detail
void free_fade_table(const unsigned char*);
//color = bgcolor * fade_rate + fgcolor * (1 - fade_rate);
//nana::pixel_color_t fade_color(nana::pixel_color_t bgcolor, nana::pixel_color_t fgcolor, double fade_rate); //deprecated
nana::pixel_color_t fade_color(nana::pixel_color_t bgcolor, nana::pixel_color_t fgcolor, const unsigned char* const fade_table);
nana::pixel_color_t fade_color_intermedia(pixel_color_t fgcolor, const unsigned char* fade_table);
nana::pixel_color_t fade_color_by_intermedia(pixel_color_t bgcolor, nana::pixel_color_t fgcolor_intermedia, const unsigned char* const fade_table);

View File

@ -1381,7 +1381,7 @@ namespace detail
Window child;
::XTranslateCoordinates(self.display_, self.root_window(), evt.xclient.window, x, y, &self.xdnd_.pos.x, &self.xdnd_.pos.y, &child);
auto wd = bedrock.wd_manager().find_window(reinterpret_cast<native_window_type>(evt.xclient.window), self.xdnd_.pos.x, self.xdnd_.pos.y);
auto wd = bedrock.wd_manager().find_window(reinterpret_cast<native_window_type>(evt.xclient.window), self.xdnd_.pos);
if(wd && wd->flags.dropable)
{
accepted = true;

View File

@ -258,7 +258,7 @@ namespace nana
return;
native_interface::calc_window_point(native_handle, pos);
if (wd != wd_manager().find_window(native_handle, pos.x, pos.y))
if (wd != wd_manager().find_window(native_handle, pos))
return;
set_cursor(wd, wd->predef_cursor, thrd);

View File

@ -376,7 +376,7 @@ namespace detail
switch(msg.kind)
{
case nana::detail::msg_packet_tag::kind_mouse_drop:
msgwd = brock.wd_manager().find_window(native_window, msg.u.mouse_drop.x, msg.u.mouse_drop.y);
msgwd = brock.wd_manager().find_window(native_window, {msg.u.mouse_drop.x, msg.u.mouse_drop.y});
if(msgwd)
{
arg_dropfiles arg;
@ -511,7 +511,7 @@ namespace detail
if(pressed_wd_space)
break;
msgwnd = wd_manager.find_window(native_window, xevent.xcrossing.x, xevent.xcrossing.y);
msgwnd = wd_manager.find_window(native_window, {xevent.xcrossing.x, xevent.xcrossing.y});
if(msgwnd)
{
if (mouse_action::pressed != msgwnd->flags.action)
@ -568,7 +568,7 @@ namespace detail
if(xevent.xbutton.button == Button4 || xevent.xbutton.button == Button5)
break;
msgwnd = wd_manager.find_window(native_window, xevent.xbutton.x, xevent.xbutton.y);
msgwnd = wd_manager.find_window(native_window, {xevent.xbutton.x, xevent.xbutton.y});
pressed_wd = nullptr;
if(nullptr == msgwnd)
@ -614,7 +614,7 @@ namespace detail
auto pos = native_interface::cursor_position();
auto rootwd = native_interface::find_window(pos.x, pos.y);
native_interface::calc_window_point(rootwd, pos);
if(msgwnd != wd_manager.find_window(rootwd, pos.x, pos.y))
if(msgwnd != wd_manager.find_window(rootwd, pos))
{
//call the drawer mouse up event for restoring the surface graphics
msgwnd->set_action(mouse_action::normal);
@ -634,7 +634,7 @@ namespace detail
if(pressed_wd_space)
break;
msgwnd = wd_manager.find_window(native_window, xevent.xbutton.x, xevent.xbutton.y);
msgwnd = wd_manager.find_window(native_window, {xevent.xbutton.x, xevent.xbutton.y});
if(nullptr == msgwnd)
break;
@ -754,7 +754,7 @@ namespace detail
if(pressed_wd_space)
break;
msgwnd = wd_manager.find_window(native_window, xevent.xmotion.x, xevent.xmotion.y);
msgwnd = wd_manager.find_window(native_window, {xevent.xmotion.x, xevent.xmotion.y});
if (wd_manager.available(hovered_wd) && (msgwnd != hovered_wd))
{
brock.event_msleave(hovered_wd);
@ -1282,7 +1282,7 @@ namespace detail
return;
native_interface::calc_window_point(native_handle, pos);
auto rev_wd = wd_manager().find_window(native_handle, pos.x, pos.y);
auto rev_wd = wd_manager().find_window(native_handle, pos);
if (rev_wd)
set_cursor(rev_wd, rev_wd->predef_cursor, thrd);
}

View File

@ -893,7 +893,7 @@ namespace detail
break;
pressed_wd = nullptr;
msgwnd = wd_manager.find_window(native_window, pmdec.mouse.x, pmdec.mouse.y);
msgwnd = wd_manager.find_window(native_window, { pmdec.mouse.x, pmdec.mouse.y });
if (msgwnd && msgwnd->flags.enabled)
{
if (msgwnd->flags.take_active && !msgwnd->flags.ignore_mouse_focus)
@ -918,7 +918,7 @@ namespace detail
if (pressed_wd_space)
break;
msgwnd = wd_manager.find_window(native_window, pmdec.mouse.x, pmdec.mouse.y);
msgwnd = wd_manager.find_window(native_window, { pmdec.mouse.x, pmdec.mouse.y });
//Don't take care about whether msgwnd is equal to the pressed_wd.
//
@ -962,7 +962,7 @@ namespace detail
auto pos = native_interface::cursor_position();
auto rootwd = native_interface::find_window(pos.x, pos.y);
native_interface::calc_window_point(rootwd, pos);
if(msgwnd != wd_manager.find_window(rootwd, pos.x, pos.y))
if (msgwnd != wd_manager.find_window(rootwd, pos))
{
//call the drawer mouse up event for restoring the surface graphics
msgwnd->set_action(mouse_action::normal);
@ -985,7 +985,7 @@ namespace detail
if (pressed_wd_space)
break;
msgwnd = wd_manager.find_window(native_window, pmdec.mouse.x, pmdec.mouse.y);
msgwnd = wd_manager.find_window(native_window, { pmdec.mouse.x, pmdec.mouse.y });
if (nullptr == msgwnd)
break;
@ -1040,7 +1040,7 @@ namespace detail
if (pressed_wd_space)
break;
msgwnd = wd_manager.find_window(native_window, pmdec.mouse.x, pmdec.mouse.y);
msgwnd = wd_manager.find_window(native_window, {pmdec.mouse.x, pmdec.mouse.y});
if (wd_manager.available(hovered_wd) && (msgwnd != hovered_wd))
{
brock.event_msleave(hovered_wd);
@ -1121,7 +1121,7 @@ namespace detail
if (pointer_wd == root_window)
{
::ScreenToClient(pointer_wd, &scr_pos);
auto scrolled_wd = wd_manager.find_window(reinterpret_cast<native_window_type>(pointer_wd), scr_pos.x, scr_pos.y);
auto scrolled_wd = wd_manager.find_window(reinterpret_cast<native_window_type>(pointer_wd), { scr_pos.x, scr_pos.y });
def_window_proc = true;
auto evt_wd = scrolled_wd;
@ -1162,10 +1162,12 @@ namespace detail
case WM_DROPFILES:
{
HDROP drop = reinterpret_cast<HDROP>(wParam);
POINT pos;
::DragQueryPoint(drop, &pos);
POINT mswin_pos;
::DragQueryPoint(drop, &mswin_pos);
msgwnd = wd_manager.find_window(native_window, pos.x, pos.y);
const point pos{ mswin_pos.x, mswin_pos.y };
msgwnd = wd_manager.find_window(native_window, pos);
if(msgwnd)
{
arg_dropfiles dropfiles;
@ -1193,8 +1195,7 @@ namespace detail
if(msgwnd)
{
dropfiles.pos.x = pos.x;
dropfiles.pos.y = pos.y;
dropfiles.pos = pos;
wd_manager.calc_window_point(msgwnd, dropfiles.pos);
dropfiles.window_handle = reinterpret_cast<window>(msgwnd);
@ -1783,7 +1784,7 @@ namespace detail
}
native_interface::calc_window_point(native_handle, pos);
auto rev_wd = wd_manager().find_window(native_handle, pos.x, pos.y);
auto rev_wd = wd_manager().find_window(native_handle, pos);
if (rev_wd)
{
set_cursor(rev_wd, rev_wd->predef_cursor, thrd);

View File

@ -14,14 +14,17 @@
#include <nana/config.hpp>
#include <nana/gui/detail/bedrock.hpp>
#include <nana/gui/detail/events_operation.hpp>
#include <nana/gui/detail/handle_manager.hpp>
#include <nana/gui/detail/window_manager.hpp>
#include <nana/gui/detail/window_layout.hpp>
#include "window_register.hpp"
#include <nana/gui/detail/native_window_interface.hpp>
#include <nana/gui/detail/inner_fwd_implement.hpp>
#include <nana/gui/layout_utility.hpp>
#include <nana/gui/detail/effects_renderer.hpp>
#include <stdexcept>
#include <algorithm>
#include <iterator>
#if defined(STD_THREAD_NOT_SUPPORTED)
#include <nana/std_mutex.hpp>
@ -34,6 +37,8 @@ namespace nana
namespace detail
{
using window_layer = window_layout;
//class shortkey_container
struct shortkey_rep
{
@ -266,7 +271,8 @@ namespace detail
struct window_manager::wdm_private_impl
{
root_register misc_register;
handle_manager<core_window_t*, window_manager, window_handle_deleter> wd_register;
window_register wd_register;
paint::image default_icon_big;
paint::image default_icon_small;
@ -443,13 +449,11 @@ namespace detail
delete impl_;
}
bool window_manager::is_queue(core_window_t* wd)
{
return (wd && (category::flags::root == wd->other.category));
}
std::size_t window_manager::number_of_core_window() const
{
//Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_);
return impl_->wd_register.size();
}
@ -460,7 +464,9 @@ namespace detail
void window_manager::all_handles(std::vector<core_window_t*> &v) const
{
impl_->wd_register.all(v);
//Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_);
v = impl_->wd_register.queue();
}
void window_manager::event_filter(core_window_t* wd, bool is_make, event_code evtid)
@ -477,11 +483,15 @@ namespace detail
bool window_manager::available(core_window_t* wd)
{
//Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_);
return impl_->wd_register.available(wd);
}
bool window_manager::available(core_window_t * a, core_window_t* b)
{
//Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_);
return (impl_->wd_register.available(a) && impl_->wd_register.available(b));
}
@ -533,7 +543,7 @@ namespace detail
auto* value = impl_->misc_register.insert(result.native_handle, root_misc(wd, result.width, result.height));
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);
impl_->wd_register.insert(wd);
#ifndef WIDGET_FRAME_DEPRECATED
if (owner && (category::flags::frame == owner->other.category))
@ -614,7 +624,8 @@ namespace detail
wd = new core_window_t(parent, std::move(wdg_notifier), r, (category::lite_widget_tag**)nullptr);
else
wd = new core_window_t(parent, std::move(wdg_notifier), r, (category::widget_tag**)nullptr);
impl_->wd_register.insert(wd, wd->thread_id);
impl_->wd_register.insert(wd);
return wd;
}
@ -701,15 +712,16 @@ namespace detail
}
}
void window_manager::default_icon(const nana::paint::image& _small, const nana::paint::image& big)
{
impl_->default_icon_big = big;
impl_->default_icon_small = _small;
}
void window_manager::icon(core_window_t* wd, const paint::image& small_icon, const paint::image& big_icon)
{
if(!big_icon.empty() || !small_icon.empty())
{
if (nullptr == wd)
{
impl_->default_icon_big = big_icon;
impl_->default_icon_small = small_icon;
}
else
{
std::lock_guard<mutex_type> lock(mutex_);
if (impl_->wd_register.available(wd))
@ -719,6 +731,7 @@ namespace detail
}
}
}
}
void sync_child_root_display(window_manager::core_window_t* wd)
{
@ -791,7 +804,7 @@ namespace detail
return true;
}
window_manager::core_window_t* window_manager::find_window(native_window_type root, int x, int y)
window_manager::core_window_t* window_manager::find_window(native_window_type root, const point& pos)
{
if (nullptr == root)
return nullptr;
@ -801,7 +814,6 @@ namespace detail
//Thread-Safe Required!
std::lock_guard<mutex_type> lock(mutex_);
auto rrt = root_runtime(root);
point pos{ x, y };
if (rrt && _m_effective(rrt->window, pos))
return _m_find(rrt->window, pos);
}
@ -873,9 +885,8 @@ namespace detail
//Move child widgets
if(r.x != wd->pos_owner.x || r.y != wd->pos_owner.y)
{
point delta{ r.x - wd->pos_owner.x, r.y - wd->pos_owner.y };
wd->pos_owner.x = r.x;
wd->pos_owner.y = r.y;
auto delta = r.position() - wd->pos_owner;
wd->pos_owner = r.position();
_m_move_core(wd, delta);
moved = true;
@ -1807,32 +1818,18 @@ namespace detail
brock.emit(event_code::destroy, wd, arg, true, brock.get_thread_context());
//Delete the children widgets.
for (auto i = wd->children.rbegin(), end = wd->children.rend(); i != end;)
while (!wd->children.empty())
{
auto child = *i;
auto child = wd->children.back();
if (category::flags::root == child->other.category)
{
//closing a child root window erases itself from wd->children,
//to make sure the iterator is valid, it must be reloaded.
auto offset = std::distance(wd->children.rbegin(), i);
//!!!
//a potential issue is that if the calling thread is not same with child's thread,
//the child root window may not be erased from wd->children now.
//Only the nested_form meets the condition
native_interface::close_window(child->root);
i = wd->children.rbegin();
std::advance(i, offset);
end = wd->children.rend();
continue;
}
_m_destroy(child);
++i;
wd->children.pop_back();
}
wd->children.clear();
_m_disengage(wd, nullptr);
window_layer::enable_effects_bground(wd, false);

View File

@ -0,0 +1,201 @@
#ifndef NANA_WINDOW_REGISTER_HEADER_INCLUDED
#define NANA_WINDOW_REGISTER_HEADER_INCLUDED
#include <nana/gui/detail/basic_window.hpp>
#include <set>
#include <vector>
#include <algorithm> //std::find
namespace nana
{
namespace detail
{
template<typename Key, typename Value, std::size_t CacheSize>
class cache
: noncopyable
{
public:
typedef Key key_type;
typedef Value value_type;
typedef std::pair<key_type, value_type> pair_type;
typedef std::size_t size_type;
cache()
:addr_(reinterpret_cast<pair_type*>(::operator new(sizeof(pair_type) * CacheSize)))
{
for (std::size_t i = 0; i < CacheSize; ++i)
{
bitmap_[i] = 0;
seq_[i] = nana::npos;
}
}
~cache()
{
for (std::size_t i = 0; i < CacheSize; ++i)
{
if (bitmap_[i])
addr_[i].~pair_type();
}
::operator delete(addr_);
}
bool insert(key_type k, value_type v)
{
size_type pos = _m_find_key(k);
if (pos != nana::npos)
{
addr_[pos].second = v;
}
else
{
//No key exists
pos = _m_find_pos();
if (pos == nana::npos)
{ //No room, and remove the last pair
pos = seq_[CacheSize - 1];
(addr_ + pos)->~pair_type();
}
if (seq_[0] != nana::npos)
{//Need to move
for (int i = CacheSize - 1; i > 0; --i)
seq_[i] = seq_[i - 1];
}
seq_[0] = pos;
new (addr_ + pos) pair_type(k, v);
bitmap_[pos] = 1;
}
return v;
}
value_type * get(key_type k)
{
size_type pos = _m_find_key(k);
if (pos != nana::npos)
return &(addr_[pos].second);
return 0;
}
private:
size_type _m_find_key(key_type k) const
{
for (std::size_t i = 0; i < CacheSize; ++i)
{
if (bitmap_[i] && (addr_[i].first == k))
return i;
}
return nana::npos;
}
size_type _m_find_pos() const
{
for (std::size_t i = 0; i < CacheSize; ++i)
{
if (bitmap_[i] == 0)
return i;
}
return nana::npos;
}
private:
char bitmap_[CacheSize];
size_type seq_[CacheSize];
pair_type * addr_;
};
class window_register
{
public:
using window_handle_type = basic_window*;
void insert(window_handle_type wd)
{
if (wd)
{
base_.insert(wd);
wdcache_.insert(wd, true);
if (category::flags::root == wd->other.category)
queue_.push_back(wd);
}
}
void operator()(window_handle_type wd)
{
remove(wd);
}
void remove(window_handle_type wd)
{
if (base_.erase(wd))
{
wdcache_.insert(wd, false);
if (category::flags::root == wd->other.category)
{
trash_.push_back(wd);
auto i = std::find(queue_.begin(), queue_.end(), wd);
if (i != queue_.end())
queue_.erase(i);
}
}
}
void delete_trash(unsigned thread_id)
{
if (0 == thread_id)
{
for (auto wd : trash_)
delete wd;
trash_.clear();
}
else
{
for (auto i = trash_.begin(); i != trash_.end();)
{
if (thread_id == (*i)->thread_id)
{
delete (*i);
i = trash_.erase(i);
}
else
++i;
}
}
}
const std::vector<window_handle_type>& queue() const
{
return queue_;
}
/// Returns the number of registered windows
std::size_t size() const
{
return base_.size();
}
bool available(window_handle_type wd) const
{
if (nullptr == wd)
return false;
auto exists = wdcache_.get(wd);
if (exists)
return *exists;
return wdcache_.insert(wd, (base_.count(wd) != 0));
}
private:
mutable cache<window_handle_type, bool, 5> wdcache_;
std::set<window_handle_type> base_;
std::vector<window_handle_type> trash_;
std::vector<window_handle_type> queue_;
};
}
}
#endif

View File

@ -461,11 +461,12 @@ namespace API
void window_icon_default(const paint::image& small_icon, const paint::image& big_icon)
{
restrict::wd_manager().default_icon(small_icon, big_icon);
restrict::wd_manager().icon(nullptr, small_icon, big_icon);
}
void window_icon(window wd, const paint::image& small_icon, const paint::image& big_icon)
{
if(nullptr != wd)
restrict::wd_manager().icon(reinterpret_cast<basic_window*>(wd), small_icon, big_icon);
}
@ -1320,7 +1321,7 @@ namespace API
::nana::point clipos{pos};
interface_type::calc_window_point(wd, clipos);
return reinterpret_cast<window>(
restrict::wd_manager().find_window(wd, clipos.x, clipos.y));
restrict::wd_manager().find_window(wd, clipos));
}
return nullptr;
}

View File

@ -204,15 +204,13 @@ namespace nana
range_width_px.first = minimum;
range_width_px.second = maximum;
if (width_px < range_width_px.first)
width_px = range_width_px.first;
else if (range_width_px.second < width_px)
width_px = range_width_px.second;
else
return;
unsigned px = std::clamp(static_cast<int>(width_px), static_cast<int>(minimum), static_cast<int>(maximum));
if (width_px != px)
{
width_px = px;
_m_refresh();
}
}
size_type position(bool disp_order) const noexcept override; //The definition is provided after essence
@ -3104,10 +3102,7 @@ namespace nana
if (col.range_width_px.first != col.range_width_px.second)
{
//Column ranged width
if (new_w < col.range_width_px.first)
new_w = col.range_width_px.first;
else if (new_w > col.range_width_px.second)
new_w = col.range_width_px.second;
new_w = std::clamp(static_cast<int>(new_w), static_cast<int>(col.range_width_px.first), static_cast<int>(col.range_width_px.second));
}
else
{
@ -3129,7 +3124,6 @@ namespace nana
{
const auto border_color = essence_->scheme_ptr->header_bgcolor.get_color().blend(colors::black, 0.2);
int text_top = (r.height - essence_->text_height) / 2 + r.y;
auto text_color = essence_->scheme_ptr->header_fgcolor.get_color();
auto state = item_state::normal;
@ -3153,7 +3147,7 @@ namespace nana
//Make sure the column is in the display area.
if (right_pos > r.x)
{
_m_draw_header_item(graph, column_r, text_top, text_color, col, (col.index == essence_->pointer_where.second ? state : item_state::normal));
_m_draw_header_item(graph, column_r, text_color, col, (col.index == essence_->pointer_where.second ? state : item_state::normal));
graph.line({ right_pos - 1, r.y }, { right_pos - 1, r.bottom() - 2 }, border_color);
}
@ -3191,10 +3185,8 @@ namespace nana
{
//convert x to header logic coordinate.
auto const x_offset = essence_->content_view->origin().x;
if (x < x_offset)
x = x_offset;
else if (x > x_offset + static_cast<int>(rect.width))
x = x_offset + static_cast<int>(rect.width);
x = std::clamp(x, x_offset, x_offset + static_cast<int>(rect.width));
auto i = essence_->header.column_from_point(x);
@ -3219,9 +3211,10 @@ namespace nana
return npos;
}
void _m_draw_header_item(graph_reference graph, const rectangle& column_r, int text_top, const ::nana::color& fgcolor, const es_header::column& column, item_state state)
void _m_draw_header_item(graph_reference graph, const rectangle& column_r, const ::nana::color& fgcolor, const es_header::column& column, item_state state)
{
::nana::color bgcolor;
switch(state)
{
case item_state::normal: bgcolor = essence_->scheme_ptr->header_bgcolor.get_color(); break;
@ -3249,7 +3242,7 @@ namespace nana
{
graph.palette(true, fgcolor);
point text_pos{ column_r.x, text_top };
point text_pos{ column_r.x, (static_cast<int>(essence_->scheme_ptr->header_height) - static_cast<int>(essence_->text_height)) / 2 };
if (align::left == column.alignment)
text_pos.x += text_margin;
@ -3277,11 +3270,9 @@ namespace nana
fl_graph.typeface(essence_->graph->typeface());
int text_top = (essence_->scheme_ptr->header_height - essence_->text_height) / 2;
_m_draw_header_item(fl_graph, rectangle{ fl_graph.size()}, text_top, colors::white, col, item_state::floated);
_m_draw_header_item(fl_graph, rectangle{ fl_graph.size()}, colors::white, col, item_state::floated);
auto xpos = essence_->header.position(col.index, nullptr) + pos.x - grabs_.start_pos;
essence_->graph->blend(rectangle{ point{ xpos - essence_->content_view->origin().x + rect.x, rect.y } , fl_graph.size() }, fl_graph, {}, 0.5);
}

View File

@ -419,8 +419,13 @@ namespace nana{ namespace widgets
//Overrides methods of colored_area_access_interface
std::shared_ptr<colored_area_type> get(std::size_t line_pos) override
{
#ifdef _MSC_VER
auto i = colored_areas_.cbegin();
for (; i != colored_areas_.cend(); ++i)
#else
auto i = colored_areas_.begin();
for (; i != colored_areas_.end(); ++i)
#endif
{
auto & area = *(i->get());
if (area.begin <= line_pos && line_pos < area.begin + area.count)
@ -430,10 +435,9 @@ namespace nana{ namespace widgets
break;
}
auto iter = colored_areas_.emplace(i, std::make_shared<colored_area_type>(colored_area_type{line_pos}));
auto & area = *(iter->get());
area.count = 1;
return *iter;
return *colored_areas_.emplace(i,
std::make_shared<colored_area_type>(colored_area_type{line_pos, 1, color{}, color{}})
);
}
bool clear()
@ -449,7 +453,11 @@ namespace nana{ namespace widgets
bool remove(std::size_t pos) override
{
bool changed = false;
#ifdef _MSC_VER
for (auto i = colored_areas_.cbegin(); i != colored_areas_.cend();)
#else
for (auto i = colored_areas_.begin(); i != colored_areas_.end();)
#endif
{
if (i->get()->begin <= pos && pos < i->get()->begin + i->get()->count)
{