add scroll_operation_interface

This commit is contained in:
Jinhao
2018-04-21 03:49:15 +08:00
parent 2cf374705f
commit 0c7e8a8ca2
13 changed files with 258 additions and 203 deletions

View File

@@ -297,6 +297,19 @@ that return a corresponding nana::appearance with predefined values.
virtual bool visible() const = 0; virtual bool visible() const = 0;
};//end class caret_interface };//end class caret_interface
/// Interface for scroll operations
/**
* This interface provides methods to operate the scrollbars that are contained
* in a specific widget, such as listbox and treebox
*/
class scroll_operation_interface
{
public:
virtual ~scroll_operation_interface() = default;
virtual bool visible(bool vert) const = 0;
};
namespace parameters namespace parameters
{ {
/// The system-wide parameters for mouse wheel /// The system-wide parameters for mouse wheel

View File

@@ -1541,6 +1541,7 @@ the nana::detail::basic_window member pointer scheme
nana::any* _m_anyobj(size_type cat, size_type index, bool allocate_if_empty) const override; nana::any* _m_anyobj(size_type cat, size_type index, bool allocate_if_empty) const override;
drawerbase::listbox::category_t* _m_assoc(std::shared_ptr<nana::detail::key_interface>, bool create_if_not_exists); drawerbase::listbox::category_t* _m_assoc(std::shared_ptr<nana::detail::key_interface>, bool create_if_not_exists);
void _m_erase_key(nana::detail::key_interface*) noexcept; void _m_erase_key(nana::detail::key_interface*) noexcept;
std::shared_ptr<scroll_operation_interface> _m_scroll_operation();
}; };
}//end namespace nana }//end namespace nana

View File

