Merge branch 'develop'
This commit is contained in:
@@ -16,7 +16,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include "general_events.hpp"
|
#include "general_events.hpp"
|
||||||
#include <nana/paint/graphics.hpp>
|
#include <nana/paint/graphics.hpp>
|
||||||
#include <nana/paint/image.hpp>
|
//#include <nana/paint/image.hpp> //deprecated
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
namespace nana
|
namespace nana
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ namespace nana
|
|||||||
public:
|
public:
|
||||||
trigger();
|
trigger();
|
||||||
~trigger();
|
~trigger();
|
||||||
essence_t& essence();
|
//essence_t& essence(); //deprecated
|
||||||
essence_t& essence() const;
|
essence_t& essence() const;
|
||||||
void draw();
|
void draw();
|
||||||
private:
|
private:
|
||||||
@@ -618,7 +618,7 @@ By \a clicking on one header the list get \a reordered, first up, and then down
|
|||||||
{
|
{
|
||||||
typedef typename nana::detail::type_escape<Key>::type key_t;
|
typedef typename nana::detail::type_escape<Key>::type key_t;
|
||||||
nana::key<key_t, std::less<key_t> > key(kv);
|
nana::key<key_t, std::less<key_t> > key(kv);
|
||||||
_m_ease_key(&key);
|
_m_erase_key(&key);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Key>
|
template<typename Key>
|
||||||
@@ -626,7 +626,7 @@ By \a clicking on one header the list get \a reordered, first up, and then down
|
|||||||
{
|
{
|
||||||
typedef typename nana::detail::type_escape<Key>::type key_t;
|
typedef typename nana::detail::type_escape<Key>::type key_t;
|
||||||
nana::key<key_t, std::less<key_t> > key(std::move(kv));
|
nana::key<key_t, std::less<key_t> > key(std::move(kv));
|
||||||
_m_ease_key(&key);
|
_m_erase_key(&key);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sortable() const;
|
bool sortable() const;
|
||||||
@@ -661,7 +661,7 @@ By \a clicking on one header the list get \a reordered, first up, and then down
|
|||||||
drawerbase::listbox::essence_t & _m_ess() const;
|
drawerbase::listbox::essence_t & _m_ess() const;
|
||||||
nana::any* _m_anyobj(size_type cat, size_type index, bool allocate_if_empty) const;
|
nana::any* _m_anyobj(size_type cat, size_type index, bool allocate_if_empty) const;
|
||||||
drawerbase::listbox::category_t* _m_at_key(std::shared_ptr<nana::detail::key_interface>);
|
drawerbase::listbox::category_t* _m_at_key(std::shared_ptr<nana::detail::key_interface>);
|
||||||
void _m_ease_key(nana::detail::key_interface*);
|
void _m_erase_key(nana::detail::key_interface*);
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace dev
|
namespace dev
|
||||||
|
|||||||
@@ -334,4 +334,51 @@ namespace nana
|
|||||||
std::unique_ptr<drawerbase::tabbar::event_agent<value_type, drawerbase::tabbar::trigger> > evt_agent_;
|
std::unique_ptr<drawerbase::tabbar::event_agent<value_type, drawerbase::tabbar::trigger> > evt_agent_;
|
||||||
};
|
};
|
||||||
}//end namespace nana
|
}//end namespace nana
|
||||||
|
|
||||||
|
|
||||||
|
namespace nana
|
||||||
|
{
|
||||||
|
namespace ng
|
||||||
|
{
|
||||||
|
namespace drawerbase
|
||||||
|
{
|
||||||
|
namespace tabbar_lite
|
||||||
|
{
|
||||||
|
class model;
|
||||||
|
|
||||||
|
class driver
|
||||||
|
: public drawer_trigger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
driver();
|
||||||
|
~driver();
|
||||||
|
|
||||||
|
model* get_model();
|
||||||
|
private:
|
||||||
|
//Overrides drawer_trigger's method
|
||||||
|
void attached(widget_reference, graph_reference) override;
|
||||||
|
void refresh(graph_reference) override;
|
||||||
|
void mouse_move(graph_reference, const arg_mouse&) override;
|
||||||
|
void mouse_leave(graph_reference, const arg_mouse&) override;
|
||||||
|
void mouse_down(graph_reference, const arg_mouse&) override;
|
||||||
|
private:
|
||||||
|
model* const model_;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}//end namespace drawerbase
|
||||||
|
|
||||||
|
class tabbar_lite
|
||||||
|
: public widget_object<category::widget_tag, drawerbase::tabbar_lite::driver>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
tabbar_lite() = default;
|
||||||
|
tabbar_lite(window, bool visible = true, const::nana::rectangle& = {});
|
||||||
|
|
||||||
|
|
||||||
|
void push_back(std::string text, ::nana::any par = {});
|
||||||
|
void push_front(std::string text, ::nana::any par = {});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace nana
|
|||||||
: nana::noncopyable, nana::nonmovable
|
: nana::noncopyable, nana::nonmovable
|
||||||
{
|
{
|
||||||
friend class detail::widget_notifier_interface;
|
friend class detail::widget_notifier_interface;
|
||||||
class notifier;
|
class inner_widget_notifier;
|
||||||
typedef void(*dummy_bool_type)(widget* (*)(const widget&));
|
typedef void(*dummy_bool_type)(widget* (*)(const widget&));
|
||||||
public:
|
public:
|
||||||
virtual ~widget() = default;
|
virtual ~widget() = default;
|
||||||
|
|||||||
@@ -96,7 +96,8 @@ namespace nana
|
|||||||
::nana::size glyph_extent_size(const char_t*, std::size_t length, std::size_t begin, std::size_t end) const;
|
::nana::size glyph_extent_size(const char_t*, std::size_t length, std::size_t begin, std::size_t end) const;
|
||||||
::nana::size glyph_extent_size(const string&, std::size_t length, std::size_t begin, std::size_t end) const;
|
::nana::size glyph_extent_size(const string&, std::size_t length, std::size_t begin, std::size_t end) const;
|
||||||
bool glyph_pixels(const char_t *, std::size_t length, unsigned* pxbuf) const;
|
bool glyph_pixels(const char_t *, std::size_t length, unsigned* pxbuf) const;
|
||||||
::nana::size bidi_extent_size(const string&) const;
|
::nana::size bidi_extent_size(const std::wstring&) const;
|
||||||
|
::nana::size bidi_extent_size(const std::string&) const;
|
||||||
|
|
||||||
bool text_metrics(unsigned & ascent, unsigned& descent, unsigned& internal_leading) const;
|
bool text_metrics(unsigned & ascent, unsigned& descent, unsigned& internal_leading) const;
|
||||||
|
|
||||||
@@ -139,6 +140,7 @@ namespace nana
|
|||||||
void set_text_color(const ::nana::color&);
|
void set_text_color(const ::nana::color&);
|
||||||
|
|
||||||
unsigned bidi_string(const nana::point&, const char_t *, std::size_t len);
|
unsigned bidi_string(const nana::point&, const char_t *, std::size_t len);
|
||||||
|
unsigned bidi_string(const point& pos, const char*, std::size_t len);
|
||||||
|
|
||||||
void blend(const ::nana::rectangle& r, const ::nana::color&, double fade_rate);
|
void blend(const ::nana::rectangle& r, const ::nana::color&, double fade_rate);
|
||||||
|
|
||||||
|
|||||||
@@ -189,8 +189,6 @@ namespace nana
|
|||||||
auto retain = wd->together.events_ptr;
|
auto retain = wd->together.events_ptr;
|
||||||
auto evts_ptr = retain.get();
|
auto evts_ptr = retain.get();
|
||||||
|
|
||||||
//enable refreshing flag, this is a RAII class for exception-safe
|
|
||||||
flag_guard fguard(this, wd);
|
|
||||||
|
|
||||||
switch (evt_code)
|
switch (evt_code)
|
||||||
{
|
{
|
||||||
@@ -199,8 +197,11 @@ namespace nana
|
|||||||
auto arg = dynamic_cast<const arg_click*>(&event_arg);
|
auto arg = dynamic_cast<const arg_click*>(&event_arg);
|
||||||
if (nullptr == arg)
|
if (nullptr == arg)
|
||||||
return;
|
return;
|
||||||
|
{
|
||||||
|
//enable refreshing flag, this is a RAII class for exception-safe
|
||||||
|
flag_guard fguard(this, wd);
|
||||||
wd->drawer.click(*arg);
|
wd->drawer.click(*arg);
|
||||||
|
}
|
||||||
if (!draw_only)
|
if (!draw_only)
|
||||||
evts_ptr->click.emit(*arg);
|
evts_ptr->click.emit(*arg);
|
||||||
}
|
}
|
||||||
@@ -249,7 +250,11 @@ namespace nana
|
|||||||
throw std::runtime_error("Invalid mouse event code");
|
throw std::runtime_error("Invalid mouse event code");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
//enable refreshing flag, this is a RAII class for exception-safe
|
||||||
|
flag_guard fguard(this, wd);
|
||||||
(wd->drawer.*drawer_event_fn)(*arg);
|
(wd->drawer.*drawer_event_fn)(*arg);
|
||||||
|
}
|
||||||
|
|
||||||
if (!draw_only)
|
if (!draw_only)
|
||||||
evt_addr->emit(*arg);
|
evt_addr->emit(*arg);
|
||||||
@@ -260,7 +265,12 @@ namespace nana
|
|||||||
auto arg = dynamic_cast<const arg_wheel*>(&event_arg);
|
auto arg = dynamic_cast<const arg_wheel*>(&event_arg);
|
||||||
if (arg)
|
if (arg)
|
||||||
{
|
{
|
||||||
|
{
|
||||||
|
//enable refreshing flag, this is a RAII class for exception-safe
|
||||||
|
flag_guard fguard(this, wd);
|
||||||
wd->drawer.mouse_wheel(*arg);
|
wd->drawer.mouse_wheel(*arg);
|
||||||
|
}
|
||||||
|
|
||||||
if (!draw_only)
|
if (!draw_only)
|
||||||
evts_ptr->mouse_wheel.emit(*arg);
|
evts_ptr->mouse_wheel.emit(*arg);
|
||||||
}
|
}
|
||||||
@@ -299,7 +309,12 @@ namespace nana
|
|||||||
default:
|
default:
|
||||||
throw std::runtime_error("Invalid keyboard event code");
|
throw std::runtime_error("Invalid keyboard event code");
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
//enable refreshing flag, this is a RAII class for exception-safe
|
||||||
|
flag_guard fguard(this, wd);
|
||||||
(wd->drawer.*drawer_event_fn)(*arg);
|
(wd->drawer.*drawer_event_fn)(*arg);
|
||||||
|
}
|
||||||
|
|
||||||
if (!draw_only)
|
if (!draw_only)
|
||||||
evt_addr->emit(*arg);
|
evt_addr->emit(*arg);
|
||||||
break;
|
break;
|
||||||
@@ -317,7 +332,11 @@ namespace nana
|
|||||||
auto arg = dynamic_cast<const arg_focus*>(&event_arg);
|
auto arg = dynamic_cast<const arg_focus*>(&event_arg);
|
||||||
if (arg)
|
if (arg)
|
||||||
{
|
{
|
||||||
|
{
|
||||||
|
//enable refreshing flag, this is a RAII class for exception-safe
|
||||||
|
flag_guard fguard(this, wd);
|
||||||
wd->drawer.focus(*arg);
|
wd->drawer.focus(*arg);
|
||||||
|
}
|
||||||
if (!draw_only)
|
if (!draw_only)
|
||||||
evts_ptr->focus.emit(*arg);
|
evts_ptr->focus.emit(*arg);
|
||||||
}
|
}
|
||||||
@@ -328,7 +347,11 @@ namespace nana
|
|||||||
auto arg = dynamic_cast<const arg_move*>(&event_arg);
|
auto arg = dynamic_cast<const arg_move*>(&event_arg);
|
||||||
if (arg)
|
if (arg)
|
||||||
{
|
{
|
||||||
|
{
|
||||||
|
//enable refreshing flag, this is a RAII class for exception-safe
|
||||||
|
flag_guard fguard(this, wd);
|
||||||
wd->drawer.move(*arg);
|
wd->drawer.move(*arg);
|
||||||
|
}
|
||||||
if (!draw_only)
|
if (!draw_only)
|
||||||
evts_ptr->move.emit(*arg);
|
evts_ptr->move.emit(*arg);
|
||||||
}
|
}
|
||||||
@@ -339,7 +362,11 @@ namespace nana
|
|||||||
auto arg = dynamic_cast<const arg_resizing*>(&event_arg);
|
auto arg = dynamic_cast<const arg_resizing*>(&event_arg);
|
||||||
if (arg)
|
if (arg)
|
||||||
{
|
{
|
||||||
|
{
|
||||||
|
//enable refreshing flag, this is a RAII class for exception-safe
|
||||||
|
flag_guard fguard(this, wd);
|
||||||
wd->drawer.resizing(*arg);
|
wd->drawer.resizing(*arg);
|
||||||
|
}
|
||||||
if (!draw_only)
|
if (!draw_only)
|
||||||
evts_ptr->resizing.emit(*arg);
|
evts_ptr->resizing.emit(*arg);
|
||||||
}
|
}
|
||||||
@@ -350,7 +377,11 @@ namespace nana
|
|||||||
auto arg = dynamic_cast<const arg_resized*>(&event_arg);
|
auto arg = dynamic_cast<const arg_resized*>(&event_arg);
|
||||||
if (arg)
|
if (arg)
|
||||||
{
|
{
|
||||||
|
{
|
||||||
|
//enable refreshing flag, this is a RAII class for exception-safe
|
||||||
|
flag_guard fguard(this, wd);
|
||||||
wd->drawer.resized(*arg);
|
wd->drawer.resized(*arg);
|
||||||
|
}
|
||||||
if (!draw_only)
|
if (!draw_only)
|
||||||
evts_ptr->resized.emit(*arg);
|
evts_ptr->resized.emit(*arg);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -326,6 +326,9 @@ namespace detail
|
|||||||
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
std::lock_guard<decltype(mutex_)> lock(mutex_);
|
||||||
if (impl_->wd_register.available(wd) == false) return;
|
if (impl_->wd_register.available(wd) == false) return;
|
||||||
|
|
||||||
|
if (wd->flags.destroying)
|
||||||
|
return;
|
||||||
|
|
||||||
if(wd->other.category == category::root_tag::value)
|
if(wd->other.category == category::root_tag::value)
|
||||||
{
|
{
|
||||||
auto &brock = bedrock::instance();
|
auto &brock = bedrock::instance();
|
||||||
@@ -340,13 +343,15 @@ namespace detail
|
|||||||
if(wd->flags.modal || (wd->owner == nullptr) || wd->owner->flags.take_active)
|
if(wd->flags.modal || (wd->owner == nullptr) || wd->owner->flags.take_active)
|
||||||
native_interface::activate_owner(wd->root);
|
native_interface::activate_owner(wd->root);
|
||||||
|
|
||||||
|
if (!wd->flags.destroying)
|
||||||
|
{
|
||||||
//Close should detach the drawer and send destroy signal to widget object.
|
//Close should detach the drawer and send destroy signal to widget object.
|
||||||
//Otherwise, when a widget object is been deleting in other thread by delete operator, the object will be destroyed
|
//Otherwise, when a widget object is been deleting in other thread by delete operator, the object will be destroyed
|
||||||
//before the window_manager destroyes the window, and then, window_manager detaches the
|
//before the window_manager destroyes the window, and then, window_manager detaches the
|
||||||
//non-existing drawer_trigger which is destroyed by destruction of widget. Crash!
|
//non-existing drawer_trigger which is destroyed by destruction of widget. Crash!
|
||||||
wd->drawer.detached();
|
wd->drawer.detached();
|
||||||
|
|
||||||
wd->widget_notifier->destroy();
|
wd->widget_notifier->destroy();
|
||||||
|
}
|
||||||
|
|
||||||
native_interface::close_window(wd->root);
|
native_interface::close_window(wd->root);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
#include <nana/gui/widgets/listbox.hpp>
|
#include <nana/gui/widgets/listbox.hpp>
|
||||||
#include <nana/gui/widgets/scroll.hpp>
|
#include <nana/gui/widgets/scroll.hpp>
|
||||||
#include <nana/gui/widgets/panel.hpp>
|
#include <nana/gui/widgets/panel.hpp> //for inline widget
|
||||||
|
|
||||||
#include <nana/gui/layout_utility.hpp>
|
#include <nana/gui/layout_utility.hpp>
|
||||||
#include <nana/gui/element.hpp>
|
#include <nana/gui/element.hpp>
|
||||||
@@ -438,11 +438,13 @@ namespace nana
|
|||||||
return pixels;
|
return pixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
/// return the original order or index previous to any list reorganization of the current column "n".
|
/// return the original order or index previous to any list reorganization of the current column "n".
|
||||||
size_type index(size_type n) const
|
size_type index(size_type n) const //deprecated
|
||||||
{
|
{
|
||||||
return (n < cont_.size() ? cont_[n].index : npos);
|
return (n < cont_.size() ? cont_[n].index : npos);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
const container& cont() const
|
const container& cont() const
|
||||||
{
|
{
|
||||||
@@ -539,23 +541,43 @@ namespace nana
|
|||||||
return npos;
|
return npos;
|
||||||
}
|
}
|
||||||
/// move the col originaly at index to the position currently in front (or after) the col originaly at index "to" invalidating some current index
|
/// move the col originaly at index to the position currently in front (or after) the col originaly at index "to" invalidating some current index
|
||||||
void move(size_type index, size_type to, bool front)
|
void move(size_type index, size_type to, bool front) throw()
|
||||||
{
|
{
|
||||||
if(index == to) return;
|
if(index == to) return;
|
||||||
if(index >= cont_.size()) return;
|
if(index >= cont_.size()) return;
|
||||||
if(to >= cont_.size()) return;
|
if(to >= cont_.size()) return;
|
||||||
|
|
||||||
auto i = std::find_if(cont_.begin(), cont_.end(), [index](container::value_type& m){return (index == m.index);});
|
for (auto i = cont_.begin(); i != cont_.end(); ++i)
|
||||||
|
{
|
||||||
|
if (index == i->index)
|
||||||
|
{
|
||||||
|
column_t from = std::move(*i);
|
||||||
|
cont_.erase(i);
|
||||||
|
|
||||||
|
for (auto u = cont_.begin(); u != cont_.end(); ++u)
|
||||||
|
{
|
||||||
|
if (to == u->index)
|
||||||
|
{
|
||||||
|
cont_.insert(front ? u : ++u, from);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
auto i = std::find_if(cont_.begin(), cont_.end(), [index](container::value_type& m){return (index == m.index);}); //deprecated
|
||||||
|
|
||||||
if (i == cont_.end())
|
if (i == cont_.end())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto from = *i; // a temp copy
|
column_t from = std::move(*i); //move
|
||||||
cont_.erase(i);
|
cont_.erase(i);
|
||||||
|
|
||||||
i = std::find_if(cont_.begin(), cont_.end(), [to](const container::value_type& m)->bool{ return (to == m.index); } );
|
i = std::find_if(cont_.begin(), cont_.end(), [to](const container::value_type& m)->bool{ return (to == m.index); } );
|
||||||
if(i != cont_.end())
|
if(i != cont_.end())
|
||||||
cont_.insert((front ? i : ++i), from);
|
cont_.insert((front ? i : ++i), from);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
bool visible_{true};
|
bool visible_{true};
|
||||||
@@ -842,8 +864,9 @@ namespace nana
|
|||||||
|
|
||||||
bool active_sort(bool resort)
|
bool active_sort(bool resort)
|
||||||
{
|
{
|
||||||
std::swap(resort, resort_);
|
bool prstatus = resort;
|
||||||
return resort;
|
resort_ = resort;
|
||||||
|
return prstatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sort_reverse() const
|
bool sort_reverse() const
|
||||||
@@ -2015,12 +2038,14 @@ namespace nana
|
|||||||
trace_item_abs(lister.last_selected_abs);
|
trace_item_abs(lister.last_selected_abs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void trace_first_selected_item()
|
/*
|
||||||
|
void trace_first_selected_item() //deprecated
|
||||||
{
|
{
|
||||||
auto fs=lister.find_first_selected();
|
auto fs=lister.find_first_selected();
|
||||||
if( ! fs.empty() )
|
if( ! fs.empty() )
|
||||||
trace_item_abs( fs );
|
trace_item_abs( fs );
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
void update()
|
void update()
|
||||||
{
|
{
|
||||||
@@ -2597,11 +2622,11 @@ namespace nana
|
|||||||
{
|
{
|
||||||
const auto& item = essence_->header.column(item_spliter_);
|
const auto& item = essence_->header.column(item_spliter_);
|
||||||
//Resize the item specified by item_spliter_.
|
//Resize the item specified by item_spliter_.
|
||||||
int new_w = orig_item_width_ - (ref_xpos_ - pos.x);
|
auto new_w = orig_item_width_ - (ref_xpos_ - pos.x);
|
||||||
if(static_cast<int>(item.pixels) != new_w)
|
if(static_cast<int>(item.pixels) != new_w)
|
||||||
{
|
{
|
||||||
essence_->header.item_width(item_spliter_, (new_w < static_cast<int>(essence_->suspension_width + 20) ? essence_->suspension_width + 20 : new_w));
|
essence_->header.item_width(item_spliter_, (new_w < static_cast<int>(essence_->suspension_width + 20) ? essence_->suspension_width + 20 : new_w));
|
||||||
auto new_w = essence_->header.pixels();
|
new_w = essence_->header.pixels();
|
||||||
if(new_w < (rect.width + essence_->scroll.offset_x))
|
if(new_w < (rect.width + essence_->scroll.offset_x))
|
||||||
essence_->scroll.offset_x = (new_w > rect.width ? new_w - rect.width : 0);
|
essence_->scroll.offset_x = (new_w > rect.width ? new_w - rect.width : 0);
|
||||||
|
|
||||||
@@ -2614,7 +2639,41 @@ namespace nana
|
|||||||
|
|
||||||
void draw(const nana::rectangle& r)
|
void draw(const nana::rectangle& r)
|
||||||
{
|
{
|
||||||
_m_draw(essence_->header.cont(), r);
|
//_m_draw(essence_->header.cont(), r); //deprecated
|
||||||
|
|
||||||
|
graph_reference graph = *(essence_->graph);
|
||||||
|
|
||||||
|
int text_top = (r.height - essence_->text_height) / 2 + r.y;
|
||||||
|
auto text_color = essence_->lister.wd_ptr()->fgcolor();
|
||||||
|
|
||||||
|
auto state = item_state::normal;
|
||||||
|
//check whether grabing an item, if item_spliter_ != npos, that indicates the grab item is a spliter.
|
||||||
|
if (essence_->pointer_where.first == parts::header && (item_spliter_ == npos))
|
||||||
|
state = essence_->ptr_state;
|
||||||
|
|
||||||
|
const unsigned height = r.height - 1;
|
||||||
|
const int bottom_y = r.bottom() - 2;
|
||||||
|
int x = r.x - essence_->scroll.offset_x;
|
||||||
|
|
||||||
|
for (auto & i : essence_->header.cont())
|
||||||
|
{
|
||||||
|
if (i.visible)
|
||||||
|
{
|
||||||
|
int next_x = x + static_cast<int>(i.pixels);
|
||||||
|
if (next_x > r.x)
|
||||||
|
{
|
||||||
|
_m_draw_header_item(graph, x, r.y, height, text_top, text_color, i, (i.index == essence_->pointer_where.second ? state : item_state::normal));
|
||||||
|
graph.line({ next_x - 1, r.y }, { next_x - 1, bottom_y }, _m_border_color());
|
||||||
|
}
|
||||||
|
|
||||||
|
x = next_x;
|
||||||
|
if (x > r.right())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x < r.right())
|
||||||
|
graph.rectangle({ x, r.y, static_cast<unsigned>(r.right() - x), height }, true, essence_->scheme_ptr->header_bgcolor);
|
||||||
|
|
||||||
const int y = r.y + r.height - 1;
|
const int y = r.y + r.height - 1;
|
||||||
essence_->graph->line({ r.x, y }, { r.x + static_cast<int>(r.width), y }, _m_border_color());
|
essence_->graph->line({ r.x, y }, { r.x + static_cast<int>(r.width), y }, _m_border_color());
|
||||||
@@ -2657,9 +2716,9 @@ namespace nana
|
|||||||
}
|
}
|
||||||
return npos;
|
return npos;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
template<typename Container>
|
template<typename Container>
|
||||||
void _m_draw(const Container& cont, const nana::rectangle& rect)
|
void _m_draw(const Container& cont, const nana::rectangle& rect) //deprecated
|
||||||
{
|
{
|
||||||
graph_reference graph = *(essence_->graph);
|
graph_reference graph = *(essence_->graph);
|
||||||
|
|
||||||
@@ -2694,6 +2753,7 @@ namespace nana
|
|||||||
if (x < rect.right())
|
if (x < rect.right())
|
||||||
graph.rectangle({ x, rect.y, static_cast<unsigned>(rect.right() - x), height }, true, essence_->scheme_ptr->header_bgcolor);
|
graph.rectangle({ x, rect.y, static_cast<unsigned>(rect.right() - x), height }, true, essence_->scheme_ptr->header_bgcolor);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
template<typename Item>
|
template<typename Item>
|
||||||
void _m_draw_header_item(graph_reference graph, int x, int y, unsigned height, int txtop, const ::nana::color& fgcolor, const Item& item, item_state state)
|
void _m_draw_header_item(graph_reference graph, int x, int y, unsigned height, int txtop, const ::nana::color& fgcolor, const Item& item, item_state state)
|
||||||
@@ -3166,10 +3226,12 @@ namespace nana
|
|||||||
delete essence_;
|
delete essence_;
|
||||||
}
|
}
|
||||||
|
|
||||||
essence_t& trigger::essence()
|
/*
|
||||||
|
essence_t& trigger::essence() //deprecated
|
||||||
{
|
{
|
||||||
return *essence_;
|
return *essence_;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
essence_t& trigger::essence() const
|
essence_t& trigger::essence() const
|
||||||
{
|
{
|
||||||
@@ -3513,10 +3575,8 @@ namespace nana
|
|||||||
case keyboard::os_arrow_up:
|
case keyboard::os_arrow_up:
|
||||||
up = true;
|
up = true;
|
||||||
case keyboard::os_arrow_down:
|
case keyboard::os_arrow_down:
|
||||||
// move_select(bool upwards=true, bool unselect_previous=true, bool trace_selected=false)
|
|
||||||
essence_->lister.move_select(up, !arg.shift, true);
|
essence_->lister.move_select(up, !arg.shift, true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STR(' ') :
|
case STR(' ') :
|
||||||
{
|
{
|
||||||
selection s;
|
selection s;
|
||||||
@@ -4501,7 +4561,7 @@ namespace nana
|
|||||||
return cat;
|
return cat;
|
||||||
}
|
}
|
||||||
|
|
||||||
void listbox::_m_ease_key(nana::detail::key_interface* p)
|
void listbox::_m_erase_key(nana::detail::key_interface* p)
|
||||||
{
|
{
|
||||||
auto & cont = _m_ess().lister.cat_container();
|
auto & cont = _m_ess().lister.cat_container();
|
||||||
|
|
||||||
|
|||||||
@@ -1270,3 +1270,295 @@ namespace nana
|
|||||||
}//end namespace tabbar
|
}//end namespace tabbar
|
||||||
}//end namespace drawerbase
|
}//end namespace drawerbase
|
||||||
}//end namespace nana
|
}//end namespace nana
|
||||||
|
|
||||||
|
#include <forward_list>
|
||||||
|
namespace nana
|
||||||
|
{
|
||||||
|
namespace ng
|
||||||
|
{
|
||||||
|
namespace drawerbase
|
||||||
|
{
|
||||||
|
namespace tabbar_lite
|
||||||
|
{
|
||||||
|
struct item
|
||||||
|
{
|
||||||
|
::std::string text;
|
||||||
|
::nana::any value;
|
||||||
|
::std::pair<int, int> pos_ends;
|
||||||
|
|
||||||
|
item(std::string t, ::nana::any v)
|
||||||
|
: text(std::move(t)), value(std::move(v))
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
void calc_px(std::vector<unsigned>& values, unsigned limit)
|
||||||
|
{
|
||||||
|
unsigned base = 0;
|
||||||
|
auto count = values.size();
|
||||||
|
|
||||||
|
while (count)
|
||||||
|
{
|
||||||
|
unsigned minv = static_cast<unsigned>(-1);
|
||||||
|
|
||||||
|
unsigned minv_count = 0;
|
||||||
|
for (auto u : values)
|
||||||
|
{
|
||||||
|
if (u >= base && u < minv)
|
||||||
|
{
|
||||||
|
minv_count = 1;
|
||||||
|
minv = u;
|
||||||
|
}
|
||||||
|
else if (minv == u)
|
||||||
|
minv_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
count -= minv_count;
|
||||||
|
if (minv * count >= limit)
|
||||||
|
{
|
||||||
|
auto piece = limit / double(count);
|
||||||
|
double deviation = 0;
|
||||||
|
for (auto & u : values)
|
||||||
|
{
|
||||||
|
if (minv >= u)
|
||||||
|
{
|
||||||
|
auto px = piece + deviation;
|
||||||
|
u = static_cast<unsigned>(px);
|
||||||
|
deviation = px - u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
base = minv;
|
||||||
|
limit -= minv_count * minv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class model
|
||||||
|
{
|
||||||
|
struct indexes
|
||||||
|
{
|
||||||
|
std::size_t hovered_pos{ npos };
|
||||||
|
std::size_t active_pos{ 0 };
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
using graph_reference = ::nana::paint::graphics&;
|
||||||
|
static const std::size_t npos = static_cast<std::size_t>(-1);
|
||||||
|
|
||||||
|
void set_widget(widget& wdg)
|
||||||
|
{
|
||||||
|
widget_ = &wdg;
|
||||||
|
}
|
||||||
|
|
||||||
|
::nana::dev::widget_traits<widget>::scheme_type & scheme()
|
||||||
|
{
|
||||||
|
return API::scheme(*widget_);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::forward_list<item>& items()
|
||||||
|
{
|
||||||
|
return items_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool track_pointer(const point& pos)
|
||||||
|
{
|
||||||
|
std::size_t item_pos = 0;
|
||||||
|
bool matched = false;
|
||||||
|
for (auto & m : items_)
|
||||||
|
{
|
||||||
|
if (m.pos_ends.first <= pos.x && pos.x < m.pos_ends.second)
|
||||||
|
{
|
||||||
|
matched = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
++item_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!matched)
|
||||||
|
item_pos = npos;
|
||||||
|
|
||||||
|
if (indexes_.hovered_pos == item_pos)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
indexes_.hovered_pos = item_pos;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
indexes& get_indexes()
|
||||||
|
{
|
||||||
|
return indexes_;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
widget * widget_{ nullptr };
|
||||||
|
std::forward_list<item> items_;
|
||||||
|
indexes indexes_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class renderer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using graph_reference = ::nana::paint::graphics&;
|
||||||
|
|
||||||
|
void render(graph_reference graph, model& model)
|
||||||
|
{
|
||||||
|
_m_calc_metrics(graph, model.items());
|
||||||
|
|
||||||
|
auto & scheme = model.scheme();
|
||||||
|
|
||||||
|
//draw background
|
||||||
|
graph.rectangle(true, scheme.background);
|
||||||
|
|
||||||
|
auto & indexes = model.get_indexes();
|
||||||
|
std::size_t pos = 0;
|
||||||
|
for (auto & m : model.items())
|
||||||
|
{
|
||||||
|
rectangle r{ m.pos_ends.first, 0, static_cast<unsigned>(m.pos_ends.second - m.pos_ends.first), graph.height() };
|
||||||
|
if (indexes.active_pos == pos)
|
||||||
|
{
|
||||||
|
graph.set_color(colors::white);
|
||||||
|
graph.set_text_color(colors::black);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
::nana::color bgcolor(colors::coral);
|
||||||
|
|
||||||
|
if (pos == indexes.hovered_pos)
|
||||||
|
bgcolor = bgcolor.blend(colors::white, 0.5);
|
||||||
|
|
||||||
|
graph.set_color(bgcolor);
|
||||||
|
graph.set_text_color(colors::white);
|
||||||
|
}
|
||||||
|
|
||||||
|
graph.rectangle(r, true);
|
||||||
|
graph.bidi_string({ m.pos_ends.first + 5, 0 }, m.text.data(), m.text.size());
|
||||||
|
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
void _m_calc_metrics(graph_reference graph, std::forward_list<item>& items)
|
||||||
|
{
|
||||||
|
std::vector<unsigned> pxs;
|
||||||
|
|
||||||
|
unsigned pixels = 0;
|
||||||
|
for (auto & m : items)
|
||||||
|
{
|
||||||
|
auto ts = graph.bidi_extent_size(m.text);
|
||||||
|
pxs.push_back(ts.width + 12);
|
||||||
|
pixels += ts.width + 12;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pixels > graph.width())
|
||||||
|
calc_px(pxs, graph.width());
|
||||||
|
|
||||||
|
auto i = pxs.cbegin();
|
||||||
|
int pos = 0;
|
||||||
|
for (auto & m : items)
|
||||||
|
{
|
||||||
|
m.pos_ends.first = pos;
|
||||||
|
m.pos_ends.second = (pos += static_cast<int>(*i++));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//class driver
|
||||||
|
driver::driver()
|
||||||
|
: model_(new model)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
driver::~driver()
|
||||||
|
{
|
||||||
|
delete model_;
|
||||||
|
}
|
||||||
|
|
||||||
|
model* driver::get_model()
|
||||||
|
{
|
||||||
|
return model_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void driver::attached(widget_reference wdg, graph_reference)
|
||||||
|
{
|
||||||
|
model_->set_widget(wdg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Overrides drawer_trigger's method
|
||||||
|
void driver::refresh(graph_reference graph)
|
||||||
|
{
|
||||||
|
renderer rd;
|
||||||
|
rd.render(graph, *model_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void driver::mouse_move(graph_reference graph, const arg_mouse& arg)
|
||||||
|
{
|
||||||
|
if (!model_->track_pointer(arg.pos))
|
||||||
|
return;
|
||||||
|
|
||||||
|
refresh(graph);
|
||||||
|
API::lazy_refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void driver::mouse_leave(graph_reference graph, const arg_mouse&)
|
||||||
|
{
|
||||||
|
if (model_->get_indexes().hovered_pos == model_->npos)
|
||||||
|
return;
|
||||||
|
|
||||||
|
refresh(graph);
|
||||||
|
API::lazy_refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void driver::mouse_down(graph_reference graph, const arg_mouse&)
|
||||||
|
{
|
||||||
|
auto & indexes = model_->get_indexes();
|
||||||
|
if (indexes.hovered_pos == model_->npos)
|
||||||
|
return;
|
||||||
|
|
||||||
|
indexes.active_pos = indexes.hovered_pos;
|
||||||
|
refresh(graph);
|
||||||
|
API::lazy_refresh();
|
||||||
|
}
|
||||||
|
//end class driver
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//class tabbar
|
||||||
|
|
||||||
|
tabbar_lite::tabbar_lite(window parent_wd, bool visible, const ::nana::rectangle& r)
|
||||||
|
{
|
||||||
|
this->create(parent_wd, r, visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tabbar_lite::push_back(std::string text, ::nana::any any)
|
||||||
|
{
|
||||||
|
auto & items = get_drawer_trigger().get_model()->items();
|
||||||
|
internal_scope_guard lock;
|
||||||
|
|
||||||
|
auto i = items.cbefore_begin();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
auto next = i++;
|
||||||
|
if (i == items.cend())
|
||||||
|
{
|
||||||
|
items.emplace_after(next, std::move(text), std::move(any));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
API::refresh_window(handle());
|
||||||
|
}
|
||||||
|
|
||||||
|
void tabbar_lite::push_front(std::string text, ::nana::any any)
|
||||||
|
{
|
||||||
|
auto & items = get_drawer_trigger().get_model()->items();
|
||||||
|
internal_scope_guard lock;
|
||||||
|
|
||||||
|
items.emplace_front(std::move(text), std::move(any));
|
||||||
|
API::refresh_window(handle());
|
||||||
|
}
|
||||||
|
//end class tabbar
|
||||||
|
}
|
||||||
|
}//end namespace nana
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ namespace nana
|
|||||||
|
|
||||||
//class widget
|
//class widget
|
||||||
//@brief:The definition of class widget
|
//@brief:The definition of class widget
|
||||||
class widget::notifier: public detail::widget_notifier_interface
|
class widget::inner_widget_notifier : public detail::widget_notifier_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
notifier(widget& wdg)
|
inner_widget_notifier(widget& wdg)
|
||||||
: wdg_(wdg)
|
: wdg_(wdg)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -246,7 +246,7 @@ namespace nana
|
|||||||
|
|
||||||
std::unique_ptr<::nana::detail::widget_notifier_interface> widget::_m_wdg_notifier()
|
std::unique_ptr<::nana::detail::widget_notifier_interface> widget::_m_wdg_notifier()
|
||||||
{
|
{
|
||||||
return std::unique_ptr<::nana::detail::widget_notifier_interface>(new notifier(*this));
|
return std::unique_ptr<::nana::detail::widget_notifier_interface>(new inner_widget_notifier(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void widget::_m_complete_creation()
|
void widget::_m_complete_creation()
|
||||||
@@ -348,7 +348,7 @@ namespace nana
|
|||||||
{
|
{
|
||||||
std::unique_ptr<widget_notifier_interface> widget_notifier_interface::get_notifier(widget* wdg)
|
std::unique_ptr<widget_notifier_interface> widget_notifier_interface::get_notifier(widget* wdg)
|
||||||
{
|
{
|
||||||
return std::unique_ptr<widget_notifier_interface>(new widget::notifier(*wdg));
|
return std::unique_ptr<widget_notifier_interface>(new widget::inner_widget_notifier(*wdg));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}//end namespace nana
|
}//end namespace nana
|
||||||
|
|||||||
@@ -55,6 +55,21 @@ namespace nana
|
|||||||
const int png_width = ::png_get_image_width(png_ptr, info_ptr);
|
const int png_width = ::png_get_image_width(png_ptr, info_ptr);
|
||||||
const int png_height = ::png_get_image_height(png_ptr, info_ptr);
|
const int png_height = ::png_get_image_height(png_ptr, info_ptr);
|
||||||
png_byte color_type = ::png_get_color_type(png_ptr, info_ptr);
|
png_byte color_type = ::png_get_color_type(png_ptr, info_ptr);
|
||||||
|
const auto bit_depth = ::png_get_bit_depth(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
//do some extra work for palette/gray color type
|
||||||
|
if (PNG_COLOR_TYPE_PALETTE == color_type)
|
||||||
|
::png_set_palette_to_rgb(png_ptr);
|
||||||
|
else if ((PNG_COLOR_TYPE_GRAY == color_type) && (bit_depth < 8))
|
||||||
|
::png_set_gray_to_rgb(png_ptr);
|
||||||
|
|
||||||
|
bool is_alpha_enabled = (::png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) != 0);
|
||||||
|
if (is_alpha_enabled)
|
||||||
|
::png_set_tRNS_to_alpha(png_ptr);
|
||||||
|
|
||||||
|
//make sure 8-bit per channel
|
||||||
|
if (16 == bit_depth)
|
||||||
|
::png_set_strip_16(png_ptr);
|
||||||
|
|
||||||
::png_set_interlace_handling(png_ptr);
|
::png_set_interlace_handling(png_ptr);
|
||||||
::png_read_update_info(png_ptr, info_ptr);
|
::png_read_update_info(png_ptr, info_ptr);
|
||||||
@@ -65,7 +80,7 @@ namespace nana
|
|||||||
|
|
||||||
pixbuf_.open(png_width, png_height);
|
pixbuf_.open(png_width, png_height);
|
||||||
|
|
||||||
const bool is_alpha_enabled = ((PNG_COLOR_MASK_ALPHA & color_type) != 0);
|
is_alpha_enabled |= ((PNG_COLOR_MASK_ALPHA & color_type) != 0);
|
||||||
pixbuf_.alpha_channel(is_alpha_enabled);
|
pixbuf_.alpha_channel(is_alpha_enabled);
|
||||||
|
|
||||||
if(is_alpha_enabled && (png_rowbytes == png_width * sizeof(pixel_argb_t)))
|
if(is_alpha_enabled && (png_rowbytes == png_width * sizeof(pixel_argb_t)))
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
* http://www.boost.org/LICENSE_1_0.txt)
|
* http://www.boost.org/LICENSE_1_0.txt)
|
||||||
*
|
*
|
||||||
* @file: nana/paint/detail/native_paint_interface.cpp
|
* @file: nana/paint/detail/native_paint_interface.cpp
|
||||||
|
* @contributors: dareg
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <nana/config.hpp>
|
#include <nana/config.hpp>
|
||||||
@@ -187,7 +188,9 @@ namespace detail
|
|||||||
reinterpret_cast<XftChar8*>(const_cast<char*>(utf8str.c_str())), utf8str.size());
|
reinterpret_cast<XftChar8*>(const_cast<char*>(utf8str.c_str())), utf8str.size());
|
||||||
*/
|
*/
|
||||||
auto fs = reinterpret_cast<XftFont*>(dw->font->handle);
|
auto fs = reinterpret_cast<XftFont*>(dw->font->handle);
|
||||||
std::unique_ptr<FT_UInt> glyphs_ptr(new FT_UInt[len]);
|
|
||||||
|
//Fixed missing array declaration by dareg
|
||||||
|
std::unique_ptr<FT_UInt[]> glyphs_ptr(new FT_UInt[len]);
|
||||||
auto glyphs = glyphs_ptr.get();
|
auto glyphs = glyphs_ptr.get();
|
||||||
const auto endstr = str + len;
|
const auto endstr = str + len;
|
||||||
for(auto chr = str; chr != endstr; ++chr)
|
for(auto chr = str; chr != endstr; ++chr)
|
||||||
|
|||||||
@@ -451,7 +451,7 @@ namespace paint
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
nana::size graphics::bidi_extent_size(const nana::string& str) const
|
nana::size graphics::bidi_extent_size(const std::wstring& str) const
|
||||||
{
|
{
|
||||||
nana::size sz;
|
nana::size sz;
|
||||||
#if defined NANA_UNICODE
|
#if defined NANA_UNICODE
|
||||||
@@ -472,6 +472,11 @@ namespace paint
|
|||||||
return sz;
|
return sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::nana::size graphics::bidi_extent_size(const std::string& str) const
|
||||||
|
{
|
||||||
|
return bidi_extent_size(std::wstring{ ::nana::charset(str, ::nana::unicode::utf8) });
|
||||||
|
}
|
||||||
|
|
||||||
bool graphics::text_metrics(unsigned & ascent, unsigned& descent, unsigned& internal_leading) const
|
bool graphics::text_metrics(unsigned & ascent, unsigned& descent, unsigned& internal_leading) const
|
||||||
{
|
{
|
||||||
if(handle_)
|
if(handle_)
|
||||||
@@ -883,6 +888,12 @@ namespace paint
|
|||||||
return static_cast<unsigned>(moved_pos.x - pos.x);
|
return static_cast<unsigned>(moved_pos.x - pos.x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned graphics::bidi_string(const point& pos, const char* str, std::size_t len)
|
||||||
|
{
|
||||||
|
std::wstring wstr = ::nana::charset(std::string(str, str + len), ::nana::unicode::utf8);
|
||||||
|
return bidi_string(pos, wstr.data(), wstr.size());
|
||||||
|
}
|
||||||
|
|
||||||
void graphics::blend(const nana::rectangle& r, const ::nana::color& clr, double fade_rate)
|
void graphics::blend(const nana::rectangle& r, const ::nana::color& clr, double fade_rate)
|
||||||
{
|
{
|
||||||
if (handle_)
|
if (handle_)
|
||||||
|
|||||||
Reference in New Issue
Block a user