Merge branch 'hotfixes-1.0.2' into develop
Conflicts: include/nana/gui/detail/basic_window.hpp include/nana/gui/widgets/listbox.hpp source/gui/detail/linux_X11/bedrock.cpp source/gui/detail/win32/bedrock.cpp source/gui/detail/window_layout.cpp source/gui/detail/window_manager.cpp source/gui/widgets/listbox.cpp source/gui/widgets/toolbar.cpp
This commit is contained in:
@@ -151,7 +151,7 @@ namespace nana{ namespace drawerbase
|
||||
|
||||
void trigger::key_char(graph_reference, const arg_keyboard& arg)
|
||||
{
|
||||
if(arg.key == static_cast<char_t>(keyboard::enter))
|
||||
if (static_cast<char_t>(keyboard::enter) == arg.key || static_cast<char_t>(keyboard::space) == arg.key)
|
||||
emit_click();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include <nana/gui/widgets/skeletons/text_editor.hpp>
|
||||
#include <nana/gui/widgets/skeletons/textbase_export_interface.hpp>
|
||||
|
||||
#include <iterator>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
arg_combox::arg_combox(combox& wdg): widget(wdg)
|
||||
|
||||
@@ -402,18 +402,20 @@ namespace nana
|
||||
return{};
|
||||
}
|
||||
|
||||
void create(nana::string&& text, unsigned pixels)
|
||||
size_type create(nana::string&& text, unsigned pixels)
|
||||
{
|
||||
cont_.emplace_back(std::move(text), pixels, static_cast<size_type>(cont_.size()));
|
||||
return cont_.back().index;
|
||||
}
|
||||
|
||||
void item_width(size_type pos, unsigned width)
|
||||
{
|
||||
for(auto & m : cont_)
|
||||
{
|
||||
if(m.index == pos)
|
||||
{
|
||||
m.pixels = width;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned item_width(size_type pos) const
|
||||
@@ -1606,31 +1608,7 @@ namespace nana
|
||||
}
|
||||
|
||||
/// set all items in cat to selection sel, emiting events, actualizing last_selected_abs, but not check for single_selection_
|
||||
bool categ_selected(size_type cat, bool sel)
|
||||
{
|
||||
bool changed = false;
|
||||
auto & items = _m_at(cat)->items;
|
||||
|
||||
index_pair pos(cat, 0);
|
||||
for(auto & m : items)
|
||||
{
|
||||
if(m.flags.selected != sel)
|
||||
{
|
||||
m.flags.selected = sel;
|
||||
|
||||
arg_listbox arg{ item_proxy(ess_, pos), sel };
|
||||
wd_ptr()->events().selected.emit(arg);
|
||||
changed = true;
|
||||
|
||||
if (sel) // not check for single_selection_
|
||||
last_selected_abs = pos;
|
||||
else if (last_selected_abs == pos)
|
||||
last_selected_abs.set_both(npos);
|
||||
}
|
||||
++pos.item;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
void categ_selected(size_type cat, bool sel);
|
||||
|
||||
void reverse_categ_selected(size_type categ)
|
||||
{
|
||||
@@ -1658,9 +1636,22 @@ namespace nana
|
||||
/// absolute position of the last displayed item
|
||||
index_pair last_displ() const
|
||||
{
|
||||
return absolute ( last_displ() );
|
||||
return absolute ( last() );
|
||||
}
|
||||
|
||||
/// can be used as the absolute position of the first absolute item, or as the display pos of the first displayed item
|
||||
index_pair first() const
|
||||
{
|
||||
index_pair fst{0,npos};
|
||||
good_item(fst,fst);
|
||||
return fst;
|
||||
}
|
||||
/// absolute position of the first displayed item
|
||||
index_pair first_displ() const
|
||||
{
|
||||
return absolute ( first() );
|
||||
}
|
||||
|
||||
bool good(size_type cat) const
|
||||
{
|
||||
return (cat < list_.size());
|
||||
@@ -1670,32 +1661,32 @@ namespace nana
|
||||
{
|
||||
return ((pos.cat < list_.size()) && (pos.item < size_item(pos.cat)));
|
||||
}
|
||||
|
||||
/// if good return the same item (in arg item), or just the next cat and true, but If fail return false
|
||||
bool good_item(index_pair pos, index_pair& item) const
|
||||
{
|
||||
if (!good(pos.cat))
|
||||
return false;
|
||||
return false; // cat out of range
|
||||
|
||||
if (pos.is_category())
|
||||
{
|
||||
item = pos;
|
||||
if (0 == pos.cat)
|
||||
item.item = 0;
|
||||
|
||||
return true;
|
||||
item = pos; // return the cat self
|
||||
if (0 == pos.cat) // but for cat 0 return first item
|
||||
item.item = 0; // let check this is good
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
auto i = _m_at(pos.cat);
|
||||
auto i = _m_at(pos.cat); // pos is not a cat and i point to it cat
|
||||
if (pos.item < i->items.size())
|
||||
{
|
||||
item = pos;
|
||||
item = pos; // good item, return it
|
||||
return true;
|
||||
}
|
||||
|
||||
if (++i == list_.end())
|
||||
if (++i == list_.end()) // item out of range and no more cat
|
||||
return false;
|
||||
|
||||
item.cat = pos.cat + 1;
|
||||
item.cat = pos.cat + 1; // select the next cat
|
||||
item.item = npos;
|
||||
return true;
|
||||
}
|
||||
@@ -1703,7 +1694,7 @@ namespace nana
|
||||
///Translate relative position (position in display) into absolute position (original data order)
|
||||
size_type absolute(const index_pair& display_pos) const
|
||||
{
|
||||
if(sorted_index_ == npos)
|
||||
if(sorted_index_ == npos || display_pos.item == npos)
|
||||
return display_pos.item ;
|
||||
|
||||
auto & catobj = *_m_at(display_pos.cat);
|
||||
@@ -2202,7 +2193,7 @@ namespace nana
|
||||
}
|
||||
else
|
||||
{
|
||||
new_where.second = (y - header_visible_px() + 1) / item_size;
|
||||
new_where.second = ((y + 1) - header_visible_px()) / item_size; // y>1 !
|
||||
new_where.first = parts::lister;
|
||||
if(checkable)
|
||||
{
|
||||
@@ -2324,6 +2315,27 @@ namespace nana
|
||||
}
|
||||
}
|
||||
|
||||
unsigned auto_width(size_type pos, unsigned max = 3000) /// \todo introduce parametr max_header_width
|
||||
{
|
||||
unsigned max_w{ 0 };
|
||||
for (const auto &cat : lister.cat_container())
|
||||
for (const auto &it : cat.items)
|
||||
{
|
||||
if (pos >= it.cells.size()) continue;
|
||||
// precalcule text geometry
|
||||
unsigned ts = static_cast<unsigned> (graph->text_extent_size(it.cells[pos].text).width);
|
||||
if (max_w < ts)
|
||||
max_w = ts;
|
||||
}
|
||||
if (!max_w) return 0;
|
||||
|
||||
unsigned ext_w = scheme_ptr->ext_w;
|
||||
if (pos == 0 && checkable) // only before the first column (display_order=0 ?)
|
||||
ext_w += 18;
|
||||
header.item_width(pos, max_w + ext_w + 1 < max ? max_w + ext_w + 1 : max);
|
||||
return max_w;
|
||||
}
|
||||
|
||||
inline_pane * open_inline(pat::abstract_factory<inline_notifier_interface>* factory, inline_indicator* indicator)
|
||||
{
|
||||
std::unique_ptr<inline_pane> pane_ptr;
|
||||
@@ -2494,7 +2506,7 @@ namespace nana
|
||||
}
|
||||
}
|
||||
|
||||
nana::string es_lister::to_string(const export_options& exp_opt) const
|
||||
nana::string es_lister::to_string(const export_options& exp_opt) const
|
||||
{
|
||||
nana::string list_str;
|
||||
bool first{true};
|
||||
@@ -2515,6 +2527,17 @@ namespace nana
|
||||
return list_str ;
|
||||
}
|
||||
|
||||
void es_lister::categ_selected(size_type cat, bool sel)
|
||||
{
|
||||
cat_proxy cpx{ess_,cat};
|
||||
for (item_proxy &it : cpx )
|
||||
{
|
||||
if (it.selected() != sel)
|
||||
it.select(sel);
|
||||
}
|
||||
|
||||
last_selected_abs = last_selected_dpl = index_pair {cat, npos};
|
||||
}
|
||||
|
||||
class drawer_header_impl
|
||||
{
|
||||
@@ -3450,6 +3473,14 @@ namespace nana
|
||||
|
||||
void trigger::dbl_click(graph_reference graph, const arg_mouse&)
|
||||
{
|
||||
if (essence_->pointer_where.first == essence_t::parts::header)
|
||||
if (cursor::size_we == essence_->lister.wd_ptr()->cursor())
|
||||
{
|
||||
if (essence(). auto_width(drawer_header_->item_spliter() )) // ? in order
|
||||
essence().update();
|
||||
return;
|
||||
}
|
||||
|
||||
if (essence_->pointer_where.first != essence_t::parts::lister)
|
||||
return;
|
||||
|
||||
@@ -3518,21 +3549,35 @@ namespace nana
|
||||
if (! scrl.make_page_scroll(!up))
|
||||
return;
|
||||
essence_->lister.select_for_all(false);
|
||||
if (up)
|
||||
item_proxy {essence_, essence_->scroll_y_abs()}.select(true);
|
||||
else
|
||||
{
|
||||
index_pair idx{essence_->scroll_y_dpl()};
|
||||
|
||||
index_pair idx{essence_->scroll_y_dpl()};
|
||||
if (!up)
|
||||
essence_->lister.forward(idx, scrl.range()-1, idx);
|
||||
item_proxy::from_display(essence_,idx).select(true);
|
||||
}
|
||||
|
||||
if (idx.is_item())
|
||||
item_proxy::from_display(essence_, idx).select(true);
|
||||
else
|
||||
if(!essence_->lister.single_selection())
|
||||
essence_->lister.categ_selected(idx.cat, true);
|
||||
|
||||
essence_->trace_last_selected_item ();
|
||||
|
||||
break;
|
||||
}
|
||||
case keyboard::os_home:
|
||||
{
|
||||
essence_->lister.select_for_all(false);
|
||||
item_proxy::from_display(essence_, {0,0}).select(true);
|
||||
|
||||
index_pair frst{essence_->lister.first()};
|
||||
if (frst.is_item())
|
||||
item_proxy::from_display(essence_, frst).select(true);
|
||||
else
|
||||
if(!essence_->lister.single_selection())
|
||||
essence_->lister.categ_selected(frst.cat, true);
|
||||
|
||||
essence_->trace_last_selected_item ();
|
||||
break;
|
||||
}
|
||||
case keyboard::os_end:
|
||||
essence_->lister.select_for_all(false);
|
||||
item_proxy::from_display(essence_, essence_->lister.last()).select(true);
|
||||
@@ -3584,7 +3629,7 @@ namespace nana
|
||||
{
|
||||
auto i = ess_->lister.cat_container().begin();
|
||||
std::advance(i, pos.cat);
|
||||
cat_ = &(*i);
|
||||
cat_ = &(*i); // what is pos is a cat?
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3617,6 +3662,7 @@ namespace nana
|
||||
m.flags.checked = ck;
|
||||
arg_listbox arg{*this, ck};
|
||||
ess_->lister.wd_ptr()->events().checked.emit(arg);
|
||||
ess_->update();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -3629,7 +3675,7 @@ namespace nana
|
||||
/// is ignored if no change (maybe set last_selected anyway??), but if change emit event, deselect others if need ans set/unset last_selected
|
||||
item_proxy & item_proxy::select(bool s)
|
||||
{
|
||||
auto & m = cat_->items.at(pos_.item); // a ref to the real item
|
||||
auto & m = cat_->items.at(pos_.item); // a ref to the real item // what is pos is a cat?
|
||||
if(m.flags.selected == s) return *this; // ignore if no change
|
||||
m.flags.selected = s; // actually change selection
|
||||
|
||||
@@ -3646,6 +3692,7 @@ namespace nana
|
||||
|
||||
ess_->update();
|
||||
|
||||
ess_->update();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -3865,6 +3912,24 @@ namespace nana
|
||||
}
|
||||
}
|
||||
|
||||
cat_proxy & cat_proxy::select(bool sel)
|
||||
{
|
||||
for (item_proxy &it : *this )
|
||||
it.select(sel);
|
||||
|
||||
ess_->lister.last_selected_abs =
|
||||
ess_->lister.last_selected_dpl = index_pair {this->pos_, npos};
|
||||
|
||||
return *this;
|
||||
}
|
||||
bool cat_proxy::selected() const
|
||||
{
|
||||
for (item_proxy &it : *this )
|
||||
if (!it.selected())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
auto cat_proxy::columns() const -> size_type
|
||||
{
|
||||
return ess_->header.cont().size();
|
||||
@@ -3907,6 +3972,11 @@ namespace nana
|
||||
//Behavior of a container
|
||||
item_proxy cat_proxy::begin() const
|
||||
{
|
||||
auto i = ess_->lister.cat_container().begin();
|
||||
std::advance(i, pos_);
|
||||
if (i->items.empty())
|
||||
return end();
|
||||
|
||||
return item_proxy(ess_, index_pair(pos_, 0));
|
||||
}
|
||||
|
||||
@@ -4121,11 +4191,12 @@ namespace nana
|
||||
_m_ess().set_auto_draw(ad);
|
||||
}
|
||||
|
||||
void listbox::append_header(nana::string text, unsigned width)
|
||||
listbox::size_type listbox::append_header(nana::string text, unsigned width)
|
||||
{
|
||||
auto & ess = _m_ess();
|
||||
ess.header.create(std::move(text), width);
|
||||
listbox::size_type index = ess.header.create(std::move(text), width);
|
||||
ess.update();
|
||||
return index;
|
||||
}
|
||||
|
||||
listbox& listbox::header_width(size_type pos, unsigned pixels)
|
||||
@@ -4135,6 +4206,13 @@ namespace nana
|
||||
ess.update();
|
||||
return *this;
|
||||
}
|
||||
unsigned listbox::auto_width(size_type pos, unsigned max)
|
||||
{
|
||||
auto & ess = _m_ess();
|
||||
unsigned max_w = ess.auto_width(pos, max);
|
||||
ess.update();
|
||||
return max_w;
|
||||
}
|
||||
|
||||
unsigned listbox::header_width(size_type pos) const
|
||||
{
|
||||
|
||||
@@ -114,7 +114,7 @@ namespace nana
|
||||
{
|
||||
if(at.item_state == state::active)
|
||||
{
|
||||
graph.rectangle(r, false, {0xa8, 0xd8, 0xeb});
|
||||
graph.rectangle(r, false, static_cast<color_rgb>(0xa8d8eb));
|
||||
nana::point points[4] = {
|
||||
nana::point(r.x, r.y),
|
||||
nana::point(r.x + r.width - 1, r.y),
|
||||
@@ -144,9 +144,9 @@ namespace nana
|
||||
}
|
||||
}
|
||||
|
||||
void item_image(graph_reference graph, const nana::point& pos, const paint::image& img)
|
||||
void item_image(graph_reference graph, const nana::point& pos, unsigned image_px, const paint::image& img)
|
||||
{
|
||||
img.paste(graph, pos.x, pos.y);
|
||||
img.stretch(rectangle{ img.size() }, graph, rectangle{ pos, ::nana::size(image_px, image_px) });
|
||||
}
|
||||
|
||||
void item_text(graph_reference graph, const nana::point& pos, const nana::string& text, unsigned text_pixels, const attr& at)
|
||||
@@ -200,35 +200,35 @@ namespace nana
|
||||
|
||||
void checked(std::size_t index, bool check)
|
||||
{
|
||||
if(root_.items.size() > index)
|
||||
if (root_.items.size() <= index)
|
||||
return;
|
||||
|
||||
item_type & m = root_.items[index];
|
||||
if(check && (checks::option == m.style))
|
||||
{
|
||||
item_type & m = root_.items[index];
|
||||
if(check && (checks::option == m.style))
|
||||
if(index)
|
||||
{
|
||||
if(index)
|
||||
std::size_t i = index;
|
||||
do
|
||||
{
|
||||
std::size_t i = index;
|
||||
do
|
||||
{
|
||||
item_type& el = root_.items[--i];
|
||||
if(el.flags.splitter) break;
|
||||
|
||||
if(checks::option == el.style)
|
||||
el.flags.checked = false;
|
||||
}while(i);
|
||||
}
|
||||
|
||||
for(std::size_t i = index + 1; i < root_.items.size(); ++i)
|
||||
{
|
||||
item_type & el = root_.items[i];
|
||||
item_type& el = root_.items[--i];
|
||||
if(el.flags.splitter) break;
|
||||
|
||||
if(checks::option == el.style)
|
||||
el.flags.checked = false;
|
||||
}
|
||||
}while(i);
|
||||
}
|
||||
|
||||
for(std::size_t i = index + 1; i < root_.items.size(); ++i)
|
||||
{
|
||||
item_type & el = root_.items[i];
|
||||
if(el.flags.splitter) break;
|
||||
|
||||
if(checks::option == el.style)
|
||||
el.flags.checked = false;
|
||||
}
|
||||
m.flags.checked = check;
|
||||
}
|
||||
m.flags.checked = check;
|
||||
}
|
||||
|
||||
menu_type& data()
|
||||
@@ -304,7 +304,7 @@ namespace nana
|
||||
: public drawer_trigger
|
||||
{
|
||||
public:
|
||||
typedef menu_item_type::item_proxy item_proxy;
|
||||
using item_proxy = menu_item_type::item_proxy;
|
||||
|
||||
renderer_interface * renderer;
|
||||
|
||||
@@ -330,12 +330,12 @@ namespace nana
|
||||
detail_.monitor_pos = API::cursor_position();
|
||||
}
|
||||
|
||||
void mouse_move(graph_reference, const arg_mouse& arg)
|
||||
void mouse_move(graph_reference graph, const arg_mouse& arg)
|
||||
{
|
||||
state_.nullify_mouse = false;
|
||||
if(track_mouse(arg.pos.x, arg.pos.y))
|
||||
if(track_mouse(arg.pos))
|
||||
{
|
||||
draw();
|
||||
refresh(graph);
|
||||
API::lazy_refresh();
|
||||
}
|
||||
}
|
||||
@@ -350,9 +350,70 @@ namespace nana
|
||||
state_.nullify_mouse = false;
|
||||
}
|
||||
|
||||
void refresh(graph_reference)
|
||||
void refresh(graph_reference graph)
|
||||
{
|
||||
draw();
|
||||
if (nullptr == menu_) return;
|
||||
|
||||
_m_adjust_window_size();
|
||||
|
||||
renderer->background(graph, *widget_);
|
||||
|
||||
const unsigned item_h_px = _m_item_height();
|
||||
const unsigned image_px = item_h_px - 2;
|
||||
nana::rectangle item_r(2, 2, graph_->width() - 4, item_h_px);
|
||||
|
||||
unsigned strpixels = item_r.width - 60;
|
||||
|
||||
int text_top_off = (item_h_px - graph.text_extent_size(STR("jh({[")).height) / 2;
|
||||
|
||||
std::size_t pos = 0;
|
||||
for (auto & m : menu_->items)
|
||||
{
|
||||
if (m.flags.splitter)
|
||||
{
|
||||
graph_->set_color(colors::gray_border);
|
||||
graph_->line({ item_r.x + 40, item_r.y }, { static_cast<int>(graph.width()) - 1, item_r.y });
|
||||
item_r.y += 2;
|
||||
++pos;
|
||||
continue;
|
||||
}
|
||||
|
||||
renderer_interface::attr attr = _m_make_renderer_attr(pos == state_.active, m);
|
||||
//Draw item background
|
||||
renderer->item(*graph_, item_r, attr);
|
||||
|
||||
//Draw text, the text is transformed from orignal for hotkey character
|
||||
nana::char_t hotkey;
|
||||
nana::string::size_type hotkey_pos;
|
||||
nana::string text = API::transform_shortkey_text(m.text, hotkey, &hotkey_pos);
|
||||
|
||||
if (m.image.empty() == false)
|
||||
renderer->item_image(graph, nana::point(item_r.x + 5, item_r.y + static_cast<int>(item_h_px - image_px) / 2 - 1), image_px, m.image);
|
||||
|
||||
renderer->item_text(graph, nana::point(item_r.x + 40, item_r.y + text_top_off), text, strpixels, attr);
|
||||
|
||||
if (hotkey)
|
||||
{
|
||||
m.hotkey = hotkey;
|
||||
if (m.flags.enabled)
|
||||
{
|
||||
unsigned off_w = (hotkey_pos ? graph.text_extent_size(text, static_cast<unsigned>(hotkey_pos)).width : 0);
|
||||
nana::size hotkey_size = graph.text_extent_size(text.c_str() + hotkey_pos, 1);
|
||||
int x = item_r.x + 40 + off_w;
|
||||
int y = item_r.y + text_top_off + hotkey_size.height;
|
||||
|
||||
graph_->set_color(colors::black);
|
||||
graph_->line({ x, y }, { x + static_cast<int>(hotkey_size.width) - 1, y });
|
||||
}
|
||||
}
|
||||
|
||||
if (m.sub_menu)
|
||||
renderer->sub_arrow(graph, nana::point(graph_->width() - 20, item_r.y), item_h_px, attr);
|
||||
|
||||
item_r.y += item_r.height + 1;
|
||||
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t active() const
|
||||
@@ -411,21 +472,21 @@ namespace nana
|
||||
state_.active = pos;
|
||||
state_.sub_window = false;
|
||||
|
||||
draw();
|
||||
refresh(*graph_);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool track_mouse(int x, int y)
|
||||
bool track_mouse(const ::nana::point& pos)
|
||||
{
|
||||
if(state_.nullify_mouse == false)
|
||||
if (!state_.nullify_mouse)
|
||||
{
|
||||
std::size_t index = _m_get_index_by_pos(x, y);
|
||||
if(index != state_.active)
|
||||
std::size_t index = _m_get_index_by_pos(pos.x, pos.y);
|
||||
if (index != state_.active)
|
||||
{
|
||||
if((index == npos) && menu_->items.at(state_.active).sub_menu && state_.sub_window)
|
||||
if ((index == npos) && menu_->items.at(state_.active).sub_menu && state_.sub_window)
|
||||
return false;
|
||||
|
||||
state_.active = (index != npos && menu_->items.at(index).flags.splitter) ? npos : index;
|
||||
@@ -433,6 +494,7 @@ namespace nana
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -451,29 +513,35 @@ namespace nana
|
||||
state_.sub_window = subw;
|
||||
}
|
||||
|
||||
menu_type* retrive_sub_menu(nana::point& pos, std::size_t interval) const
|
||||
menu_type* get_sub(nana::point& pos, unsigned long& tmstamp) const
|
||||
{
|
||||
if(state_.active != npos && (nana::system::timestamp() - state_.active_timestamp >= interval))
|
||||
if (npos == state_.active)
|
||||
return nullptr;
|
||||
|
||||
auto sub = menu_->items.at(state_.active).sub_menu;
|
||||
if (sub)
|
||||
{
|
||||
pos.x = graph_->width() - 2;
|
||||
pos.x = static_cast<int>(graph_->width()) - 2;
|
||||
pos.y = 2;
|
||||
|
||||
std::size_t index = 0;
|
||||
for(auto & m : menu_->items)
|
||||
auto index = state_.active;
|
||||
for (auto & m : menu_->items)
|
||||
{
|
||||
if(false == m.flags.splitter)
|
||||
if (m.flags.splitter)
|
||||
{
|
||||
if(index == state_.active)
|
||||
break;
|
||||
|
||||
pos.y += _m_item_height() + 1;
|
||||
}
|
||||
else
|
||||
pos.y += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
++index;
|
||||
if (0 == index)
|
||||
break;
|
||||
|
||||
pos.y += _m_item_height() + 1;
|
||||
--index;
|
||||
}
|
||||
return (menu_->items.at(state_.active).sub_menu);
|
||||
|
||||
tmstamp = state_.active_timestamp;
|
||||
return sub;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -498,8 +566,7 @@ namespace nana
|
||||
state_.active = index;
|
||||
state_.active_timestamp = nana::system::timestamp();
|
||||
|
||||
draw();
|
||||
API::update_window(*widget_);
|
||||
API::refresh_window(*widget_);
|
||||
return 2;
|
||||
}
|
||||
else if(m.flags.enabled)
|
||||
@@ -514,71 +581,6 @@ namespace nana
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void draw() const
|
||||
{
|
||||
if(nullptr == menu_) return;
|
||||
|
||||
_m_adjust_window_size();
|
||||
|
||||
renderer->background(*graph_, *widget_);
|
||||
|
||||
const unsigned item_h_px = _m_item_height();
|
||||
nana::rectangle item_r(2, 2, graph_->width() - 4, item_h_px);
|
||||
|
||||
unsigned strpixels = item_r.width - 60;
|
||||
|
||||
int text_top_off = (item_h_px - graph_->text_extent_size(STR("jh({[")).height) / 2;
|
||||
|
||||
std::size_t pos = 0;
|
||||
for(auto & m : menu_->items)
|
||||
{
|
||||
if(m.flags.splitter)
|
||||
{
|
||||
graph_->set_color(colors::gray_border);
|
||||
graph_->line({ item_r.x + 40, item_r.y }, { static_cast<int>(graph_->width()) - 1, item_r.y });
|
||||
item_r.y += 2;
|
||||
++pos;
|
||||
continue;
|
||||
}
|
||||
|
||||
renderer_interface::attr attr = _m_make_renderer_attr(pos == state_.active, m);
|
||||
//Draw item background
|
||||
renderer->item(*graph_, item_r, attr);
|
||||
|
||||
//Draw text, the text is transformed from orignal for hotkey character
|
||||
nana::char_t hotkey;
|
||||
nana::string::size_type hotkey_pos;
|
||||
nana::string text = API::transform_shortkey_text(m.text, hotkey, &hotkey_pos);
|
||||
|
||||
if(m.image.empty() == false)
|
||||
renderer->item_image(*graph_, nana::point(item_r.x + 5, item_r.y + (item_h_px - m.image.size().height) / 2), m.image);
|
||||
|
||||
renderer->item_text(*graph_, nana::point(item_r.x + 40, item_r.y + text_top_off), text, strpixels, attr);
|
||||
|
||||
if(hotkey)
|
||||
{
|
||||
m.hotkey = hotkey;
|
||||
if(m.flags.enabled)
|
||||
{
|
||||
unsigned off_w = (hotkey_pos ? graph_->text_extent_size(text, static_cast<unsigned>(hotkey_pos)).width : 0);
|
||||
nana::size hotkey_size = graph_->text_extent_size(text.c_str() + hotkey_pos, 1);
|
||||
int x = item_r.x + 40 + off_w;
|
||||
int y = item_r.y + text_top_off + hotkey_size.height;
|
||||
|
||||
graph_->set_color(colors::black);
|
||||
graph_->line({ x, y }, { x + static_cast<int>(hotkey_size.width) - 1, y });
|
||||
}
|
||||
}
|
||||
|
||||
if(m.sub_menu)
|
||||
renderer->sub_arrow(*graph_, nana::point(graph_->width() - 20, item_r.y), item_h_px, attr);
|
||||
|
||||
item_r.y += item_r.height + 1;
|
||||
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
private:
|
||||
static renderer_interface::attr _m_make_renderer_attr(bool active, const menu_item_type & m)
|
||||
{
|
||||
@@ -683,10 +685,10 @@ namespace nana
|
||||
|
||||
struct state
|
||||
{
|
||||
std::size_t active;
|
||||
unsigned long active_timestamp;
|
||||
unsigned long sub_window: 1;
|
||||
unsigned long nullify_mouse: 1;
|
||||
std::size_t active;
|
||||
unsigned active_timestamp;
|
||||
bool sub_window: 1;
|
||||
bool nullify_mouse: 1;
|
||||
}state_;
|
||||
|
||||
struct widget_detail
|
||||
@@ -699,15 +701,18 @@ namespace nana
|
||||
class menu_window
|
||||
: public widget_object<category::root_tag, menu_drawer>
|
||||
{
|
||||
typedef menu_drawer drawer_type;
|
||||
typedef widget_object<category::root_tag, menu_drawer> base_type;
|
||||
using drawer_type = menu_drawer;
|
||||
using base_type = widget_object<category::root_tag, menu_drawer>;
|
||||
public:
|
||||
typedef menu_builder::item_type item_type;
|
||||
using item_type = menu_builder::item_type;
|
||||
|
||||
menu_window(window wd, const point& pos, renderer_interface * rdptr)
|
||||
|
||||
menu_window(window wd, bool is_wd_parent_menu, const point& pos, renderer_interface * rdptr)
|
||||
//add a is_wd_parent_menu to determine whether the menu wants the focus.
|
||||
//if a submenu gets the focus, the program may cause a crash error when the submenu is being destroyed
|
||||
: base_type(wd, false, rectangle(pos, nana::size(2, 2)), appear::bald<appear::floating>()),
|
||||
want_focus_(nullptr == wd || (API::focus_window() != wd)),
|
||||
event_focus_(nullptr)
|
||||
want_focus_{ (!wd) || ((!is_wd_parent_menu) && (API::focus_window() != wd)) },
|
||||
event_focus_{ nullptr }
|
||||
{
|
||||
caption(STR("nana menu window"));
|
||||
get_drawer_trigger().close_menu_tree([this]{ this->_m_close_all(); });
|
||||
@@ -718,7 +723,19 @@ namespace nana
|
||||
submenu_.child = submenu_.parent = nullptr;
|
||||
submenu_.object = nullptr;
|
||||
|
||||
_m_make_mouse_event();
|
||||
state_.mouse_pos = API::cursor_position();
|
||||
events().mouse_move.connect_unignorable([this]{
|
||||
nana::point pos = API::cursor_position();
|
||||
if (pos != state_.mouse_pos)
|
||||
{
|
||||
menu_window * root = this;
|
||||
while (root->submenu_.parent)
|
||||
root = root->submenu_.parent;
|
||||
root->state_.auto_popup_submenu = true;
|
||||
|
||||
state_.mouse_pos = pos;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void popup(menu_type& menu, bool owner_menubar)
|
||||
@@ -745,13 +762,19 @@ namespace nana
|
||||
_m_key_down(arg);
|
||||
});
|
||||
|
||||
events().mouse_up.connect_unignorable([this]{
|
||||
pick();
|
||||
events().mouse_down.connect_unignorable([this](const arg_mouse& arg)
|
||||
{
|
||||
this->_m_open_sub(0); //Try to open submenu immediately
|
||||
});
|
||||
|
||||
events().mouse_up.connect_unignorable([this](const arg_mouse& arg){
|
||||
if (arg.left_button)
|
||||
pick();
|
||||
});
|
||||
|
||||
timer_.interval(100);
|
||||
timer_.elapse([this]{
|
||||
this->_m_check_repeatly();
|
||||
this->_m_open_sub(500); //Try to open submenu
|
||||
});
|
||||
timer_.start();
|
||||
|
||||
@@ -797,29 +820,27 @@ namespace nana
|
||||
|
||||
bool submenu(bool enter)
|
||||
{
|
||||
menu_window * object = this;
|
||||
while (object->submenu_.child)
|
||||
object = object->submenu_.child;
|
||||
menu_window * menu_wd = this;
|
||||
while (menu_wd->submenu_.child)
|
||||
menu_wd = menu_wd->submenu_.child;
|
||||
|
||||
state_.auto_popup_submenu = false;
|
||||
|
||||
if (enter)
|
||||
if (!enter)
|
||||
{
|
||||
if (object->submenu_.parent)
|
||||
if (menu_wd->submenu_.parent)
|
||||
{
|
||||
auto & sub = object->submenu_.parent->submenu_;
|
||||
auto & sub = menu_wd->submenu_.parent->submenu_;
|
||||
sub.child = nullptr;
|
||||
sub.object = nullptr;
|
||||
|
||||
object->close();
|
||||
menu_wd->close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
nana::point pos;
|
||||
menu_type * sbm = object->get_drawer_trigger().retrive_sub_menu(pos, 0);
|
||||
return object->_m_show_submenu(sbm, pos, true);
|
||||
return menu_wd->_m_manipulate_sub(0, true);
|
||||
}
|
||||
|
||||
int send_shortkey(nana::char_t key)
|
||||
@@ -965,63 +986,51 @@ namespace nana
|
||||
}
|
||||
}
|
||||
|
||||
void _m_make_mouse_event()
|
||||
bool _m_manipulate_sub(unsigned long delay_ms, bool forced)
|
||||
{
|
||||
state_.mouse_pos = API::cursor_position();
|
||||
events().mouse_move.connect_unignorable([this]{
|
||||
_m_mouse_event();
|
||||
});
|
||||
}
|
||||
auto & drawer = get_drawer_trigger();
|
||||
::nana::point pos;
|
||||
unsigned long tmstamp;
|
||||
|
||||
void _m_mouse_event()
|
||||
{
|
||||
nana::point pos = API::cursor_position();
|
||||
if(pos != state_.mouse_pos)
|
||||
auto menu_ptr = drawer.get_sub(pos, tmstamp);
|
||||
|
||||
if (menu_ptr == submenu_.object)
|
||||
return false;
|
||||
|
||||
if (menu_ptr && (::nana::system::timestamp() - tmstamp < delay_ms))
|
||||
return false;
|
||||
|
||||
if (submenu_.object && (menu_ptr != submenu_.object))
|
||||
{
|
||||
menu_window * root = this;
|
||||
while(root->submenu_.parent)
|
||||
root = root->submenu_.parent;
|
||||
root->state_.auto_popup_submenu = true;
|
||||
|
||||
state_.mouse_pos = pos;
|
||||
}
|
||||
}
|
||||
|
||||
bool _m_show_submenu(menu_type* sbm, nana::point pos, bool forced)
|
||||
{
|
||||
auto & mdtrigger = get_drawer_trigger();
|
||||
if(submenu_.object && (sbm != submenu_.object))
|
||||
{
|
||||
mdtrigger.set_sub_window(false);
|
||||
drawer.set_sub_window(false);
|
||||
submenu_.child->close();
|
||||
submenu_.child = nullptr;
|
||||
submenu_.object = nullptr;
|
||||
}
|
||||
|
||||
if(sbm)
|
||||
if (menu_ptr)
|
||||
{
|
||||
menu_window * root = this;
|
||||
while(root->submenu_.parent)
|
||||
while (root->submenu_.parent)
|
||||
root = root->submenu_.parent;
|
||||
|
||||
if((submenu_.object == nullptr) && sbm && (forced || root->state_.auto_popup_submenu))
|
||||
if ((submenu_.object == nullptr) && menu_ptr && (forced || root->state_.auto_popup_submenu))
|
||||
{
|
||||
sbm->item_pixels = mdtrigger.data()->item_pixels;
|
||||
sbm->gaps = mdtrigger.data()->gaps;
|
||||
pos.x += sbm->gaps.x;
|
||||
pos.y += sbm->gaps.y;
|
||||
menu_ptr->item_pixels = drawer.data()->item_pixels;
|
||||
menu_ptr->gaps = drawer.data()->gaps;
|
||||
pos += menu_ptr->gaps;
|
||||
|
||||
menu_window & mwnd = form_loader<menu_window, false>()(handle(), pos, mdtrigger.renderer);
|
||||
menu_window & mwnd = form_loader<menu_window, false>()(handle(), true, pos, drawer.renderer);
|
||||
mwnd.state_.self_submenu = true;
|
||||
submenu_.child = & mwnd;
|
||||
submenu_.child = &mwnd;
|
||||
submenu_.child->submenu_.parent = this;
|
||||
submenu_.object = sbm;
|
||||
submenu_.object = menu_ptr;
|
||||
|
||||
API::set_window_z_order(handle(), mwnd.handle(), z_order_action::none);
|
||||
|
||||
mwnd.popup(*sbm, state_.owner_menubar);
|
||||
mdtrigger.set_sub_window(true);
|
||||
if(forced)
|
||||
mwnd.popup(*menu_ptr, state_.owner_menubar);
|
||||
drawer.set_sub_window(true);
|
||||
if (forced)
|
||||
mwnd.goto_next(true);
|
||||
|
||||
return true;
|
||||
@@ -1030,17 +1039,16 @@ namespace nana
|
||||
return false;
|
||||
}
|
||||
|
||||
void _m_check_repeatly()
|
||||
void _m_open_sub(unsigned delay_ms) //check_repeatly
|
||||
{
|
||||
if(state_.auto_popup_submenu)
|
||||
{
|
||||
nana::point pos = API::cursor_position();
|
||||
auto pos = API::cursor_position();
|
||||
|
||||
drawer_type& drawer = get_drawer_trigger();
|
||||
API::calc_window_point(handle(), pos);
|
||||
drawer.track_mouse(pos.x, pos.y);
|
||||
menu_type* sbm = drawer.retrive_sub_menu(pos, 500);
|
||||
_m_show_submenu(sbm, pos, false);
|
||||
get_drawer_trigger().track_mouse(pos);
|
||||
|
||||
_m_manipulate_sub(delay_ms, false);
|
||||
}
|
||||
}
|
||||
private:
|
||||
@@ -1293,7 +1301,7 @@ namespace nana
|
||||
{
|
||||
close();
|
||||
|
||||
impl_->uiobj = &(form_loader<drawerbase::menu::menu_window, false>()(wd, point(x, y), &(*impl_->mbuilder.renderer())));
|
||||
impl_->uiobj = &(form_loader<drawerbase::menu::menu_window, false>()(wd, false, point(x, y), &(*impl_->mbuilder.renderer())));
|
||||
impl_->uiobj->events().destroy.connect_unignorable([this]{
|
||||
impl_->uiobj = nullptr;
|
||||
if (impl_->destroy_answer)
|
||||
|
||||
@@ -89,6 +89,15 @@ namespace nana
|
||||
{
|
||||
return unknown_;
|
||||
}
|
||||
bool trigger::stoped() const
|
||||
{
|
||||
return stop_;
|
||||
}
|
||||
bool trigger::stop(bool s)
|
||||
{
|
||||
std::swap(s,stop_);
|
||||
return s;
|
||||
}
|
||||
|
||||
void trigger::refresh(graph_reference)
|
||||
{
|
||||
@@ -197,5 +206,13 @@ namespace nana
|
||||
{
|
||||
return get_drawer_trigger().unknown();
|
||||
}
|
||||
bool progress::stop(bool s)
|
||||
{
|
||||
return get_drawer_trigger().stop(s);
|
||||
}
|
||||
bool progress::stoped() const
|
||||
{
|
||||
return get_drawer_trigger().stoped();
|
||||
}
|
||||
//end class progress
|
||||
}//end namespace nana
|
||||
|
||||
@@ -1482,6 +1482,8 @@ namespace nana{ namespace widgets
|
||||
|
||||
behavior_->pre_calc_lines(width_pixels());
|
||||
_m_scrollbar();
|
||||
|
||||
move_caret(points_.caret);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
*/
|
||||
|
||||
#include <nana/gui/widgets/toolbar.hpp>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
#include <nana/gui/tooltip.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace nana
|
||||
{
|
||||
arg_toolbar::arg_toolbar(toolbar& tbar, std::size_t btn)
|
||||
@@ -25,13 +25,6 @@ namespace nana
|
||||
{
|
||||
namespace toolbar
|
||||
{
|
||||
struct listitem
|
||||
{
|
||||
nana::string text;
|
||||
nana::paint::image image;
|
||||
bool enable;
|
||||
};
|
||||
|
||||
struct item_type
|
||||
{
|
||||
enum kind{ button, container};
|
||||
@@ -43,28 +36,23 @@ namespace nana
|
||||
unsigned pixels{0};
|
||||
nana::size textsize;
|
||||
bool enable{true};
|
||||
window other{nullptr};
|
||||
|
||||
kind type;
|
||||
std::function<void(size_type, size_type)> answer;
|
||||
std::vector<listitem> children;
|
||||
|
||||
item_type(const nana::string& text, const nana::paint::image& img, kind type)
|
||||
:text(text), image(img), type(type)
|
||||
{}
|
||||
};
|
||||
|
||||
class container
|
||||
{
|
||||
container(const container&) = delete;
|
||||
container& operator=(const container&) = delete;
|
||||
public:
|
||||
typedef std::vector<item_type*>::size_type size_type;
|
||||
typedef std::vector<item_type*>::iterator iterator;
|
||||
typedef std::vector<item_type*>::const_iterator const_iterator;
|
||||
|
||||
container() = default;
|
||||
~container()
|
||||
|
||||
class item_container
|
||||
{
|
||||
public:
|
||||
using container_type = std::vector<item_type*>;
|
||||
using size_type = container_type::size_type;
|
||||
|
||||
~item_container()
|
||||
{
|
||||
for(auto ptr : cont_)
|
||||
delete ptr;
|
||||
@@ -98,7 +86,7 @@ namespace nana
|
||||
cont_.push_back(nullptr);
|
||||
}
|
||||
|
||||
void push_back()
|
||||
void separate()
|
||||
{
|
||||
cont_.push_back(nullptr);
|
||||
}
|
||||
@@ -108,35 +96,17 @@ namespace nana
|
||||
return cont_.size();
|
||||
}
|
||||
|
||||
item_type* at(size_type n)
|
||||
container_type& container()
|
||||
{
|
||||
if(n < cont_.size())
|
||||
return cont_[n];
|
||||
|
||||
throw std::out_of_range("toolbar: bad index!");
|
||||
return cont_;
|
||||
}
|
||||
|
||||
iterator begin()
|
||||
item_type * at(size_type pos)
|
||||
{
|
||||
return cont_.begin();
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
return cont_.end();
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
return cont_.cbegin();
|
||||
}
|
||||
|
||||
const_iterator end() const
|
||||
{
|
||||
return cont_.cend();
|
||||
return cont_.at(pos);
|
||||
}
|
||||
private:
|
||||
std::vector<item_type*> cont_;
|
||||
container_type cont_;
|
||||
};
|
||||
|
||||
class item_renderer
|
||||
@@ -152,38 +122,36 @@ namespace nana
|
||||
void operator()(int x, int y, unsigned width, unsigned height, item_type& item, state_t state)
|
||||
{
|
||||
//draw background
|
||||
if(state != state_t::normal)
|
||||
graph.rectangle({ x, y, width, height }, false, { 0x33, 0x99, 0xFF });
|
||||
switch(state)
|
||||
if (state != state_t::normal)
|
||||
{
|
||||
case state_t::highlighted:
|
||||
graph.gradual_rectangle({ x + 1, y + 1, width - 2, height - 2 }, bgcolor, { 0xC0, 0xDD, 0xFC }, true);
|
||||
break;
|
||||
case state_t::selected:
|
||||
graph.gradual_rectangle({ x + 1, y + 1, width - 2, height - 2 }, bgcolor, { 0x99, 0xCC, 0xFF }, true);
|
||||
default: break;
|
||||
nana::rectangle background_r(x, y, width, height);
|
||||
graph.rectangle(background_r, false, static_cast<color_rgb>(0x3399FF));
|
||||
|
||||
if (state_t::highlighted == state || state_t::selected == state)
|
||||
graph.gradual_rectangle(background_r.pare_off(1), bgcolor, static_cast<color_rgb>(state_t::selected == state ? 0x99CCFF : 0xC0DDFC), true);
|
||||
}
|
||||
|
||||
if(item.image.empty() == false)
|
||||
if(!item.image.empty())
|
||||
{
|
||||
nana::size size = item.image.size();
|
||||
if(size.width > scale) size.width = scale;
|
||||
if(size.height > scale) size.height = scale;
|
||||
auto imgsize = item.image.size();
|
||||
|
||||
if (imgsize.width > scale) imgsize.width = scale;
|
||||
if (imgsize.height > scale) imgsize.height = scale;
|
||||
|
||||
nana::point pos(x, y);
|
||||
pos.x += static_cast<int>(scale + extra_size - size.width) / 2;
|
||||
pos.y += static_cast<int>(height - size.height) / 2;
|
||||
pos.x += static_cast<int>(scale + extra_size - imgsize.width) / 2;
|
||||
pos.y += static_cast<int>(height - imgsize.height) / 2;
|
||||
|
||||
item.image.paste(::nana::rectangle{ size }, graph, pos);
|
||||
item.image.paste(::nana::rectangle{ imgsize }, graph, pos);
|
||||
if(item.enable == false)
|
||||
{
|
||||
nana::paint::graphics gh(size);
|
||||
gh.bitblt(::nana::rectangle{ size }, graph, pos);
|
||||
nana::paint::graphics gh(imgsize);
|
||||
gh.bitblt(::nana::rectangle{ imgsize }, graph, pos);
|
||||
gh.rgb_to_wb();
|
||||
gh.paste(graph, pos.x, pos.y);
|
||||
}
|
||||
else if(state == state_t::normal)
|
||||
graph.blend(nana::rectangle(pos, size), ::nana::color(0xc0, 0xdd, 0xfc).blend(bgcolor, 0.5), 0.25);
|
||||
graph.blend(nana::rectangle(pos, imgsize), ::nana::color(0xc0, 0xdd, 0xfc).blend(bgcolor, 0.5), 0.25);
|
||||
|
||||
x += scale;
|
||||
width -= scale;
|
||||
@@ -204,13 +172,15 @@ namespace nana
|
||||
|
||||
struct drawer::drawer_impl_type
|
||||
{
|
||||
event_handle event_size{nullptr};
|
||||
event_handle event_size{ nullptr };
|
||||
paint::graphics* graph_ptr{ nullptr };
|
||||
|
||||
unsigned scale{16};
|
||||
bool textout{false};
|
||||
size_type which{npos};
|
||||
item_renderer::state_t state{item_renderer::state_t::normal};
|
||||
|
||||
container cont;
|
||||
item_container items;
|
||||
::nana::tooltip tooltip;
|
||||
};
|
||||
|
||||
@@ -225,116 +195,118 @@ namespace nana
|
||||
delete impl_;
|
||||
}
|
||||
|
||||
void drawer::append(const nana::string& text, const nana::paint::image& img)
|
||||
item_container& drawer::items() const
|
||||
{
|
||||
impl_->cont.push_back(text, img);
|
||||
}
|
||||
|
||||
void drawer::append()
|
||||
{
|
||||
impl_->cont.push_back();
|
||||
}
|
||||
|
||||
bool drawer::enable(drawer::size_type n) const
|
||||
{
|
||||
if(impl_->cont.size() > n)
|
||||
{
|
||||
auto item = impl_->cont.at(n);
|
||||
return (item && item->enable);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool drawer::enable(size_type n, bool eb)
|
||||
{
|
||||
if(impl_->cont.size() > n)
|
||||
{
|
||||
item_type * item = impl_->cont.at(n);
|
||||
if(item && (item->enable != eb))
|
||||
{
|
||||
item->enable = eb;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return impl_->items;
|
||||
}
|
||||
|
||||
void drawer::scale(unsigned s)
|
||||
{
|
||||
impl_->scale = s;
|
||||
|
||||
for(auto m : impl_->cont)
|
||||
_m_fill_pixels(m, true);
|
||||
for(auto m : impl_->items.container())
|
||||
_m_calc_pixels(m, true);
|
||||
}
|
||||
|
||||
void drawer::refresh(graph_reference)
|
||||
void drawer::refresh(graph_reference graph)
|
||||
{
|
||||
_m_draw();
|
||||
int x = 2, y = 2;
|
||||
|
||||
auto bgcolor = API::bgcolor(widget_->handle());
|
||||
graph.set_text_color(bgcolor);
|
||||
graph.gradual_rectangle(rectangle{ graph.size() }, bgcolor.blend(colors::white, 0.9), bgcolor.blend(colors::black, 0.95), true);
|
||||
|
||||
item_renderer ir(graph, impl_->textout, impl_->scale, bgcolor);
|
||||
size_type index = 0;
|
||||
|
||||
for (auto item : impl_->items.container())
|
||||
{
|
||||
if (item)
|
||||
{
|
||||
_m_calc_pixels(item, false);
|
||||
ir(x, y, item->pixels, impl_->scale + ir.extra_size, *item, (index == impl_->which ? impl_->state : item_renderer::state_t::normal));
|
||||
x += item->pixels;
|
||||
}
|
||||
else
|
||||
{
|
||||
x += 2;
|
||||
graph.line({ x, y + 2 }, { x, y + static_cast<int>(impl_->scale + ir.extra_size) - 4 }, static_cast<color_rgb>(0x808080));
|
||||
x += 4;
|
||||
}
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
void drawer::attached(widget_reference widget, graph_reference graph)
|
||||
{
|
||||
graph_ = &graph;
|
||||
impl_->graph_ptr = &graph;
|
||||
|
||||
widget_ = static_cast< ::nana::toolbar*>(&widget);
|
||||
widget.caption(STR("Nana Toolbar"));
|
||||
impl_->event_size = widget.events().resized.connect_unignorable(std::bind(&drawer::_m_owner_sized, this, std::placeholders::_1));
|
||||
widget.caption(L"Nana Toolbar");
|
||||
|
||||
impl_->event_size = API::events(widget.parent()).resized.connect_unignorable([this](const arg_resized& arg)
|
||||
{
|
||||
auto wd = widget_->handle();
|
||||
API::window_size(wd, nana::size(arg.width, widget_->size().height));
|
||||
API::update_window(wd);
|
||||
});
|
||||
}
|
||||
|
||||
void drawer::detached()
|
||||
{
|
||||
API::umake_event(impl_->event_size);
|
||||
impl_->event_size = nullptr;
|
||||
impl_->graph_ptr = nullptr;
|
||||
}
|
||||
|
||||
void drawer::mouse_move(graph_reference graph, const arg_mouse& arg)
|
||||
{
|
||||
if(arg.left_button == false)
|
||||
if (arg.left_button)
|
||||
return;
|
||||
|
||||
size_type which = _m_which(arg.pos, true);
|
||||
if(impl_->which != which)
|
||||
{
|
||||
size_type which = _m_which(arg.pos.x, arg.pos.y, true);
|
||||
if(impl_->which != which)
|
||||
auto & container = impl_->items.container();
|
||||
if (impl_->which != npos && container.at(impl_->which)->enable)
|
||||
{
|
||||
if (impl_->which != npos && impl_->cont.at(impl_->which)->enable)
|
||||
{
|
||||
::nana::arg_toolbar arg{ *widget_, impl_->which };
|
||||
widget_->events().leave.emit(arg);
|
||||
}
|
||||
|
||||
impl_->which = which;
|
||||
if(which == npos || impl_->cont.at(which)->enable)
|
||||
{
|
||||
impl_->state = (arg.left_button ? item_renderer::state_t::selected : item_renderer::state_t::highlighted);
|
||||
|
||||
_m_draw();
|
||||
API::lazy_refresh();
|
||||
|
||||
if (impl_->state == item_renderer::state_t::highlighted)
|
||||
{
|
||||
::nana::arg_toolbar arg{ *widget_, which };
|
||||
widget_->events().enter.emit(arg);
|
||||
}
|
||||
}
|
||||
|
||||
if(which != npos)
|
||||
impl_->tooltip.show(widget_->handle(), nana::point(arg.pos.x, arg.pos.y + 20), (*(impl_->cont.begin() + which))->text, 0);
|
||||
else
|
||||
impl_->tooltip.close();
|
||||
::nana::arg_toolbar arg{ *widget_, impl_->which };
|
||||
widget_->events().leave.emit(arg);
|
||||
}
|
||||
|
||||
impl_->which = which;
|
||||
if (which == npos || container.at(which)->enable)
|
||||
{
|
||||
impl_->state = (arg.left_button ? item_renderer::state_t::selected : item_renderer::state_t::highlighted);
|
||||
|
||||
refresh(graph);
|
||||
API::lazy_refresh();
|
||||
|
||||
if (impl_->state == item_renderer::state_t::highlighted)
|
||||
{
|
||||
::nana::arg_toolbar arg{ *widget_, which };
|
||||
widget_->events().enter.emit(arg);
|
||||
}
|
||||
}
|
||||
|
||||
if(which != npos)
|
||||
impl_->tooltip.show(widget_->handle(), nana::point(arg.pos.x, arg.pos.y + 20), (*(container.begin() + which))->text, 0);
|
||||
else
|
||||
impl_->tooltip.close();
|
||||
}
|
||||
}
|
||||
|
||||
void drawer::mouse_leave(graph_reference, const arg_mouse&)
|
||||
void drawer::mouse_leave(graph_reference graph, const arg_mouse&)
|
||||
{
|
||||
if(impl_->which != npos)
|
||||
{
|
||||
size_type which = impl_->which;
|
||||
|
||||
impl_->which = npos;
|
||||
_m_draw();
|
||||
refresh(graph);
|
||||
API::lazy_refresh();
|
||||
|
||||
if (which != npos && impl_->cont.at(which)->enable)
|
||||
if (which != npos && impl_->items.at(which)->enable)
|
||||
{
|
||||
::nana::arg_toolbar arg{ *widget_, which };
|
||||
widget_->events().leave.emit(arg);
|
||||
@@ -343,22 +315,22 @@ namespace nana
|
||||
impl_->tooltip.close();
|
||||
}
|
||||
|
||||
void drawer::mouse_down(graph_reference, const arg_mouse&)
|
||||
void drawer::mouse_down(graph_reference graph, const arg_mouse&)
|
||||
{
|
||||
impl_->tooltip.close();
|
||||
if(impl_->which != npos && (impl_->cont.at(impl_->which)->enable))
|
||||
if(impl_->which != npos && (impl_->items.at(impl_->which)->enable))
|
||||
{
|
||||
impl_->state = item_renderer::state_t::selected;
|
||||
_m_draw();
|
||||
refresh(graph);
|
||||
API::lazy_refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void drawer::mouse_up(graph_reference, const arg_mouse& arg)
|
||||
void drawer::mouse_up(graph_reference graph, const arg_mouse& arg)
|
||||
{
|
||||
if(impl_->which != npos)
|
||||
{
|
||||
size_type which = _m_which(arg.pos.x, arg.pos.y, false);
|
||||
size_type which = _m_which(arg.pos, false);
|
||||
if(impl_->which == which)
|
||||
{
|
||||
::nana::arg_toolbar arg{ *widget_, which };
|
||||
@@ -372,89 +344,47 @@ namespace nana
|
||||
impl_->state = (which == npos ? item_renderer::state_t::normal : item_renderer::state_t::highlighted);
|
||||
}
|
||||
|
||||
_m_draw();
|
||||
refresh(graph);
|
||||
API::lazy_refresh();
|
||||
}
|
||||
}
|
||||
|
||||
drawer::size_type drawer::_m_which(int x, int y, bool want_if_disabled) const
|
||||
drawer::size_type drawer::_m_which(point pos, bool want_if_disabled) const
|
||||
{
|
||||
if(x < 2 || y < 2 || y >= static_cast<int>(impl_->scale + item_renderer::extra_size + 2)) return npos;
|
||||
if (pos.x < 2 || pos.y < 2 || pos.y >= static_cast<int>(impl_->scale + item_renderer::extra_size + 2)) return npos;
|
||||
|
||||
x -= 2;
|
||||
pos.x -= 2;
|
||||
|
||||
size_type pos = 0;
|
||||
for(auto m: impl_->cont)
|
||||
std::size_t index = 0;
|
||||
for(auto m: impl_->items.container())
|
||||
{
|
||||
bool compart = (nullptr == m);
|
||||
auto px = static_cast<const int>(m ? m->pixels : 3);
|
||||
|
||||
if(x < static_cast<int>(compart ? 3 : m->pixels))
|
||||
return ((compart || (m->enable == false && want_if_disabled == false)) ? npos : pos);
|
||||
if(pos.x < px)
|
||||
return (((!m) || (!m->enable && !want_if_disabled)) ? npos : index);
|
||||
|
||||
x -= (compart ? 3 : m->pixels);
|
||||
pos.x -= px;
|
||||
|
||||
++pos;
|
||||
++index;
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
|
||||
void drawer::_m_draw_background(const ::nana::color& clr)
|
||||
void drawer::_m_calc_pixels(item_type* item, bool force)
|
||||
{
|
||||
graph_->gradual_rectangle(::nana::rectangle{ graph_->size() }, clr.blend(colors::white, 0.9), clr.blend(colors::black, 0.95), true);
|
||||
}
|
||||
|
||||
void drawer::_m_draw()
|
||||
{
|
||||
int x = 2, y = 2;
|
||||
|
||||
auto bgcolor = API::bgcolor(widget_->handle());
|
||||
graph_->set_text_color(bgcolor);
|
||||
_m_draw_background(bgcolor);
|
||||
|
||||
item_renderer ir(*graph_, impl_->textout, impl_->scale, bgcolor);
|
||||
size_type index = 0;
|
||||
|
||||
for(auto item : impl_->cont)
|
||||
if (item && (force || (0 == item->pixels)))
|
||||
{
|
||||
if(item)
|
||||
{
|
||||
_m_fill_pixels(item, false);
|
||||
ir(x, y, item->pixels, impl_->scale + ir.extra_size, *item, (index == impl_->which ? impl_->state : item_renderer::state_t::normal));
|
||||
x += item->pixels;
|
||||
}
|
||||
else
|
||||
{
|
||||
graph_->line({ x + 2, y + 2 }, { x + 2, y + static_cast<int>(impl_->scale + ir.extra_size) - 4 }, { 0x80, 0x80, 0x80 });
|
||||
x += 6;
|
||||
}
|
||||
++index;
|
||||
}
|
||||
}
|
||||
if (item->text.size())
|
||||
item->textsize = impl_->graph_ptr->text_extent_size(item->text);
|
||||
|
||||
void drawer::_m_owner_sized(const arg_resized& arg)
|
||||
{
|
||||
auto wd = widget_->handle();
|
||||
API::window_size(wd, nana::size(arg.width, widget_->size().height));
|
||||
_m_draw();
|
||||
API::update_window(wd);
|
||||
}
|
||||
|
||||
void drawer::_m_fill_pixels(item_type* item, bool force)
|
||||
{
|
||||
if(item && (force || (0 == item->pixels)))
|
||||
{
|
||||
if(item->text.size())
|
||||
item->textsize = graph_->text_extent_size(item->text);
|
||||
|
||||
if(item->image.empty() == false)
|
||||
if (item->image.empty() == false)
|
||||
item->pixels = impl_->scale + item_renderer::extra_size;
|
||||
|
||||
if(item->textsize.width && impl_->textout)
|
||||
if (item->textsize.width && impl_->textout)
|
||||
item->pixels += item->textsize.width + 8;
|
||||
}
|
||||
}
|
||||
//};//class drawer
|
||||
|
||||
//class drawer
|
||||
}//end namespace toolbar
|
||||
}//end namespace drawerbase
|
||||
|
||||
@@ -469,33 +399,48 @@ namespace nana
|
||||
create(wd, r, visible);
|
||||
}
|
||||
|
||||
void toolbar::append()
|
||||
void toolbar::separate()
|
||||
{
|
||||
get_drawer_trigger().append();
|
||||
get_drawer_trigger().items().separate();
|
||||
API::refresh_window(handle());
|
||||
}
|
||||
|
||||
void toolbar::append(const nana::string& text, const nana::paint::image& img)
|
||||
{
|
||||
get_drawer_trigger().append(text, img);
|
||||
get_drawer_trigger().items().push_back(text, img);
|
||||
API::refresh_window(handle());
|
||||
}
|
||||
|
||||
void toolbar::append(const nana::string& text)
|
||||
{
|
||||
get_drawer_trigger().append(text, nana::paint::image());
|
||||
get_drawer_trigger().items().push_back(text, {});
|
||||
API::refresh_window(this->handle());
|
||||
}
|
||||
|
||||
bool toolbar::enable(size_type n) const
|
||||
bool toolbar::enable(size_type pos) const
|
||||
{
|
||||
return get_drawer_trigger().enable(n);
|
||||
auto & items = get_drawer_trigger().items();
|
||||
|
||||
if (items.size() <= pos)
|
||||
return false;
|
||||
|
||||
auto m = items.at(pos);
|
||||
return (m && m->enable);
|
||||
}
|
||||
|
||||
void toolbar::enable(size_type n, bool eb)
|
||||
void toolbar::enable(size_type pos, bool eb)
|
||||
{
|
||||
if(get_drawer_trigger().enable(n, eb))
|
||||
API::refresh_window(this->handle());
|
||||
auto & items = get_drawer_trigger().items();
|
||||
|
||||
if (items.size() > pos)
|
||||
{
|
||||
auto m = items.at(pos);
|
||||
if (m && (m->enable != eb))
|
||||
{
|
||||
m->enable = eb;
|
||||
API::refresh_window(this->handle());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void toolbar::scale(unsigned s)
|
||||
@@ -503,5 +448,5 @@ namespace nana
|
||||
get_drawer_trigger().scale(s);
|
||||
API::refresh_window(handle());
|
||||
}
|
||||
//}; class toolbar
|
||||
//end class toolbar
|
||||
}//end namespace nana
|
||||
|
||||
Reference in New Issue
Block a user