@@ -1,7 +1,7 @@
/* /*
* A text editor implementation * A text editor implementation
* Nana C++ Library(http://www.nanapro.org) * Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
* *
* Distributed under the Boost Software License, Version 1.0. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@@ -219,6 +219,8 @@ namespace nana{ namespace widgets
const skeletons::textbase<char_type>& textbase() const; const skeletons::textbase<char_type>& textbase() const;
bool try_refresh(); bool try_refresh();
std::shared_ptr<scroll_operation_interface> scroll_operation() const;
private: private:
nana::color _m_draw_colored_area(paint::graphics& graph, const std::pair<std::size_t,std::size_t>& row, bool whole_line); nana::color _m_draw_colored_area(paint::graphics& graph, const std::pair<std::size_t,std::size_t>& row, bool whole_line);
std::vector<upoint> _m_render_text(const ::nana::color& text_color); std::vector<upoint> _m_render_text(const ::nana::color& text_color);

View File

@@ -1,7 +1,7 @@
/** /**
* A Textbox Implementation * A Textbox Implementation
* Nana C++ Library(http://www.nanapro.org) * Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
* *
* Distributed under the Boost Software License, Version 1.0. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@@ -279,6 +279,7 @@ namespace nana
native_string_type _m_caption() const throw() override; native_string_type _m_caption() const throw() override;
void _m_caption(native_string_type&&) override; void _m_caption(native_string_type&&) override;
void _m_typeface(const paint::font&) override; void _m_typeface(const paint::font&) override;
std::shared_ptr<scroll_operation_interface> _m_scroll_operation() const;
}; };
}//end namespace nana }//end namespace nana
#include <nana/pop_ignore_diagnostic> #include <nana/pop_ignore_diagnostic>

View File

@@ -1,7 +1,7 @@
/** /**
* A Tree Box Implementation * A Tree Box Implementation
* Nana C++ Library(http://www.nanapro.org) * Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
* *
* Distributed under the Boost Software License, Version 1.0. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE or copy at * (See accompanying file LICENSE or copy at
@@ -445,6 +445,9 @@ namespace nana
item_proxy selected() const; ///< returns the selected node item_proxy selected() const; ///< returns the selected node
private:
std::shared_ptr<scroll_operation_interface> _m_scroll_operation() const;
};//end class treebox };//end class treebox
}//end namespace nana }//end namespace nana

View File

@@ -1,7 +1,7 @@
/** /**
* The fundamental widget class implementation * The fundamental widget class implementation
* Nana C++ Library(http://www.nanapro.org) * Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
* *
* Distributed under the Boost Software License, Version 1.0. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@@ -83,6 +83,8 @@ namespace nana
void focus(); void focus();
bool focused() const; bool focused() const;
std::shared_ptr<scroll_operation_interface> scroll_operation();
void show(); ///< Sets the window visible. void show(); ///< Sets the window visible.
void hide(); ///< Sets the window invisible. void hide(); ///< Sets the window invisible.
bool visible() const; bool visible() const;
@@ -137,6 +139,7 @@ namespace nana
virtual void _m_close(); virtual void _m_close();
virtual bool _m_enabled() const; virtual bool _m_enabled() const;
virtual void _m_enabled(bool); virtual void _m_enabled(bool);
virtual std::shared_ptr<scroll_operation_interface> _m_scroll_operation();
virtual bool _m_show(bool); virtual bool _m_show(bool);
virtual bool _m_visible() const; virtual bool _m_visible() const;
virtual void _m_size(const nana::size&); virtual void _m_size(const nana::size&);

View File

@@ -797,8 +797,8 @@ namespace nana
void emit_cs(const index_pair& pos, bool for_selection) void emit_cs(const index_pair& pos, bool for_selection)
{ {
item_proxy i(ess_, pos); item_proxy item(ess_, pos);
arg_listbox arg{ i }; arg_listbox arg{ item };
auto & events = wd_ptr()->events(); auto & events = wd_ptr()->events();
@@ -813,9 +813,9 @@ namespace nana
if (p && (p->item_pos == pos)) if (p && (p->item_pos == pos))
{ {
if (for_selection) if (for_selection)
p->inline_ptr->notify_status(inline_widget_status::selecting, i.selected()); p->inline_ptr->notify_status(inline_widget_status::selecting, item.selected());
else else
p->inline_ptr->notify_status(inline_widget_status::checking, i.checked()); p->inline_ptr->notify_status(inline_widget_status::checking, item.checked());
} }
} }
} }
@@ -954,7 +954,7 @@ namespace nana
*/ */
bool sort_column(std::size_t pos, const bool * reverse) bool sort_column(std::size_t pos, const bool * reverse)
{ {
if (npos == pos) if (nana::npos == pos)
{ {
sort_attrs_.column = npos; sort_attrs_.column = npos;
return false; return false;
@@ -992,22 +992,12 @@ namespace nana
return prstatus; return prstatus;
} }
#if 0
void scroll(const index_pair& abs_pos, bool to_bottom); //deprecated
#endif
/// Scroll the selected item into the view /// Scroll the selected item into the view
void scroll_into_view(const index_pair& abs_pos, view_action vw_act); void scroll_into_view(const index_pair& abs_pos, view_action vw_act);
/// Append a new category with a specified name and return a pointer to it.
category_t* create_cat(native_string_type&& text)
{
categories_.emplace_back(std::move(text));
return &categories_.back();
}
/// will use the key to insert new cat before the first cat with compare less than the key, or at the end of the list of cat and return a ref to that new cat. ? /// will use the key to insert new cat before the first cat with compare less than the key, or at the end of the list of cat and return a ref to that new cat. ?
category_t* create_cat(std::shared_ptr<nana::detail::key_interface>& ptr) category_t* create_category(std::shared_ptr<nana::detail::key_interface>& ptr)
{ {
//A workaround for old version of libstdc++ //A workaround for old version of libstdc++
//Some operations of vector provided by libstdc++ don't accept const iterator. //Some operations of vector provided by libstdc++ don't accept const iterator.
@@ -1038,9 +1028,15 @@ namespace nana
return &(categories_.back()); return &(categories_.back());
} }
/// add a new cat created at "pos" and return a ref to it /// Inserts a new category at position specified by pos
category_t* create_cat(std::size_t pos, native_string_type&& text) category_t* create_category(native_string_type&& text, std::size_t pos = nana::npos)
{ {
if (::nana::npos == pos)
{
categories_.emplace_back(std::move(text));
return &categories_.back();
}
return &(*categories_.emplace(this->get(pos), std::move(text))); return &(*categories_.emplace(this->get(pos), std::move(text)));
} }
@@ -1094,22 +1090,13 @@ namespace nana
*/ */
index_pair index_cast(const index_pair& from, bool from_display_order) const index_pair index_cast(const index_pair& from, bool from_display_order) const
{ {
auto cat = get(from.cat); auto target = index_cast_noexcept(from, from_display_order);
if (from.item < cat->sorted.size()) if (target.empty())
{ throw std::out_of_range("listbox: invalid element position");
if (from_display_order) return target;
return index_pair{ from.cat, static_cast<size_type>(cat->sorted[from.item]) };
for (size_type i = 0; i < cat->sorted.size(); ++i)
{
if (from.item == cat->sorted[i])
return index_pair{ from.cat, i };
}
}
throw std::out_of_range("listbox: invalid item position");
} }
index_pair index_cast_noexcpt(const index_pair& from, bool from_display_order, const index_pair& default_value = index_pair{npos, npos}) const noexcept index_pair index_cast_noexcept(const index_pair& from, bool from_display_order, const index_pair& default_value = index_pair{npos, npos}) const noexcept
{ {
if (from.cat < categories_.size()) if (from.cat < categories_.size())
{ {
@@ -1677,11 +1664,19 @@ namespace nana
} }
/// return absolute positions, no relative to display /// return absolute positions, no relative to display
index_pairs pick_items(bool for_selection, bool find_first = false) const /**
* @param for_selection Indicates whether the selected items or checked items to be returned.
* @param find_first Indicates whether or not to return the first item which
* @param items_status a pointer refers to a bool object to receive the status whethe the picked items are all selected or all checked, in contrast to for_selection
*/
index_pairs pick_items(bool for_selection, bool find_first = false, bool * items_status = nullptr) const
{ {
index_pairs results; index_pairs results;
index_pair id; index_pair id;
if (items_status)
*items_status = true;
for (auto & cat : categories_) for (auto & cat : categories_)
{ {
id.item = 0; id.item = 0;
@@ -1689,6 +1684,9 @@ namespace nana
{ {
if (for_selection ? m.flags.selected : m.flags.checked) if (for_selection ? m.flags.selected : m.flags.checked)
{ {
if (items_status && *items_status)
*items_status = (for_selection ? m.flags.checked : m.flags.selected);
results.push_back(id); // absolute positions, no relative to display results.push_back(id); // absolute positions, no relative to display
if (find_first) if (find_first)
return results; return results;
@@ -1700,31 +1698,6 @@ namespace nana
return results; return results;
} }
/// return absolute positions, no relative to display
bool item_selected_all_checked(index_pairs& vec) const
{
index_pair id;
bool ck = true;
for (auto & cat : categories_)
{
id.item = 0;
for (auto & m : cat.items)
{
if (m.flags.selected)
{
vec.push_back(id); // absolute positions, no relative to display
ck &= m.flags.checked;
}
++id.item;
}
++id.cat;
}
//Just returns true when the all selected items are checked.
return ck;
}
///<Selects an item besides the current selected item in the display. ///<Selects an item besides the current selected item in the display.
/// we are moving in display, but the selection ocurre in abs position /// we are moving in display, but the selection ocurre in abs position
void move_select(bool upwards=true, bool unselect_previous=true, bool into_view=false) noexcept; void move_select(bool upwards=true, bool unselect_previous=true, bool into_view=false) noexcept;
@@ -2285,7 +2258,7 @@ namespace nana
int item_xpos(const nana::rectangle& r) const int item_xpos(const nana::rectangle& r) const
{ {
auto seq = header_seq(r.width); auto seq = ordered_columns(r.width);
if (seq.empty()) if (seq.empty())
return 0; return 0;
@@ -2484,7 +2457,7 @@ namespace nana
return true; return true;
} }
std::vector<size_type> header_seq(unsigned lister_w) const std::vector<size_type> ordered_columns(unsigned lister_w) const
{ {
std::vector<size_type> seqs; std::vector<size_type> seqs;
int x = -content_view->origin().x; int x = -content_view->origin().x;
@@ -2496,10 +2469,12 @@ namespace nana
x += col.width_px; x += col.width_px;
if (x > 0) if (x > 0)
seqs.push_back(col.index); {
if (x >= static_cast<int>(lister_w)) if (x >= static_cast<int>(lister_w))
break; break;
seqs.push_back(col.index);
}
} }
return seqs; return seqs;
} }
@@ -2965,53 +2940,6 @@ namespace nana
std::vector<std::pair<index_type, inline_pane*>> panes_; std::vector<std::pair<index_type, inline_pane*>> panes_;
}; };
#if 0
void es_lister::scroll(const index_pair& abs_pos, bool to_bottom) //deprecated
{
auto& cat = *get(abs_pos.cat);
if ((abs_pos.item != nana::npos) && (abs_pos.item >= cat.items.size()))
throw std::invalid_argument("listbox: invalid pos to scroll");
if (!cat.expand)
{
this->expand(abs_pos.cat, true);
ess_->calc_content_size();
}
else if (!ess_->auto_draw)
{
//force a update of content size and scrollbar status when auto_draw is false to make
//sure that the scroll function works fine.
ess_->calc_content_size();
}
auto origin = ess_->content_view->origin();
origin.y = 0;
auto off = this->distance(this->first(), this->index_cast(abs_pos, false)) * ess_->item_height();
auto screen_px = ess_->content_view->view_area().height;
if (to_bottom)
{
off += ess_->item_height();
if (off >= screen_px)
origin.y = static_cast<int>(off - screen_px);
}
else
{
auto last_off = this->distance(this->first(), this->last()) * ess_->item_height();
if (last_off - off >= screen_px)
origin.y = static_cast<int>(off);
else if (last_off >= screen_px)
origin.y = static_cast<int>(last_off - screen_px);
}
if(ess_->content_view->move_origin(origin - ess_->content_view->origin()))
ess_->content_view->sync(false);
}
#endif
void es_lister::scroll_into_view(const index_pair& abs_pos, view_action vw_act) void es_lister::scroll_into_view(const index_pair& abs_pos, view_action vw_act)
{ {
auto& cat = *get(abs_pos.cat); auto& cat = *get(abs_pos.cat);
@@ -3088,7 +3016,7 @@ namespace nana
void es_lister::move_select(bool upwards, bool unselect_previous, bool into_view) noexcept void es_lister::move_select(bool upwards, bool unselect_previous, bool into_view) noexcept
{ {
auto next_selected_dpl = index_cast_noexcpt(latest_selected_abs, false); //convert absolute position to display position auto next_selected_dpl = index_cast_noexcept(latest_selected_abs, false); //convert absolute position to display position
if (next_selected_dpl.empty()) // has no cat ? (cat == npos) => beging from first cat if (next_selected_dpl.empty()) // has no cat ? (cat == npos) => beging from first cat
{ {
@@ -3274,15 +3202,13 @@ namespace nana
{ {
if(col.visible_state) if(col.visible_state)
{ {
auto col_pixels = static_cast<int>(col.width_px); if ((static_cast<int>(col.width_px) < x + static_cast<int>(essence_->scheme_ptr->header_splitter_area_before))
&& (x < static_cast<int>(col.width_px) + static_cast<int>(essence_->scheme_ptr->header_splitter_area_after)))
if ((col_pixels < x + static_cast<int>(essence_->scheme_ptr->header_splitter_area_before))
&& (x < col_pixels + static_cast<int>(essence_->scheme_ptr->header_splitter_area_after)))
{ {
grabs_.splitter = col.index; // original index grabs_.splitter = col.index; // original index
return true; return true;
} }
x -= col_pixels; x -= static_cast<int>(col.width_px);
} }
} }
} }
@@ -3637,12 +3563,12 @@ namespace nana
hoverred_pos = lister.advance(first_disp, static_cast<int>(ptr_where.second)); hoverred_pos = lister.advance(first_disp, static_cast<int>(ptr_where.second));
} }
auto subitems = essence_->header_seq(rect.width); auto const columns = essence_->ordered_columns(rect.width);
if (subitems.empty()) if (columns.empty())
return; return;
int txtoff = essence_->scheme_ptr->item_height_ex / 2; auto const txtoff = static_cast<int>(essence_->scheme_ptr->item_height_ex) / 2;
auto i_categ = lister.get(first_disp.cat); auto i_categ = lister.get(first_disp.cat);
@@ -3672,7 +3598,7 @@ namespace nana
auto item_pos = lister.index_cast(index_pair{ idx.cat, offs }, true); //convert display position to absolute position auto item_pos = lister.index_cast(index_pair{ idx.cat, offs }, true); //convert display position to absolute position
_m_draw_item(*i_categ, item_pos, item_coord, txtoff, header_w, rect, subitems, bgcolor, fgcolor, _m_draw_item(*i_categ, item_pos, item_coord, txtoff, header_w, rect, columns, bgcolor, fgcolor,
(hoverred_pos == idx ? item_state::highlighted : item_state::normal) (hoverred_pos == idx ? item_state::highlighted : item_state::normal)
); );
@@ -3706,7 +3632,7 @@ namespace nana
auto item_pos = lister.index_cast(index_pair{ idx.cat, pos }, true); //convert display position to absolute position auto item_pos = lister.index_cast(index_pair{ idx.cat, pos }, true); //convert display position to absolute position
_m_draw_item(*i_categ, item_pos, item_coord, txtoff, header_w, rect, subitems, bgcolor, fgcolor, _m_draw_item(*i_categ, item_pos, item_coord, txtoff, header_w, rect, columns, bgcolor, fgcolor,
(idx == hoverred_pos ? item_state::highlighted : item_state::normal) (idx == hoverred_pos ? item_state::highlighted : item_state::normal)
); );
@@ -3729,7 +3655,7 @@ namespace nana
} }
//Draw mouse selection //Draw mouse selection
//Check if the mouse selection box is present. //Check if the mouse selection box presents.
if (essence_->mouse_selection.begin_position != essence_->mouse_selection.end_position) if (essence_->mouse_selection.begin_position != essence_->mouse_selection.end_position)
{ {
point box_position{ point box_position{
@@ -4297,7 +4223,7 @@ namespace nana
{ {
auto * item_ptr = (item_pos.is_category() ? nullptr : &lister.at(item_pos)); auto * item_ptr = (item_pos.is_category() ? nullptr : &lister.at(item_pos));
const auto abs_item_pos = lister.index_cast_noexcpt(item_pos, true, item_pos); //convert display position to absolute position const auto abs_item_pos = lister.index_cast_noexcept(item_pos, true, item_pos); //convert display position to absolute position
if(ptr_where.first == parts::list) if(ptr_where.first == parts::list)
{ {
@@ -4549,10 +4475,11 @@ namespace nana
break; break;
case L' ': case L' ':
{ {
index_pairs s; bool items_checked{ false };
bool ck = ! list.item_selected_all_checked(s); auto items = list.pick_items(true, false, &items_checked);
for(auto i : s) items_checked = !items_checked;
item_proxy(essence_, i).check(ck); for (auto i : items)
item_proxy(essence_, i).check(items_checked);
} }
break; break;
case keyboard::os_pageup : case keyboard::os_pageup :
@@ -4601,10 +4528,7 @@ namespace nana
target_idx = list.last(); target_idx = list.last();
origin.y = static_cast<int>((list.distance(list.first(), target_idx) + 1) * item_px); origin.y = static_cast<int>((list.distance(list.first(), target_idx) + 1) * item_px);
if (origin.y >= static_cast<int>(screen_bottom - screen_top)) origin.y = (std::max)(origin.y - static_cast<int>(screen_bottom - screen_top), 0);
origin.y -= static_cast<int>(screen_bottom - screen_top);
else
origin.y = 0;
} }
essence_->content_view->move_origin(origin - essence_->content_view->origin()); essence_->content_view->move_origin(origin - essence_->content_view->origin());
@@ -5514,7 +5438,7 @@ namespace nana
{ {
internal_scope_guard lock; internal_scope_guard lock;
auto & ess = _m_ess(); auto & ess = _m_ess();
auto new_cat_ptr = ess.lister.create_cat(to_nstring(std::move(s))); auto new_cat_ptr = ess.lister.create_category(to_nstring(std::move(s)));
ess.update(); ess.update();
return cat_proxy{ &ess, new_cat_ptr }; return cat_proxy{ &ess, new_cat_ptr };
@@ -5524,7 +5448,7 @@ namespace nana
{ {
internal_scope_guard lock; internal_scope_guard lock;
auto & ess = _m_ess(); auto & ess = _m_ess();
auto new_cat_ptr = ess.lister.create_cat(to_nstring(std::move(s))); auto new_cat_ptr = ess.lister.create_category(to_nstring(std::move(s)));
ess.update(); ess.update();
return cat_proxy{ &ess, new_cat_ptr }; return cat_proxy{ &ess, new_cat_ptr };
} }
@@ -5535,7 +5459,7 @@ namespace nana
auto & ess = _m_ess(); auto & ess = _m_ess();
for (auto & arg : categories) for (auto & arg : categories)
ess.lister.create_cat(native_string_type(to_nstring(arg))); ess.lister.create_category(native_string_type(to_nstring(arg)));
ess.update(); ess.update();
} }
@@ -5545,7 +5469,7 @@ namespace nana
auto & ess = _m_ess(); auto & ess = _m_ess();
for (auto & arg : categories) for (auto & arg : categories)
ess.lister.create_cat(native_string_type(to_nstring(arg))); ess.lister.create_category(native_string_type(to_nstring(arg)));
ess.update(); ess.update();
} }
@@ -5562,7 +5486,7 @@ namespace nana
{ {
internal_scope_guard lock; internal_scope_guard lock;
auto & ess = _m_ess(); auto & ess = _m_ess();
auto new_cat_ptr = ess.lister.create_cat(cat.position(), to_nstring(std::move(str))); auto new_cat_ptr = ess.lister.create_category(to_nstring(std::move(str)), cat.position());
return cat_proxy{ &ess, new_cat_ptr }; return cat_proxy{ &ess, new_cat_ptr };
} }
@@ -5570,7 +5494,7 @@ namespace nana
{ {
internal_scope_guard lock; internal_scope_guard lock;
auto & ess = _m_ess(); auto & ess = _m_ess();
auto new_cat_ptr = ess.lister.create_cat(cat.position(), to_nstring(std::move(str))); auto new_cat_ptr = ess.lister.create_category(to_nstring(std::move(str)), cat.position());
return cat_proxy{ &ess, new_cat_ptr }; return cat_proxy{ &ess, new_cat_ptr };
} }
@@ -5915,7 +5839,6 @@ namespace nana
return *this; return *this;
} }
drawerbase::listbox::essence & listbox::_m_ess() const drawerbase::listbox::essence & listbox::_m_ess() const
{ {
return get_drawer_trigger().ess(); return get_drawer_trigger().ess();
@@ -5945,11 +5868,11 @@ namespace nana
if (ess.lister.enable_ordered()) if (ess.lister.enable_ordered())
{ {
cat = ess.lister.create_cat(ptr); cat = ess.lister.create_category(ptr);
} }
else else
{ {
cat = ess.lister.create_cat(native_string_type{}); cat = ess.lister.create_category(native_string_type{});
cat->key_ptr = ptr; cat->key_ptr = ptr;
} }
ess.update(); ess.update();
@@ -5970,5 +5893,11 @@ namespace nana
} }
} }
} }
std::shared_ptr<scroll_operation_interface> listbox::_m_scroll_operation()
{
internal_scope_guard lock;
return _m_ess().content_view->scroll_operation();
}
//end class listbox //end class listbox
}//end namespace nana }//end namespace nana

View File

@@ -1,7 +1,7 @@
/* /*
* A Content View Implementation * A Content View Implementation
* Nana C++ Library(http://www.nanapro.org) * Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2017 Jinhao(cnjinhao@hotmail.com) * Copyright(C) 2017-2018 Jinhao(cnjinhao@hotmail.com)
* *
* Distributed under the Boost Software License, Version 1.0. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@@ -19,6 +19,39 @@ namespace nana {
namespace widgets { namespace widgets {
namespace skeletons namespace skeletons
{ {
struct cv_scroll_rep
{
content_view::scrolls enabled_scrolls{ content_view::scrolls::both };
nana::scroll<false> horz;
nana::scroll<true> vert;
scroll_interface* scroll(arg_wheel::wheel whl)
{
if (arg_wheel::wheel::horizontal == whl)
return &horz;
else if (arg_wheel::wheel::vertical == whl)
return &vert;
return nullptr;
}
};
class scroll_operation
: public scroll_operation_interface
{
public:
scroll_operation(std::shared_ptr<cv_scroll_rep>& impl)
: cv_scroll_(impl)
{
}
private:
bool visible(bool vert) const override
{
return !(vert ? cv_scroll_->vert.empty() : cv_scroll_->horz.empty());
}
private:
std::shared_ptr<cv_scroll_rep> const cv_scroll_;
};
struct content_view::implementation struct content_view::implementation
{ {
content_view& view; content_view& view;
@@ -35,9 +68,13 @@ namespace nana {
bool drag_started{ false }; bool drag_started{ false };
point origin; point origin;
scrolls enabled_scrolls{scrolls::both}; /*
scrolls enabled_scrolls{scrolls::both}; //deprecated
nana::scroll<false> horz; nana::scroll<false> horz;
nana::scroll<true> vert; nana::scroll<true> vert;
*/
std::shared_ptr<cv_scroll_rep> cv_scroll;
timer tmr; timer tmr;
@@ -50,9 +87,11 @@ namespace nana {
implementation(content_view& v, window handle) : implementation(content_view& v, window handle) :
view(v), view(v),
window_handle(handle) window_handle(handle),
cv_scroll(std::make_shared<cv_scroll_rep>())
{ {
API::events(handle).mouse_wheel.connect_unignorable([this](const arg_wheel& arg) { API::events(handle).mouse_wheel.connect_unignorable([this](const arg_wheel& arg) {
#if 0
scroll_interface * scroll = nullptr; scroll_interface * scroll = nullptr;
switch (arg.which) switch (arg.which)
{ {
@@ -66,6 +105,11 @@ namespace nana {
//Other button is not unsupported. //Other button is not unsupported.
return; return;
} }
#else
auto const scroll = cv_scroll->scroll(arg.which);
if (nullptr == scroll)
return;
#endif
if (!API::empty_window(arg.window_handle)) if (!API::empty_window(arg.window_handle))
{ {
@@ -159,11 +203,11 @@ namespace nana {
auto speed_horz = 0; auto speed_horz = 0;
if (skew.x) if (skew.x)
speed_horz = skew.x / (std::max)(1, static_cast<int>(horz.step())) + (skew.x < 0 ? -1 : 1); speed_horz = skew.x / (std::max)(1, static_cast<int>(cv_scroll->horz.step())) + (skew.x < 0 ? -1 : 1);
auto speed_vert = 0; auto speed_vert = 0;
if (skew.y) if (skew.y)
speed_vert = skew.y / (std::max)(1, static_cast<int>(vert.step())) + (skew.y < 0 ? -1 : 1); speed_vert = skew.y / (std::max)(1, static_cast<int>(cv_scroll->vert.step())) + (skew.y < 0 ? -1 : 1);
speed_horz = (std::min)(5, (std::max)(speed_horz, -5)); speed_horz = (std::min)(5, (std::max)(speed_horz, -5));
speed_vert = (std::min)(5, (std::max)(speed_vert, -5)); speed_vert = (std::min)(5, (std::max)(speed_vert, -5));
@@ -180,10 +224,10 @@ namespace nana {
//event hander for scrollbars //event hander for scrollbars
auto event_fn = [this](const arg_scroll& arg) auto event_fn = [this](const arg_scroll& arg)
{ {
if (arg.window_handle == this->vert.handle()) if (arg.window_handle == cv_scroll->vert.handle())
origin.y = static_cast<int>(this->vert.value()); origin.y = static_cast<int>(cv_scroll->vert.value());
else else
origin.x = static_cast<int>(this->horz.value()); origin.x = static_cast<int>(cv_scroll->horz.value());
if (this->events.scrolled) if (this->events.scrolled)
this->events.scrolled(); this->events.scrolled();
@@ -194,33 +238,33 @@ namespace nana {
this->passive = passive; this->passive = passive;
bool const vert_allowed = (enabled_scrolls == scrolls::vert || enabled_scrolls == scrolls::both); bool const vert_allowed = (cv_scroll->enabled_scrolls == scrolls::vert || cv_scroll->enabled_scrolls == scrolls::both);
bool const horz_allowed = (enabled_scrolls == scrolls::horz || enabled_scrolls == scrolls::both); bool const horz_allowed = (cv_scroll->enabled_scrolls == scrolls::horz || cv_scroll->enabled_scrolls == scrolls::both);
if ((imd_area.width != disp_area.width) && vert_allowed) if ((imd_area.width != disp_area.width) && vert_allowed)
{ {
if (vert.empty()) if (cv_scroll->vert.empty())
{ {
vert.create(window_handle); cv_scroll->vert.create(window_handle);
vert.events().value_changed.connect_unignorable(event_fn); cv_scroll->vert.events().value_changed.connect_unignorable(event_fn);
API::take_active(vert, false, window_handle); API::take_active(cv_scroll->vert, false, window_handle);
this->passive = false; this->passive = false;
} }
vert.move({ cv_scroll->vert.move({
disp_area.x + static_cast<int>(imd_area.width) + skew_vert.x, disp_area.x + static_cast<int>(imd_area.width) + skew_vert.x,
disp_area.y + skew_vert.y, disp_area.y + skew_vert.y,
space(), space(),
imd_area.height + extra_px.height imd_area.height + extra_px.height
}); });
vert.amount(content_size.height); cv_scroll->vert.amount(content_size.height);
vert.range(imd_area.height); cv_scroll->vert.range(imd_area.height);
vert.value(origin.y); cv_scroll->vert.value(origin.y);
} }
else else
{ {
vert.close(); cv_scroll->vert.close();
//If vert is allowed, it indicates the vertical origin is not moved //If vert is allowed, it indicates the vertical origin is not moved
//Make sure the v origin is zero //Make sure the v origin is zero
@@ -230,28 +274,28 @@ namespace nana {
if ((imd_area.height != disp_area.height) && horz_allowed) if ((imd_area.height != disp_area.height) && horz_allowed)
{ {
if (horz.empty()) if (cv_scroll->horz.empty())
{ {
horz.create(window_handle); cv_scroll->horz.create(window_handle);
horz.events().value_changed.connect_unignorable(event_fn); cv_scroll->horz.events().value_changed.connect_unignorable(event_fn);
API::take_active(horz, false, window_handle); API::take_active(cv_scroll->horz, false, window_handle);
this->passive = false; this->passive = false;
} }
horz.move({ cv_scroll->horz.move({
disp_area.x + skew_horz.x, disp_area.x + skew_horz.x,
disp_area.y + static_cast<int>(imd_area.height) + skew_horz.y, disp_area.y + static_cast<int>(imd_area.height) + skew_horz.y,
imd_area.width + extra_px.width, imd_area.width + extra_px.width,
space() space()
}); });
horz.amount(content_size.width); cv_scroll->horz.amount(content_size.width);
horz.range(imd_area.width); cv_scroll->horz.range(imd_area.width);
horz.value(origin.x); cv_scroll->horz.value(origin.x);
} }
else else
{ {
horz.close(); cv_scroll->horz.close();
//If horz is allowed, it indicates the horzontal origin is not moved //If horz is allowed, it indicates the horzontal origin is not moved
//Make sure the x origin is zero //Make sure the x origin is zero
if (horz_allowed) if (horz_allowed)
@@ -279,20 +323,25 @@ namespace nana {
bool content_view::enable_scrolls(scrolls which) bool content_view::enable_scrolls(scrolls which)
{ {
if (impl_->enabled_scrolls == which) if (impl_->cv_scroll->enabled_scrolls == which)
return false; return false;
impl_->enabled_scrolls = which; impl_->cv_scroll->enabled_scrolls = which;
impl_->size_changed(false); impl_->size_changed(false);
return true; return true;
} }
std::shared_ptr<scroll_operation_interface> content_view::scroll_operation() const
{
return std::make_shared<skeletons::scroll_operation>(impl_->cv_scroll);
}
void content_view::step(unsigned step_value, bool horz) void content_view::step(unsigned step_value, bool horz)
{ {
if (horz) if (horz)
impl_->horz.step(step_value); impl_->cv_scroll->horz.step(step_value);
else else
impl_->vert.step(step_value); impl_->cv_scroll->vert.step(step_value);
} }
bool content_view::scroll(bool forwards, bool horz) bool content_view::scroll(bool forwards, bool horz)
@@ -306,17 +355,17 @@ namespace nana {
} }
if (horz) if (horz)
return impl_->horz.make_step(forwards, speed); return impl_->cv_scroll->horz.make_step(forwards, speed);
return impl_->vert.make_step(forwards, speed); return impl_->cv_scroll->vert.make_step(forwards, speed);
} }
bool content_view::turn_page(bool forwards, bool horz) bool content_view::turn_page(bool forwards, bool horz)
{ {
if (horz) if (horz)
return impl_->horz.make_page_scroll(forwards); return impl_->cv_scroll->horz.make_page_scroll(forwards);
else else
return impl_->vert.make_page_scroll(forwards); return impl_->cv_scroll->vert.make_page_scroll(forwards);
} }
void content_view::disp_area(const rectangle& da, const point& skew_horz, const point& skew_vert, const size& extra_px, bool try_update) void content_view::disp_area(const rectangle& da, const point& skew_horz, const point& skew_vert, const size& extra_px, bool try_update)
@@ -404,7 +453,7 @@ namespace nana {
void content_view::draw_corner(graph_reference graph) void content_view::draw_corner(graph_reference graph)
{ {
auto r = corner(); auto r = corner();
if ((!r.empty()) && (scrolls::both == impl_->enabled_scrolls)) if ((!r.empty()) && (scrolls::both == impl_->cv_scroll->enabled_scrolls))
graph.rectangle(r, true, colors::button_face); graph.rectangle(r, true, colors::button_face);
} }
@@ -415,8 +464,8 @@ namespace nana {
rectangle content_view::view_area(const size& alt_content_size) const rectangle content_view::view_area(const size& alt_content_size) const
{ {
bool const vert_allowed = (impl_->enabled_scrolls == scrolls::vert || impl_->enabled_scrolls == scrolls::both); bool const vert_allowed = (impl_->cv_scroll->enabled_scrolls == scrolls::vert || impl_->cv_scroll->enabled_scrolls == scrolls::both);
bool const horz_allowed = (impl_->enabled_scrolls == scrolls::horz || impl_->enabled_scrolls == scrolls::both); bool const horz_allowed = (impl_->cv_scroll->enabled_scrolls == scrolls::horz || impl_->cv_scroll->enabled_scrolls == scrolls::both);
unsigned extra_horz = (horz_allowed && (impl_->disp_area.width < alt_content_size.width) ? space() : 0); unsigned extra_horz = (horz_allowed && (impl_->disp_area.width < alt_content_size.width) ? space() : 0);
unsigned extra_vert = (vert_allowed && (impl_->disp_area.height < alt_content_size.height + extra_horz) ? space() : 0); unsigned extra_vert = (vert_allowed && (impl_->disp_area.height < alt_content_size.height + extra_horz) ? space() : 0);
@@ -435,13 +484,13 @@ namespace nana {
unsigned content_view::extra_space(bool horz) const unsigned content_view::extra_space(bool horz) const
{ {
return ((horz ? impl_->horz.empty() : impl_->vert.empty()) ? 0 : space()); return ((horz ? impl_->cv_scroll->horz.empty() : impl_->cv_scroll->vert.empty()) ? 0 : space());
} }
void content_view::change_position(int pos, bool aligned, bool horz) void content_view::change_position(int pos, bool aligned, bool horz)
{ {
if (aligned) if (aligned)
pos -= (pos % static_cast<int>(horz ? impl_->horz.step() : impl_->vert.step())); pos -= (pos % static_cast<int>(horz ? impl_->cv_scroll->horz.step() : impl_->cv_scroll->vert.step()));
auto imd_size = this->view_area(); auto imd_size = this->view_area();
@@ -490,8 +539,8 @@ namespace nana {
void content_view::sync(bool passive) void content_view::sync(bool passive)
{ {
impl_->passive = passive; impl_->passive = passive;
impl_->horz.value(impl_->origin.x); impl_->cv_scroll->horz.value(impl_->origin.x);
impl_->vert.value(impl_->origin.y); impl_->cv_scroll->vert.value(impl_->origin.y);
impl_->passive = true; impl_->passive = true;
} }
@@ -520,15 +569,15 @@ namespace nana {
impl_->origin.y = 0; impl_->origin.y = 0;
bool changed = false; bool changed = false;
if (!impl_->horz.empty() && (static_cast<long long>(impl_->horz.value()) != impl_->origin.x)) if (!impl_->cv_scroll->horz.empty() && (static_cast<long long>(impl_->cv_scroll->horz.value()) != impl_->origin.x))
{ {
impl_->horz.value(impl_->origin.x); impl_->cv_scroll->horz.value(impl_->origin.x);
changed = true; changed = true;
} }
if ((!impl_->vert.empty()) && (static_cast<long long>(impl_->vert.value()) != impl_->origin.y)) if ((!impl_->cv_scroll->vert.empty()) && (static_cast<long long>(impl_->cv_scroll->vert.value()) != impl_->origin.y))
{ {
impl_->vert.value(impl_->origin.y); impl_->cv_scroll->vert.value(impl_->origin.y);
changed = true; changed = true;
} }

View File

@@ -1,7 +1,7 @@
/* /*
* A Content View Implementation * A Content View Implementation
* Nana C++ Library(http://www.nanapro.org) * Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2017 Jinhao(cnjinhao@hotmail.com) * Copyright(C) 2017-2018 Jinhao(cnjinhao@hotmail.com)
* *
* Distributed under the Boost Software License, Version 1.0. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@@ -16,6 +16,7 @@
#include <nana/gui/basis.hpp> #include <nana/gui/basis.hpp>
#include <functional> #include <functional>
#include <memory>
namespace nana namespace nana
{ {
@@ -58,6 +59,8 @@ namespace skeletons
bool enable_scrolls(scrolls which); bool enable_scrolls(scrolls which);
std::shared_ptr<scroll_operation_interface> scroll_operation() const;
void step(unsigned step_value, bool horz); void step(unsigned step_value, bool horz);
bool scroll(bool forwards, bool horz); bool scroll(bool forwards, bool horz);
bool turn_page(bool forwards, bool horz); bool turn_page(bool forwards, bool horz);

View File

@@ -1,7 +1,7 @@
/* /*
* A text editor implementation * A text editor implementation
* Nana C++ Library(http://www.nanapro.org) * Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
* *
* Distributed under the Boost Software License, Version 1.0. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@@ -1954,6 +1954,11 @@ namespace nana{ namespace widgets
return impl_->capacities.behavior->take_lines(); return impl_->capacities.behavior->take_lines();
} }
std::shared_ptr<scroll_operation_interface> text_editor::scroll_operation() const
{
return impl_->cview->scroll_operation();
}
void text_editor::draw_corner() void text_editor::draw_corner()
{ {
impl_->cview->draw_corner(graph_); impl_->cview->draw_corner(graph_);

View File

@@ -1,7 +1,7 @@
/* /*
* A Textbox Implementation * A Textbox Implementation
* Nana C++ Library(http://www.nanapro.org) * Nana C++ Library(http://www.nanapro.org)
* Copyright(C) 2003-2017 Jinhao(cnjinhao@hotmail.com) * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
* *
* Distributed under the Boost Software License, Version 1.0. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@@ -816,6 +816,16 @@ namespace drawerbase {
if(editor) if(editor)
editor->reset_caret_pixels(); editor->reset_caret_pixels();
} }
std::shared_ptr<scroll_operation_interface> textbox::_m_scroll_operation() const
{
internal_scope_guard lock;
auto editor = get_drawer_trigger().editor();
if (editor)
return editor->scroll_operation();
return {};
}
//end class textbox //end class textbox
}//end namespace nana }//end namespace nana

View File

@@ -29,6 +29,25 @@ namespace nana
{ {
using node_type = trigger::node_type; using node_type = trigger::node_type;
class exclusive_scroll_operation
: public scroll_operation_interface
{
public:
exclusive_scroll_operation(std::shared_ptr<nana::scroll<true>>& scroll_wdg)
:scroll_(scroll_wdg)
{}
bool visible(bool vert) const override
{
if (vert)
return !scroll_->empty();
return false;
}
private:
std::shared_ptr<nana::scroll<true>> scroll_;
};
bool no_sensitive_compare(const std::string& text, const char *pattern, std::size_t len) bool no_sensitive_compare(const std::string& text, const char *pattern, std::size_t len)
{ {
if(len <= text.length()) if(len <= text.length())
@@ -214,7 +233,7 @@ namespace nana
struct shape_tag struct shape_tag
{ {
nana::upoint border; nana::upoint border;
nana::scroll<true> scroll; std::shared_ptr<nana::scroll<true>> scroll;
mutable std::map<std::string, node_image_tag> image_table; mutable std::map<std::string, node_image_tag> image_table;
@@ -261,6 +280,7 @@ namespace nana
shape.first = nullptr; shape.first = nullptr;
shape.indent_pixels = 10; shape.indent_pixels = 10;
shape.offset_x = 0; shape.offset_x = 0;
shape.scroll = std::make_shared<nana::scroll<true>>();
attr.auto_draw = true; attr.auto_draw = true;
@@ -598,7 +618,7 @@ namespace nana
std::size_t max_allow = max_allowed(); std::size_t max_allow = max_allowed();
std::size_t visual_items = visual_item_size(); std::size_t visual_items = visual_item_size();
auto & scroll = shape.scroll; auto & scroll = *shape.scroll;
if(visual_items <= max_allow) if(visual_items <= max_allow)
{ {
if(!scroll.empty()) if(!scroll.empty())
@@ -618,7 +638,7 @@ namespace nana
adjust.scroll_timestamp = nana::system::timestamp(); adjust.scroll_timestamp = nana::system::timestamp();
adjust.timer.start(); adjust.timer.start();
shape.first = attr.tree_cont.advance_if(nullptr, shape.scroll.value(), pred_allow_child{}); shape.first = attr.tree_cont.advance_if(nullptr, shape.scroll->value(), pred_allow_child{});
draw(false, false, true); draw(false, false, true);
}); });
} }
@@ -641,7 +661,7 @@ namespace nana
if(!data.graph) if(!data.graph)
return 0; return 0;
return static_cast<int>(data.graph->width() - (shape.scroll.empty() ? 0 : shape.scroll.size().width)); return static_cast<int>(data.graph->width() - (shape.scroll->empty() ? 0 : shape.scroll->size().width));
} }
unsigned node_w_pixels(const node_type *node) const unsigned node_w_pixels(const node_type *node) const
@@ -1901,7 +1921,7 @@ namespace nana
void trigger::mouse_wheel(graph_reference, const arg_wheel& arg) void trigger::mouse_wheel(graph_reference, const arg_wheel& arg)
{ {
auto & scroll = impl_->shape.scroll; auto & scroll = *impl_->shape.scroll;
if (scroll.empty()) if (scroll.empty())
return; return;
@@ -1935,10 +1955,10 @@ namespace nana
impl_->draw(false); impl_->draw(false);
API::dev::lazy_refresh(); API::dev::lazy_refresh();
impl_->show_scroll(); impl_->show_scroll();
if(!impl_->shape.scroll.empty()) if(!impl_->shape.scroll->empty())
{ {
nana::size s = impl_->data.graph->size(); nana::size s = impl_->data.graph->size();
impl_->shape.scroll.move(rectangle{ static_cast<int>(s.width) - 16, 0, 16, s.height }); impl_->shape.scroll->move(rectangle{ static_cast<int>(s.width) - 16, 0, 16, s.height });
} }
} }
@@ -2213,5 +2233,11 @@ namespace nana
{ {
return item_proxy(const_cast<drawer_trigger_t*>(&get_drawer_trigger()), get_drawer_trigger().selected()); return item_proxy(const_cast<drawer_trigger_t*>(&get_drawer_trigger()), get_drawer_trigger().selected());
} }
std::shared_ptr<scroll_operation_interface> treebox::_m_scroll_operation() const
{
internal_scope_guard lock;
return std::make_shared<drawerbase::treebox::exclusive_scroll_operation>(get_drawer_trigger().impl()->shape.scroll);
}
//end class treebox //end class treebox
}//end namespace nana }//end namespace nana

View File

@@ -1,6 +1,6 @@
/* /*
* The fundamental widget class implementation * The fundamental widget class implementation
* Copyright(C) 2003-2016 Jinhao(cnjinhao@hotmail.com) * Copyright(C) 2003-2018 Jinhao(cnjinhao@hotmail.com)
* *
* Distributed under the Boost Software License, Version 1.0. * Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at * (See accompanying file LICENSE_1_0.txt or copy at
@@ -158,6 +158,11 @@ namespace nana
return (API::focus_window() == handle()); return (API::focus_window() == handle());
} }
std::shared_ptr<scroll_operation_interface> widget::scroll_operation()
{
return _m_scroll_operation();
}
void widget::show() void widget::show()
{ {
_m_show(true); _m_show(true);
@@ -317,6 +322,11 @@ namespace nana
API::window_enabled(handle(), value); API::window_enabled(handle(), value);
} }
std::shared_ptr<scroll_operation_interface> widget::_m_scroll_operation()
{
return {};
}
bool widget::_m_show(bool visible) bool widget::_m_show(bool visible)
{ {
API::show_window(handle(), visible); API::show_window(handle(), visible);